本文介绍了为什么 GLES20.glCreateShader 总是返回 0?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 java 在 android 中制作 OpenGL ES 应用程序,但我遇到了一个主要问题:

I'm trying to make an OpenGL ES app in android using java and I have run in a major issue:

GLES20.glCreateShader(type)(类型为 GLES20.GL_VERTEX_SHADER 或 GLES20.GL_FRAGMENT_SHADER)总是返回 0.

GLES20.glCreateShader(type) (type beeing GLES20.GL_VERTEX_SHADER or GLES20.GL_FRAGMENT_SHADER) always returns 0.

我试过了:

  • 使用 GLES30 和 GLES31
  • 将 setEGLContextClientVersion 设置为 2 和 3
  • 在我代码的几乎所有类中进行调用,包括 laucher 类
  • 并且我已经检查过我的设备是否支持 OpenGl ES 3.1(并且出于某种原因它说:OpenGL ES 扩展包:3.2,我不明白,因为我认为它去了高达 3.1).
  • Using GLES30 and GLES31
  • setting setEGLContextClientVersion to 2 and to 3
  • making the call in pretty much all the classes of my code, including the laucher class
  • and I've checked that my device supports OpenGl ES 3.1 (and for some reason it says: OpenGL ES extention pack : 3.2 , which I don't understand, because I thaught that it went up to 3.1).

它总是,总是返回 0!

And it always, always returns 0!

我知道还有其他帖子提出了同样的问题,但似乎没有一个适合我的情况,其中一个仍然没有解决,但它已经 5 年了,没有更多的活动了.请帮帮我!

I know that there is other posts with the same question, but none of them seemed to suit my case, and one of them is still not solved, but it's 5 years old and there's no more activity on it. Please help me!

为了清楚起见,这是我的 glSurfaceView 的代码:

For clarity, here's the code of my glSurfaceView :

//Warning: I'm no where near finished
//and cleanup needs to be made once I get it working.
//If something looks weird or makes no sense, it's part of debugging or testing

public class renderer implements GLSurfaceView.Renderer{

    private Object obj;
    public StaticShader shader;
    private Object ball;

    private int bytePerFloat = 4;
    private int stride = 3*bytePerFloat; //#of elements * bpf

    private int positionOffset = 0;
    private int positionSize = 3;

    //private int colorOffset = 3;
    //private int colorSize = 4;

    private ObjectLoader objectLoader;
    private AssetManager assets;
    private Context context;

    //The important part is from here...

    renderer(AssetManager a, Context b){
      assets = a;
      context = b;
    }

    public void onSurfaceCreated(GL10 gl, EGLConfig config){

        shader = new StaticShader(assets, context);

        float[] verts =
        {
            //x,y,z
            //r,g,b,a
            0.5f,0.5f,0.0f,

            0.5f,-0.5f,0.0f,

            -0.5f,-0.5f,0.0f,

            -0.5f,0.5f,0.0f
        };

        int[] indices = {
          0,1,3,
          3,1,2
        };

        //obj = new Object(verts,indices,shader,bytePerFloat);
        //ball = objectLoader.LoadFromFile("ball.obj",shader, bytePerFloat);
    }

    //... To here

    public void onSurfaceChanged(GL10 gl, int width, int height){
        GLES20.glViewport(0,0,width,height);
    }

    public void onDrawFrame(GL10 gl){
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        if(shader.isCompiled && shader.hasFoundFile && shader.canReadFile){
            GLES20.glClearColor(0.0f,1.0f,0.0f,1.0f);
        }else{
            GLES20.glClearColor(1.0f,0.0f,0.0f,1.0f);
        }
        //render(obj);
        //render(ball);
    }

    private void render(Object object){
      try{
        object.getShader().start();

        GLES30.glBindVertexArray(object.getVaoID());
        GLES30.glEnableVertexAttribArray(0);

        GLES30.glDrawElements(GLES20.GL_TRIANGLES, object.getVertCount(), GLES30.GL_UNSIGNED_INT,0);

        GLES30.glDisableVertexAttribArray(0);
        GLES30.glBindVertexArray(0);

        object.getShader().stop();
      }catch(Exception e){

      }
    }
}

StaticShader 目前基本上实现了 ShaderProgram:

StaticShader basically implements ShaderProgram for now:

public abstract class ShaderProgram {

  private int programID;
  private int vertexShaderID;
  private int fragmentShaderID;

  public boolean hasFoundFile = true;
  public boolean isCompiled = true;
  public boolean canReadFile = true;

