如何解决为什么我的OpenGL ES应用程序在glDrawElements上崩溃?
我在Xamarin(使用OpenTK)上开发了带有OpenGL ES 3的手机游戏。在大多数设备上运行正常,但在某些设备上崩溃(HUAWEI Y5 lite)。不幸的是,我没有该错误的详细日志:
#00 pc 0000000000093d2a /vendor/lib/egl/libGLESv2_mtk.so
#01 pc 000000000001c137 /vendor/lib/egl/libGLESv2_mtk.so
#02 pc 000000000001eddf /vendor/lib/egl/libGLESv2_mtk.so
#03 pc 000000000001af75 /vendor/lib/egl/libGLESv2_mtk.so
#04 pc 000000000001aabf /vendor/lib/egl/libGLESv2_mtk.so (glDrawElements+54)
#05 pc 000000000000ca0c <anonymous>
我猜想这与我的绘画代码有关,或更糟糕的是与手机的某些驱动程序有关。我正在使用以下代码来渲染四边形:
public void BeforeRender()
{
// Use shader program.
GL.UseProgram(shader.Program);
// Enable transparency
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha,BlendingFactorDest.OneMinusSrcAlpha);
// Use texture
GL.ActiveTexture(TextureUnit.Texture0);
GL.Uniform1(shader.UniformTexture,0);
// Only bind once for all quads
GL.BindBuffer(BufferTarget.ElementArrayBuffer,indexBufferId);
}
public void Render(Sprite sprite,Vector4 color,Matrix4 modelViewProjection)
{
// Set model view projection
GL.UniformMatrix4(shader.UniformModelViewProjection,false,ref modelViewProjection);
// Set color
GL.Uniform4(shader.UniformColor,color);
// Set texture
GL.BindTexture(TextureTarget.Texture2D,sprite.TextureId);
// Update attribute value Position
GL.BindBuffer(BufferTarget.ArrayBuffer,sprite.Vbo);
GL.VertexAttribPointer(shader.AttribVertex,3,VertexAttribPointerType.Float,sizeof(float) * 5,IntPtr.Zero); // 3 + 2 = 5
GL.EnabLevertexAttribArray(shader.AttribVertex);
// Update attribute value TexCoord
GL.VertexAttribPointer(shader.AttribTexCoord,2,new IntPtr(sizeof(float) * 3));
GL.EnabLevertexAttribArray(shader.AttribTexCoord);
// Draw quad
GL.DrawElements(BeginMode.Triangles,faceIndexes.Length,DrawElementsType.UnsignedShort,IntPtr.Zero);
}
public void AfterRender()
{
// Unbind / disable
GL.BindBuffer(BufferTarget.ArrayBuffer,0);
GL.BindBuffer(BufferTarget.ElementArrayBuffer,0);
GL.disable(EnableCap.Blend);
}
BeforeRender();
foreach(var sprite in sprites)
{
Render(sprite);
}
AfterRender();
我的代码总体上是否存在问题,可能会导致某些其他设备“容忍”的设备出现问题?
谢谢!
更新:
这是我创建缓冲区的方式:
public int Load<T>(T[] data)
where T : struct
{
int bufferId;
GL.GenBuffers(1,out bufferId);
bufferIds.Add(bufferId);
GL.BindBuffer(BufferTarget.ArrayBuffer,bufferId);
GL.BufferData(BufferTarget.ArrayBuffer,(IntPtr)(data.Length * Marshal.SizeOf(default(T))),data,BufferUsage.StaticDraw);
GL.BindBuffer(BufferTarget.ArrayBuffer,0);
return bufferId;
}
对于索引缓冲区,我使用:
ushort[] faceIndexes =
{
0,1,2
};
indexBufferId = bufferManager.Load(faceIndexes);
对于顶点缓冲区,我使用:
float[] vertices =
{
0f,0f,ty,width,tx,height,0f
};
int vboId = bufferManager.Load(vertices);
解决方法
索引必须存储到ElementArrayBuffer
而不是ArrayBuffer
:
GL.BindBuffer(BufferTarget.ArrayBuffer,bufferId); ...
GL.BindBuffer(BufferTarget.ElementArrayBuffer,bufferId);
GL.BufferData(BufferTarget.ElementArrayBuffer,(IntPtr)(data.Length * Marshal.SizeOf(default(T))),data,BufferUsage.StaticDraw);
GL.BindBuffer(BufferTarget.ElementArrayBuffer,0);
向通用的target
方法添加一个Load
参数。例如:
public int Load<T>(T[] data,BufferTarget target)
where T : struct
{
int bufferId;
GL.GenBuffers(1,out bufferId);
bufferIds.Add(bufferId);
GL.BindBuffer(target,bufferId);
GL.BufferData(target,BufferUsage.StaticDraw);
GL.BindBuffer(target,0);
return bufferId;
}
indexBufferId = bufferManager.Load(faceIndexes,BufferTarget.ElementArrayBuffer);
int vboId = bufferManager.Load(vertices,BufferTarget.ArrayBuffer);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。