我的应用程序崩溃了“glDrawElements”(和glDrawArrays)。
我想知道,崩溃的原因是什么?
目前我已经拥有:
Foreach mesh
- Bind VBO/VAO
if( VAO empty )
- bind VAO(id)
- bind VBO(id)
Foreach attribs
- glEnableVertexAttribArray
- glVertexAttribPointer
End foreach
- unbindVAO(0)
- unbindVBO(0)
Foreach attribs
- glDisableVertexAttribArray
End foreach
endif
- Bind IBO(id)
- Bind program/shader(id)
-> send uniforms
-> glDrawElements
End foreach
我认为我的缓冲区有些奇怪(比如冲突),绑定的正确顺序是什么?我需要解开VAO,VBO,IBO,程序,纹理,......?
编辑:
当我删除几何体时,看起来像是崩溃,他的缓冲区从opengl中移除(因为我不再使用它们了)。所以我认为我的缓冲区总是受到限制。
OpenGL跟踪:
glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 8)
glEnableVertexAttribArray(index = 2)
glVertexAttribPointer(indx = 2, size = 3, type = GL_FLOAT, normalized = false, stride = 20, ptr = 0x0)
glEnableVertexAttribArray(index = 0)
glVertexAttribPointer(indx = 0, size = 4, type = GL_UNSIGNED_BYTE, normalized = true, stride = 20, ptr = 0xc)
glEnableVertexAttribArray(index = 4)
glVertexAttribPointer(indx = 4, size = 2, type = GL_UNSIGNED_SHORT, normalized = true, stride = 20, ptr = 0x10)
glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 0)
glBindBuffer(target = GL_ELEMENT_ARRAY_BUFFER, buffer = 7)
glUseProgram(program = 0)
glUseProgram(program = 6)
glUniformMatrix4fv(location = 2, count = 1, transpose = false, value = [1.6974937, 0.0, 0.0, 0.0, 0.0, 2.100419, -0.49304545, -0.49301255, 0.0, -1.1902374, -0.87008023, -0.8700222, -9.582167, -2.1815264, 15.627364, 15.64632])
glActiveTexture(texture = GL_TEXTURE0)
glBindTexture(target = GL_TEXTURE_2D, texture = 1)
glUniform1i(location = 8, x = 0)
glDisable(cap = GL_BLEND)
glBlendFunc(sfactor = GL_LINES, dfactor = GL_POINTS)
glEnable(cap = GL_DEPTH_TEST)
glUniformMatrix4fv(location = 7, count = 1, transpose = false, value = [50.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 50.0, 0.0, 0.0, -0.1, -150.0, 1.0])
glUniform3fv(location = 3, count = 1, v = [0.8235294, 0.8235294, 0.8235294])
glUniform2fv(location = 0, count = 1, v = [0.0, 0.0])
glUniform2fv(location = 1, count = 1, v = [1.0, 1.0])
glDrawElements(mode = GL_TRIANGLE_STRIP, count = 4, type = GL_UNSIGNED_BYTE, indices = 0x0)
答案 0 :(得分:3)
在解除绑定VAO之后,不应禁用顶点属性数组。在OpenGL 3核心上下文中,第二个取消绑定VAO,您不再具有要应用的顶点数组命令的上下文;你必须总是有一个VAO绑定或这些命令将是无效的操作。
此外,VAO持久存储顶点数组状态。这个想法不是每次绘制东西时都启用或禁用状态,而是绑定一个已经设置了所有必要状态的VAO。
以下是您应该如何考虑使用Vertex Array Objects设置顶点数组。由于VAO存储了大部分状态,因此您无需执行禁用顶点数组或取消绑定VBO以防止状态泄漏的操作。只要想要绘制不同的顶点数组,只需更改绑定的VAO即可。
阶段1: GL顶点数组/缓冲区对象初始化
When Mesh is Constructed: - Generate VAO, VBO, IBO - Bind VAO, VBO, IBO -> Upload Vertex Data to VBO -> Upload Index Array to IBO Foreach Attribute <n> - Setup Attrib Pointer (n) - Enable Attrib Array (n) End Foreach
第2阶段:绘制网格实例
When an Object (instance of Mesh) is Rendered: - Bind Mesh's VAO - Bind program/shader(id) -> send uniforms -> glDrawElements
此外,如果您的软件设置正确(例如,使用顶点阵列绘制的所有内容都有自己的VAO来管理状态),则实际上不需要解除绑定VAO。考虑应用纹理,在绘制内容后很少取消绑定纹理。你指望下一批你知道它需要什么样的纹理状态;如果它需要不同的纹理(或根本不需要),那么 it 应该是改变纹理状态的东西。在每批次之后恢复纹理状态是浪费资源,因此恢复顶点阵列状态。
在旁注中,我正在查看您的OpenGL跟踪并遇到了您可能不知道的事情。您正在使用GL_UNSIGNED_BYTE
索引,这些索引由API提供,但不一定由硬件支持。在许多硬件(例如任何桌面GPU)上GL_UNSIGNED_SHORT
是首选索引类型(即使对于非常小的顶点集合)。很容易假设使用GL_UNSIGNED_BYTE
会节省空间,因此当你的顶点数少于256时会增加吞吐量,但它实际上可以让你离开“快速路径”。如果硬件不支持8位索引,那么驱动程序不可避免地必须在提交之后将索引转换为16位。在这种情况下,它会增加驱动程序的工作量,并且不会遗漏任何GPU内存。
答案 1 :(得分:0)
如果在调用glVertexAttribPointer时缓冲区绑定到GL_ARRAY_BUFFER,则指针将被视为缓冲区内的偏移量。否则它被认为是指向系统内存的指针。因此,如果没有缓冲区绑定并且您传递了无效指针(例如零(期望绑定了缓冲区)),GL会尝试无效读取并且程序崩溃。
glDrawElements也是如此,如果缓冲区绑定到GL_ELEMENT_ARRAY_BUFFER,则指针参数将被视为缓冲区内的偏移量。
这里,GL_ARRAY_BUFFER缓冲区只需要在gl * Spinter()调用期间绑定gl * Pointer()和GL_ELEMENT_ARRAY_BUFFER。
启用客户端状态调用glEnableVertexAttribArray而不提供指针也会导致崩溃。
修改强>
我相信VAO只是记录顶点属性数组,绑定缓冲区和指向这些缓冲区的指针的配置。要使用,请在设置所有内容之前绑定VAO,就像打算进行绘制调用一样,然后取消绑定。现在,当你绑定那个VAO时,状态就会恢复,你可以简单地进行一次绘制调用而不需要大量的GL调用。
bind VAO
for each attrib,
call glEnableVertexAttribArray //in the next draw call, use the VBO I'm about to set up.
bind VBO
call glVertexAttribPointer //use data in bound VBO with size,stride,offset
unbind VBOconfig
end for
unbind VAO
//not certain but are attrib arrays still enabled after unbinding VAO (maybe disabling is unnecessary)
现在进行绘制调用,绑定VAO,绘制(),解除绑定。
最后,对于glEnableVertexAttribArray和glVertexAttribPointer我不知道,但索引是否需要是统一变量位置?