首先,我应该说我正在使用 Android API 27 在像素模拟器上运行它,但我在 Android API 26 上也遇到了同样的崩溃。
我只是想绘制一个二维 Sprite 并为其设置动画。我有一个线程同时运行到渲染循环(在 GLSurfaceView 和 GLSurfaceView.Renderer 中),在 Sprite 表中更新具有不同纹理坐标的 VBO。但是,据我所知,问题出在哪里。
基本上我能说的就是绑定(bind)和取消绑定(bind)我的 VBO 后 glDrawElements 崩溃,特别是取消绑定(bind)。具体来说,它是一个空指针取消引用错误。当我取消绑定(bind)我的元素缓冲区对象时,这个问题不会发生。
编辑:我刚刚发布了这个,我意识到我忘了提到在快速阅读 glBindBuffer 之后我发现:
The value zero is reserved, but there is no default buffer object for each buffer object target. Instead, buffer set to zero effectively unbinds any buffer object previously bound, and restores client memory usage for that buffer object target (if supported for that target).
关于恢复内存的部分可能是造成这种情况的原因吗?如果是这样,我将如何解绑它。
这是 Sprite.java 的代码:
package com.matthew.beatclimber;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.content.Context;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by matthew on 10/28/17.
*/
/*
Note to self:
This can be done to bind a attribute location to a literal
GLES20.glBindAttribLocation(program, 0, "vPosition");
*/
public class Sprite
{
private FloatBuffer vertexBuffer;
private ShortBuffer indexBuffer;
private Timer animateTimer;
private SpriteSheet spriteSheet;
private int[] vbo = {0}, ebo = {0}, texture = {0};
private int vertexShader, fragmentShader, program;
static float[] vertices = {
-16.0f, 16.0f, 0.0f, 1.0f, /*Tex Coords*/ -1.0f, 1.0f, //Top Left
-16.0f, -16.0f, 0.0f, 1.0f, -1.0f, -1.0f, //Bot Left
16.0f, -16.0f, 0.0f, 1.0f, 1.0f, -1.0f, //Bot Right
//-1.0f, 1.0f, 3.0f, 1.0f, /*Tex Coords*/ -1.0f, 1.0f, //Top Left
//1.0f, -1.0f, 3.0f, 1.0f, 1.0f, -1.0f, //Bot Right
16.0f, 16.0f, 0.0f, 1.0f, 1.0f, 1.0f //Top Right
};
private static final short[] order = { 0, 1, 2, 0, 2, 3};
private float[] model = new float[16];
static float[] ortho = new float[16];
char[] infoLog = new char[512];
private static final String vertexShaderCode =
"attribute vec4 vPosition;" +
"attribute vec2 TexCoords;" +
"varying vec2 texCoords;" +
"uniform mat4 ortho;" +
"uniform mat4 model;"+
"void main() {" +
" gl_Position = ortho * model * vPosition;" +
" texCoords = TexCoords;" +
"}";
private static final String fragmentShaderCode =
"precision mediump float;" +
"uniform sampler2D tex1;" +
"varying vec2 texCoords;" +
"void main() {" +
" gl_FragColor = mix(texture2D(tex1, texCoords), vec4(texCoords, 0.0, 1.0), 0.2);" +
"}";
public Sprite(int screenWidth, int screenHeight)
{
//Set model equal to a identity matrix
Matrix.setIdentityM(model, 0);
Matrix.translateM(model, 0, screenWidth / 2, screenHeight / 2, 0);
Matrix.scaleM(model, 0, 32, 32, 0);
ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer dlb = ByteBuffer.allocateDirect(order.length * 2);
dlb.order(ByteOrder.nativeOrder());
indexBuffer = dlb.asShortBuffer();
indexBuffer.put(order);
indexBuffer.position(0);
//Create shader program
vertexShader = OpenGLES31Activity.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
fragmentShader = OpenGLES31Activity.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
program = GLES20.glCreateProgram();
int[] success = new int[2];
GLES20.glGetShaderiv(vertexShader, GLES20.GL_COMPILE_STATUS, success, 0);
GLES20.glGetShaderiv(fragmentShader, GLES20.GL_COMPILE_STATUS, success, 1);
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glBindAttribLocation(program, 0, "vPosition");
GLES20.glBindAttribLocation(program, 1, "TexCoords");
GLES20.glLinkProgram(program);
if((success[0] == GLES20.GL_FALSE))
{
GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
String info = GLES20.glGetShaderInfoLog(vertexShader);
System.out.println("ERROR: VERTEX: " + info);
}
if ((success[1] == GLES20.GL_FALSE))
{
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
String info = GLES20.glGetShaderInfoLog(fragmentShader);
System.out.println("ERROR: FRAG: " + info);
}
//Create Buffer Objects (Vertex and Element Buffer Objects)
GLES20.glGenBuffers(1, vbo, 0);
GLES20.glGenBuffers(1, ebo, 0);
//Bind Objects
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ebo[0]);
//Write Data
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * 4, vertexBuffer, GLES20.GL_DYNAMIC_DRAW);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * 2, indexBuffer, GLES20.GL_STATIC_DRAW);
//Unbind objects
//GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
//GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
animateTimer = new Timer();
}
public synchronized void draw()
{
//Use Shader Program
GLES20.glUseProgram(program);
//////////////////////Configure Attribute (Core OpenGL ie: in)//////////////////////////
//Get Attribute Locations
//int attribLocationPos = GLES20.glGetAttribLocation(program, "vPosition");
//int attribLocationTex = GLES20.glGetAttribLocation(program, "TexCoords");
//Enable Vertex Attribute Array
GLES20.glEnableVertexAttribArray(0);
GLES20.glVertexAttribPointer(0, 4, GLES20.GL_FLOAT, false, 24, 0);
//Tex Coord Attribute
GLES20.glEnableVertexAttribArray(1);
GLES20.glVertexAttribPointer(1, 2, GLES20.GL_FLOAT, false, 24, 16);
//Bind Objects
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ebo[0]);
//int[] i = new int[1];
//int[] j = new int[1];
//GLES20.glGetIntegerv(GLES20.GL_ARRAY_BUFFER_BINDING, i, 0);
//GLES20.glGetIntegerv(GLES20.GL_ELEMENT_ARRAY_BUFFER_BINDING, j, 0);
//System.out.println(i + " " + j);
//Set model matrix uniform to model
GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(program, "model"), 1, false, model, 0);
GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(program, "ortho"), 1, false, ortho, 0);
//Texture Stuff
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]);
//Draw Square
GLES20.glDrawElements(GLES20.GL_TRIANGLES, order.length, GLES20.GL_UNSIGNED_SHORT, 0);
//GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
//Disable Vertex Attribute Array
GLES20.glDisableVertexAttribArray(0);
GLES20.glDisableVertexAttribArray(1);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
//GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
//Stop using program
//GLES20.glUseProgram(0);
}
public void createTextureSpriteSheet(Context context, int resourceID, int spriteWidth, int spriteHeight, int sheetWidth, int sheetHeight, int frame)
{
InputStream is = context.getResources().openRawResource(resourceID);
Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(is);
} finally {
try {
is.close();
} catch(IOException e) {
// Ignore.
}
}
//bitmap = BitmapFactory.decodeFile("R.raw.blobbosheet.png \
ByteBuffer data = ByteBuffer.allocateDirect(bitmap.getByteCount());
data.order(ByteOrder.nativeOrder());
bitmap.copyPixelsToBuffer(data);
System.out.println("Bitmap: " + bitmap.getWidth() + " " + bitmap.getHeight());
data.position(0);
GLES20.glGenTextures(1, texture, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, bitmap.getWidth(), bitmap.getHeight(), 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, data);
//GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
spriteSheet = new SpriteSheet(sheetWidth, sheetHeight, spriteWidth, spriteHeight, 8);
float[] texCoords = spriteSheet.getSpriteCoords(frame);
for(int i = 0; i < 8; i++)
{
System.out.println("TexCoord: " + i + " is : " + texCoords[i]);
}
spriteSheet.setFrame(frame);
//Update Tex Coords
vertices[4] = texCoords[0];
vertices[5] = texCoords[1];
vertices[10] = texCoords[2];
vertices[11] = texCoords[3];
vertices[16] = texCoords[4];
vertices[17] = texCoords[5];
vertices[22] = texCoords[6];
vertices[23] = texCoords[7];
updateVBO();
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
}
public void switchSprite(int frame)
{
float[] texCoords = spriteSheet.getSpriteCoords(frame);
spriteSheet.setFrame(frame);
//Update Tex Coords
vertices[4] = texCoords[0];
vertices[5] = texCoords[1];
vertices[10] = texCoords[2];
vertices[11] = texCoords[3];
vertices[16] = texCoords[4];
vertices[17] = texCoords[5];
vertices[22] = texCoords[6];
vertices[23] = texCoords[7];
updateVBO();
}
public void nextFrame()
{
float[] texCoords = spriteSheet.nextFrame();
for(int i = 0; i < 8; i++)
{
System.out.println("TexCoord: " + i + " is : " + texCoords[i]);
}
//Update Tex Coords
vertices[4] = texCoords[0];
vertices[5] = texCoords[1];
vertices[10] = texCoords[2];
vertices[11] = texCoords[3];
vertices[16] = texCoords[4];
vertices[17] = texCoords[5];
vertices[22] = texCoords[6];
vertices[23] = texCoords[7];
updateVBO();
}
public void animate(int startFrame, int framesPerSec, final int numbOfFrames)
{
switchSprite(startFrame);
TimerTask task = new TimerTask()
{
int count = 0;
public void run()
{
nextFrame();
count++;
System.out.println("Animate Thread Going!");
if(count == numbOfFrames)
{
System.out.println("Animate Thread Canceled");
cancel();
}
}
};
animateTimer.scheduleAtFixedRate(task, 0, 1000 / framesPerSec);
}
public synchronized void updateVBO()
{
System.out.println("In updateVBO()");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
vertexBuffer.clear();
vertexBuffer.put(vertices).flip();
float[] test = new float[vertexBuffer.capacity()];
vertexBuffer.get(test);
for(float i : test)
{
System.out.println(i + ", ");
}
vertexBuffer.clear();
vertexBuffer.put(vertices).flip();
for(int i = 4; i < 23; i += 6)
{
System.out.println("TexCoord: " + i + " is : " + vertices[i]);
System.out.println("TexCoord: " + i + " is : " + vertices[i + 1]);
}
System.out.println(vertexBuffer.capacity() * 4 + " " + vertexBuffer.remaining());
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, vertexBuffer.capacity() * 4, vertexBuffer);
//GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * 4, )
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
}
和我的渲染器的代码:
package com.matthew.beatclimber;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.Matrix;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.Display;
import android.app.Activity;
/**
* Created by matthew on 10/28/17.
*/
public class MyGLRenderer implements GLSurfaceView.Renderer
{
Sprite sprite;
float[] orthoProjection = new float[16];
Context context;
public MyGLRenderer(Context context)
{
this.context = context;
}
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig config) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
sprite = new Sprite(1080, 1704);
sprite.createTextureSpriteSheet(context, R.drawable.blobbosheet, 32, 32, 256, 32, 0);
sprite.animate(0, 2, -1);
}
@Override
public void onSurfaceChanged(GL10 gl10, int width, int height) {
GLES20.glViewport(0, 0, width, height);
Matrix.orthoM(orthoProjection, 0, 0, width, 0, height, -1, 100);
Sprite.ortho = orthoProjection;
}
@Override
public void onDrawFrame(GL10 gl10)
{
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
System.out.println("Drawing");
sprite.draw();
}
}
这也是它转储到日志中的内容:
11-04 17:50:41.569 13651-13670/com.matthew.beatclimber A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x10 in tid 13670 (GLThread 490), pid 13651 (hew.beatclimber)
11-04 17:50:41.606 13678-13678/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
11-04 17:50:41.606 13678-13678/? A/DEBUG: Build fingerprint: 'google/sdk_gphone_x86/generic_x86:8.1.0/OPM1.171004.001/4376136:userdebug/dev-keys'
11-04 17:50:41.606 13678-13678/? A/DEBUG: Revision: '0'
11-04 17:50:41.606 13678-13678/? A/DEBUG: ABI: 'x86'
11-04 17:50:41.606 13678-13678/? A/DEBUG: pid: 13651, tid: 13670, name: GLThread 490 >>> com.matthew.beatclimber <<<
11-04 17:50:41.606 13678-13678/? A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x10
11-04 17:50:41.606 13678-13678/? A/DEBUG: Cause: null pointer dereference
11-04 17:50:41.606 13678-13678/? A/DEBUG: eax 00000010 ebx 9eaf3be4 ecx 00000008 edx 8f4000ea
11-04 17:50:41.606 13678-13678/? A/DEBUG: esi 00000010 edi 00000000
11-04 17:50:41.606 13678-13678/? A/DEBUG: xcs 00000073 xds 0000007b xes 0000007b xfs 0000003b xss 0000007b
11-04 17:50:41.606 13678-13678/? A/DEBUG: eip ab72b33c ebp 8ff7c5c8 esp 8ff7c588 flags 00010202
11-04 17:50:41.907 13678-13678/? A/DEBUG: backtrace:
11-04 17:50:41.907 13678-13678/? A/DEBUG: #00 pc 0001a33c /system/lib/libc.so (memcpy+732)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #01 pc 00021cd0 /vendor/lib/egl/libEGL_emulation.so (glUtilsPackPointerData+480)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #02 pc 0003bb98 /vendor/lib/libGLESv2_enc.so ((anonymous namespace)::glVertexAttribPointerData_enc(void*, unsigned int, int, unsigned int, unsigned char, int, void*, unsigned int)+184)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #03 pc 000286c4 /vendor/lib/libGLESv2_enc.so (GL2Encoder::sendVertexAttributes(int, int, bool, int)+1124)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #04 pc 000167ce /vendor/lib/libGLESv2_enc.so (GL2Encoder::s_glDrawElements(void*, unsigned int, int, unsigned int, void const*)+958)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #05 pc 00009c3f /vendor/lib/egl/libGLESv2_emulation.so (glDrawElements+79)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #06 pc 00099c16 /system/lib/libandroid_runtime.so (android_glDrawElements__IIII(_JNIEnv*, _jobject*, int, int, int, int)+38)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #07 pc 00e82a36 /system/framework/x86/boot-framework.oat (offset 0x5fc000) (android.opengl.GLES10.glClearColorx [DEDUPED]+182)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #08 pc 00642032 /system/lib/libart.so (art_quick_invoke_static_stub+418)
11-04 17:50:41.907 13678-13678/? A/DEBUG: #09 pc 00116009 /system/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+265)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #10 pc 0032143f /system/lib/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+335)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #11 pc 0031a6a4 /system/lib/libart.so (_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+836)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #12 pc 0062927a /system/lib/libart.so (MterpInvokeStatic+282)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #13 pc 00633021 /system/lib/libart.so (artMterpAsmInstructionStart+14497)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #14 pc 002f392b /system/lib/libart.so (art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool)+539)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #15 pc 002fa1e7 /system/lib/libart.so (art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*)+231)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #16 pc 0031a68a /system/lib/libart.so (_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+810)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #17 pc 00627a44 /system/lib/libart.so (MterpInvokeVirtual+756)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #18 pc 00632ea1 /system/lib/libart.so (artMterpAsmInstructionStart+14113)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #19 pc 002f392b /system/lib/libart.so (art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool)+539)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #20 pc 002fa1e7 /system/lib/libart.so (art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*)+231)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #21 pc 0031a68a /system/lib/libart.so (_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+810)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #22 pc 00628c0f /system/lib/libart.so (MterpInvokeInterface+1647)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #23 pc 006330a1 /system/lib/libart.so (artMterpAsmInstructionStart+14625)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #24 pc 002f392b /system/lib/libart.so (art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool)+539)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #25 pc 002fa1e7 /system/lib/libart.so (art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*)+231)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #26 pc 0031a68a /system/lib/libart.so (_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+810)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #27 pc 0062905c /system/lib/libart.so (MterpInvokeDirect+428)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #28 pc 00632fa1 /system/lib/libart.so (artMterpAsmInstructionStart+14369)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #29 pc 002f392b /system/lib/libart.so (art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool)+539)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #30 pc 002fa0cb /system/lib/libart.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*)+139)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #31 pc 006175ef /system/lib/libart.so (artQuickToInterpreterBridge+1311)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #32 pc 00647f2d /system/lib/libart.so (art_quick_to_interpreter_bridge+77)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #33 pc 00641e62 /system/lib/libart.so (art_quick_invoke_stub+338)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #34 pc 00115fdf /system/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+223)
11-04 17:50:41.908 13678-13678/? A/DEBUG: #35 pc 00544aeb /system/lib/libart.so (art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::ArgArray*, art::JValue*, char const*)+91)
11-04 17:50:41.909 13678-13678/? A/DEBUG: #36 pc 00545fb8 /system/lib/libart.so (art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, jvalue*)+744)
11-04 17:50:41.909 13678-13678/? A/DEBUG: #37 pc 0057512f /system/lib/libart.so (art::Thread::CreateCallback(void*)+1487)
11-04 17:50:41.909 13678-13678/? A/DEBUG: #38 pc 00071445 /system/lib/libc.so (__pthread_start(void*)+53)
11-04 17:50:41.909 13678-13678/? A/DEBUG: #39 pc 000205db /system/lib/libc.so (__start_thread+75)
11-04 17:50:41.909 13678-13678/? A/DEBUG: #40 pc 0001ec16 /system/lib/libc.so (__bionic_clone+70)
11-04 17:50:42.190 1484-1484/? E//system/bin/tombstoned: Tombstone written to: /data/tombstones/tombstone_04
最佳答案
操作顺序有点困惑。设置顶点属性指针时,必须先绑定(bind)缓冲区,然后设置指针。
public synchronized void draw()
{
//Use Shader Program
GLES20.glUseProgram(program);
//Enable Vertex Attribute Array
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
GLES20.glEnableVertexAttribArray(0);
GLES20.glVertexAttribPointer(0, 4, GLES20.GL_FLOAT, false, 24, 0);
//Tex Coord Attribute
GLES20.glEnableVertexAttribArray(1);
GLES20.glVertexAttribPointer(1, 2, GLES20.GL_FLOAT, false, 24, 16);
//Bind Index Buffer
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ebo[0]);
...
}
添加缓冲区解除绑定(bind)代码时会出现错误,因为否则仍然会从构造函数绑定(bind)正确的缓冲区。
关于android - 取消绑定(bind) VBO 后,glDrawElements 上的 OpenGL ES 2.0 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47116154/