  public ShaderProgram (AssetManager assets, Context context, String vertexFile, String fragmentFile){

    //int shdID = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
    //Toast.makeText(context,Integer.toString(shdID),Toast.LENGTH_LONG).show();
    //Toast.makeText(context,EGL14.eglGetCurrentContext().toString(),Toast.LENGTH_LONG).show();

    //ShaderID = loadShader(assets, context, vertexFile, GLES20.GL_VERTEX_SHADER);
    //fragmentShaderID = loadShader(assets,context, fragmentFile, GLES20.GL_FRAGMENT_SHADER);

    programID = GLES20.glCreateProgram();
    GLES20.glAttachShader(programID, vertexShaderID);
    GLES20.glAttachShader(programID, fragmentShaderID);
    GLES20.glLinkProgram(programID);
    GLES20.glValidateProgram(programID);
  }

  public void start(){
    GLES20.glUseProgram(programID);
  }

  public void stop(){
    GLES20.glUseProgram(0);
  }

  protected abstract void bindAttributes();

  protected void bindAttribute(int attribute, String variableName){
    GLES20.glBindAttribLocation(programID, attribute, variableName);
  }

  private int loadShader(AssetManager assets, Context context,String fileName, int type){
    int shaderID = 0;
    try{
      InputStream file = assets.open(fileName);
      Scanner scan = new Scanner(file);
      String code = new String();
      while(scan.hasNext()){
        code = new String(code + scan.nextLine() + "/n");
      }

      shaderID = GLES20.glCreateShader(type);
      //GLES20.glShaderSource(shaderID, code);
      //Toast.makeText(context,Integer.toString(shaderID),Toast.LENGTH_LONG).show();
      //GLES20.glCompileShader(shaderID);
      int[] compileStatus = new int[1];
      GLES20.glGetShaderiv(shaderID,GLES20.GL_COMPILE_STATUS,compileStatus,0);
      if(compileStatus[0] == 0){
        //Toast.makeText(context,GLES20.glGetShaderInfoLog(),Toast.LENGTH_LONG).show();
        GLES20.glDeleteShader(shaderID);
        isCompiled = false;
      }
    }catch(FileNotFoundException e){
      hasFoundFile = false;
    }catch(IOException e){
      canReadFile = false;
    }catch(Exception e){
      isCompiled = false;
    }


    return shaderID;

  }
}

这是启动器类:

public class MainActivity extends Activity {

    private renderer surface;
    private GLSurfaceView surfaceView;
    private int STORAGE_PERMISSION_CODE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        surfaceView = new GLSurfaceView(this);
        surfaceView.setEGLContextClientVersion(2);
        surface = new renderer(getAssets(),getApplicationContext());
        surfaceView.setRenderer(surface);
        setContentView(surfaceView);
    }

    protected void onPause(){
        super.onPause();
        surfaceView.onPause();
    }

    protected void onResume(){
        super.onResume();
        surfaceView.onResume();
    }

}

我需要 AssetManager 来加载文件和用于调试的上下文,因为我没有使用 VisualStudio,这是我获取调试信息的唯一方法.

I need the AssetManager to load up files and Context for debuging, since I'm not using VisualStudio, it's my only way of getting debugging info.

推荐答案

我认为这是你的问题.glSurfaceView 的 OpenGLES 上下文仅绑定到 GLThread.您确实需要将所有 OpenGLES 代码置于 glSurfaceView.Renderer 的功能之一的下游,例如onSurfaceCreatedonDrawFrame.

This is your problem I think. glSurfaceView's OpenGLES context is only bound to the GLThread. You really need to have all your OpenGLES code downstream from one of glSurfaceView.Renderer's functions e.g. onSurfaceCreated or onDrawFrame.

eglGetCurrentContext 函数可以告诉您是否有一个 OpenGLES 上下文绑定到当前线程.在没有上下文的情况下调用任何 OpenGLES 函数将导致不会通过 glGetError 报告的错误.在调试版本中,我会在每个 OpenGLES 调用中检查上下文和 glGetError.

The function eglGetCurrentContext can tell you if there's an OpenGLES context bound to the current thread. Calling any OpenGLES functions without a context will result in bugs that aren't reported through glGetError. In debug builds, I check both the context and glGetError on every single OpenGLES call.

我不知道在 GLThread 上使用 AssetManager 和 Context 有什么真正的障碍.

I'm not aware of any real obstacle to using AssetManager and Context on the GLThread.

这篇关于为什么 GLES20.glCreateShader 总是返回 0?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-31 10:20