Android OpenGL create GL program: 0 & GL error: 1282
快速解决
1. 使用GLSurfaceView的话
请在继承类中合适的地方(一般是构造函数里面)设置当前的clientversion 为 2
具体代码:
setEGLContextClientVersion(2);
2. 使用自己构建的opengl环境的话
请在创建glContext的时传入的参数中配置 int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2 , EGL10.EGL_NONE };
具体代码如下,注意 attrib_list 中的第二个元素写为 2 。
//注意 :int EGL_CONTEXT_CLIENT_VERSION = 0x3098
int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
EGLContext glContext = egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT,attrib_list);
注意,int EGL_CONTEXT_CLIENT_VERSION = 0x3098。到此,是同样的问题的话,应该得到了解决,可以继续搬砖了。
有兴趣的继续往下看:
出错代码鉴赏
int shader = GLES20.glCreateShader(type);// add the source code to the shader and compile itGLES20.glShaderSource(shader, shaderCode);checkError();GLES20.glCompileShader(shader);checkError();int program = GLES20.glCreateProgram();checkError();
该段代码一般是封装为一个叫loadShader的函数中,本身是无误,但达不到期望的效果,如果在checkError里面抛出异常,那么就挂掉了。
通过上面的解决方法和代码,问题的原因就明显了:
GLES20.xxx() 和open环境不一致。即 opengl的环境不是2.0,却使用了2.0的接口 ,所以将opengl的版本指定(初始化)为 2。
有些朋友可能直接提问 loadShader出错,实际上的代码是上面的代码片段。
GLSurfaceView 部分代码分享
GLSurfaceView 源码是API level 30.
- GLSurfaceView中 mEGLContextClientVersion 外部没有设置的话,默认是0
- DefaultContextFactory 具体实现
private class DefaultContextFactory implements EGLContextFactory {private int EGL_CONTEXT_CLIENT_VERSION = 0x3098;public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig config) {int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, mEGLContextClientVersion,EGL10.EGL_NONE };return egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT,mEGLContextClientVersion != 0 ? attrib_list : null);}public void destroyContext(EGL10 egl, EGLDisplay display,EGLContext context) {if (!egl.eglDestroyContext(display, context)) {Log.e("DefaultContextFactory", "display:" + display + " context: " + context);if (LOG_THREADS) {Log.i("DefaultContextFactory", "tid=" + Thread.currentThread().getId());}EglHelper.throwEglException("eglDestroyContex", egl.eglGetError());}}}
从createContext 中代码可看出,mEGLContextClientVersion 为0 的时候 ,egl.eglCreateContext的最后一个参数传入的是null。同时mEGLContextClientVersion 又是 attrib_list 数组第二个元素,版本openGl2.0就是通过这个参数确定的。
- setEGLContextClientVersion
精简了函数的注释,可以从注释上面得到一些启发, Pick an OpenGL ES 2.0 context。
/*** Inform the default EGLContextFactory and default EGLConfigChooser* which EGLContext client version to pick.* <p>Use this method to create an OpenGL ES 2.0-compatible context.* Example:* <pre class="prettyprint">* public MyView(Context context) {* super(context);* setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context.* setRenderer(new MyRenderer());* }* </pre>*/public void setEGLContextClientVersion(int version) {checkRenderThreadState();mEGLContextClientVersion = version;}
综合起来使用GLSurfaceView的opengl便利的情况下要使用2.0,优先调用setEGLContextClientVersion(2)
基于TextureView 或SufaceView创建openglcontext
最终的要调用的代码如下:
int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
EGLContext glContext = egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT,attrib_list);
version 可以根据需要进行指定。
补充:
自定义 GLSurfaceView 的 setEGLContextFactory 是提供自定义创建opengl环境的接口,只要根据上面两个关键调用实现EGLContextFactory 就可以,GLSurfaceView的默认实现就是DefaultContextFactory。