如何在 android 上正确使用 GLES20.glVertexAttribPointer() 和 VBO?
How to properly use GLES20.glVertexAttribPointer() on android with VBOs?
我试图让一个简单的二维正方形出现在屏幕上,但我 运行 遇到方法 GLES20.glVertexAttribPointer() 中最后一个参数的问题。
这是我的代码(draw() 方法):
public void draw(float[] matrix){
int shaderHandle = shader.getShaderHandle();
int mMVPMatrixHandle;
GLES20.glUseProgram(shaderHandle);
mPositionHandle = GLES20.glGetAttribLocation(shaderHandle, "vPosition");
mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderHandle, "uMVPMatrix");
MyGLRenderer.checkGlError("glGetUniformLocation");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, matrix, 0);
MyGLRenderer.checkGlError("glUniformMatrix4fv");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER,vbo);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle,COORDS_PER_VERTEX,GLES20.GL_FLOAT,false,0,0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER,ibo);
GLES20.glDrawElements(GLES20.GL_TRIANGLES,DRAW_ORDER.length,GLES20.GL_UNSIGNED_SHORT,null);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER,0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER,0);
}
问题出在这一行:
GLES20.glVertexAttribPointer(mPositionHandle,COORDS_PER_VERTEX,GLES20.GL_FLOAT,false,0,0);
我正在使用 Android Studio,它告诉我不能将 0
作为此方法的最后一个参数传递,它需要一个 Buffer 对象。
为了使用我的 VBO,我被告知我必须将零作为最后一个参数。我该怎么做?
我收到的logcat条目如下:
06-23 22:27:23.098 2709-2709/? I/art: Not late-enabling -Xcheck:jni (already on)
06-23 22:27:23.222 2709-2709/com.example.android.opengl W/System: ClassLoader referenced unknown path: /data/app/com.example.android.opengl-2/lib/x86
06-23 22:27:23.362 2709-2709/com.example.android.opengl W/System: ClassLoader referenced unknown path: /data/app/com.example.android.opengl-2/lib/x86
06-23 22:27:23.432 2709-2730/com.example.android.opengl D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
[ 06-23 22:27:23.439 2709: 2709 D/ ]
HostConnection::get() New Host Connection established 0xab9e4670, tid 2709
[ 06-23 22:27:23.472 2709: 2730 D/ ]
HostConnection::get() New Host Connection established 0xaf4471b0, tid 2730
06-23 22:27:23.474 2709-2730/com.example.android.opengl I/OpenGLRenderer: Initialized EGL, version 1.4
[ 06-23 22:27:23.506 2709: 2729 D/ ]
HostConnection::get() New Host Connection established 0xab9e4ac0, tid 2729
06-23 22:27:23.557 2709-2729/com.example.android.opengl I/System.out: DEBUG
06-23 22:27:23.562 2709-2729/com.example.android.opengl E/Surface: getSlotFromBufferLocked: unknown buffer: 0xb4093c00
06-23 22:27:23.565 2709-2729/com.example.android.opengl E/AndroidRuntime: FATAL EXCEPTION: GLThread 129
Process: com.example.android.opengl, PID: 2709
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.nio.Buffer.remaining()' on a null object reference
at android.opengl.GLES20.glVertexAttribPointer(GLES20.java:1913)
at com.example.android.opengl.Sprite.draw(Sprite.java:105)
at com.example.android.opengl.MyGLRenderer.onDrawFrame(MyGLRenderer.java:76)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1535)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
06-23 22:27:23.607 2709-2730/com.example.android.opengl E/Surface: getSlotFromBufferLocked: unknown buffer: 0xa3b11230
我还没有看到你的logcat输出,所以我不知道错误是什么。但是,我有一个猜测;去掉最后两行 glBindBuffer。
public void draw(float[] matrix){
int shaderHandle = shader.getShaderHandle();
int mMVPMatrixHandle;
GLES20.glUseProgram(shaderHandle);
mPositionHandle = GLES20.glGetAttribLocation(shaderHandle, "vPosition");
mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderHandle, "uMVPMatrix");
MyGLRenderer.checkGlError("glGetUniformLocation");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, matrix, 0);
MyGLRenderer.checkGlError("glUniformMatrix4fv");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER,vbo);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle,COORDS_PER_VERTEX,GLES20.GL_FLOAT,false,0,0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER,ibo);
GLES20.glDrawElements(GLES20.GL_TRIANGLES,DRAW_ORDER.length,GLES20.GL_UNSIGNED_SHORT,null);
}
我想通了!
问题根本不是我的代码,而是我使用的 Android SDK 的版本。有一个非常简单的解决方法。
您只需将项目的 SDK 设置(compileSdkVersion、minSdkVersion、targetSdkVersion)更改为合适的版本即可。我将 minSdkVersion 和 compileSdkVersion 的版本更改为 14,因为此版本包含对 OpenGL ES 2.0 的完整(足够)支持以执行我想要的操作,并且几乎没有人再使用 SDK 版本低于 14 的设备。
我试图让一个简单的二维正方形出现在屏幕上,但我 运行 遇到方法 GLES20.glVertexAttribPointer() 中最后一个参数的问题。
这是我的代码(draw() 方法):
public void draw(float[] matrix){
int shaderHandle = shader.getShaderHandle();
int mMVPMatrixHandle;
GLES20.glUseProgram(shaderHandle);
mPositionHandle = GLES20.glGetAttribLocation(shaderHandle, "vPosition");
mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderHandle, "uMVPMatrix");
MyGLRenderer.checkGlError("glGetUniformLocation");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, matrix, 0);
MyGLRenderer.checkGlError("glUniformMatrix4fv");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER,vbo);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle,COORDS_PER_VERTEX,GLES20.GL_FLOAT,false,0,0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER,ibo);
GLES20.glDrawElements(GLES20.GL_TRIANGLES,DRAW_ORDER.length,GLES20.GL_UNSIGNED_SHORT,null);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER,0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER,0);
}
问题出在这一行:
GLES20.glVertexAttribPointer(mPositionHandle,COORDS_PER_VERTEX,GLES20.GL_FLOAT,false,0,0);
我正在使用 Android Studio,它告诉我不能将 0
作为此方法的最后一个参数传递,它需要一个 Buffer 对象。
为了使用我的 VBO,我被告知我必须将零作为最后一个参数。我该怎么做?
我收到的logcat条目如下:
06-23 22:27:23.098 2709-2709/? I/art: Not late-enabling -Xcheck:jni (already on)
06-23 22:27:23.222 2709-2709/com.example.android.opengl W/System: ClassLoader referenced unknown path: /data/app/com.example.android.opengl-2/lib/x86
06-23 22:27:23.362 2709-2709/com.example.android.opengl W/System: ClassLoader referenced unknown path: /data/app/com.example.android.opengl-2/lib/x86
06-23 22:27:23.432 2709-2730/com.example.android.opengl D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
[ 06-23 22:27:23.439 2709: 2709 D/ ]
HostConnection::get() New Host Connection established 0xab9e4670, tid 2709
[ 06-23 22:27:23.472 2709: 2730 D/ ]
HostConnection::get() New Host Connection established 0xaf4471b0, tid 2730
06-23 22:27:23.474 2709-2730/com.example.android.opengl I/OpenGLRenderer: Initialized EGL, version 1.4
[ 06-23 22:27:23.506 2709: 2729 D/ ]
HostConnection::get() New Host Connection established 0xab9e4ac0, tid 2729
06-23 22:27:23.557 2709-2729/com.example.android.opengl I/System.out: DEBUG
06-23 22:27:23.562 2709-2729/com.example.android.opengl E/Surface: getSlotFromBufferLocked: unknown buffer: 0xb4093c00
06-23 22:27:23.565 2709-2729/com.example.android.opengl E/AndroidRuntime: FATAL EXCEPTION: GLThread 129
Process: com.example.android.opengl, PID: 2709
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.nio.Buffer.remaining()' on a null object reference
at android.opengl.GLES20.glVertexAttribPointer(GLES20.java:1913)
at com.example.android.opengl.Sprite.draw(Sprite.java:105)
at com.example.android.opengl.MyGLRenderer.onDrawFrame(MyGLRenderer.java:76)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1535)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
06-23 22:27:23.607 2709-2730/com.example.android.opengl E/Surface: getSlotFromBufferLocked: unknown buffer: 0xa3b11230
我还没有看到你的logcat输出,所以我不知道错误是什么。但是,我有一个猜测;去掉最后两行 glBindBuffer。
public void draw(float[] matrix){
int shaderHandle = shader.getShaderHandle();
int mMVPMatrixHandle;
GLES20.glUseProgram(shaderHandle);
mPositionHandle = GLES20.glGetAttribLocation(shaderHandle, "vPosition");
mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderHandle, "uMVPMatrix");
MyGLRenderer.checkGlError("glGetUniformLocation");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, matrix, 0);
MyGLRenderer.checkGlError("glUniformMatrix4fv");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER,vbo);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle,COORDS_PER_VERTEX,GLES20.GL_FLOAT,false,0,0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER,ibo);
GLES20.glDrawElements(GLES20.GL_TRIANGLES,DRAW_ORDER.length,GLES20.GL_UNSIGNED_SHORT,null);
}
我想通了!
问题根本不是我的代码,而是我使用的 Android SDK 的版本。有一个非常简单的解决方法。
您只需将项目的 SDK 设置(compileSdkVersion、minSdkVersion、targetSdkVersion)更改为合适的版本即可。我将 minSdkVersion 和 compileSdkVersion 的版本更改为 14,因为此版本包含对 OpenGL ES 2.0 的完整(足够)支持以执行我想要的操作,并且几乎没有人再使用 SDK 版本低于 14 的设备。