OpenGL - 正确更新顶点数组对象的顶点缓冲区绑定

时间:2017-11-10 14:45:57

标签: c++ opengl shader vertex-buffer vertex-array-object

我注意到我的程序中有一个奇怪的错误,当我在调用glVertexArrayVertexBuffer后多次绑定VAO时会发生这种错误。在我的帧循环中,我通常有一个VAO用于一次绘制调用,但有时我想使用相同的VAO用于具有不同着色器的多个绘制调用。但这在我的实现中不起作用:

while(RUN){
    updateBuffers();//updates VAO
    drawThis();//binds and unbinds VAO
    drawThat();//binds and unbinds VAO -> OpenGL Invalid Operation error at draw call
}

虽然这有效:

while(RUN){
    updateBuffers();//updates VAO
    drawThis();//binds and unbinds VAO
    updateBuffers();//updates VAO
    drawThat();//binds and unbinds VAO -> works
}

这也行不通:

updateBuffers();
while(RUN){
    drawThis();//OpenGL Invalid Operation error in second frame
}

但这可行

updateBuffers();
glBindVertexArray(VAO);
while(RUN){
    drawThis();//only makes the draw call
}
glBindVertexArray(0);

...但这不是一个选项,因为我也想在我的帧循环中使用其他VAO(我希望保持灵活的顺序)。

那么这些功能在内部是做什么的?

draw函数只需绑定VAO和着色器,进行绘制调用(通常为glDrawElementsInstanced),然后取消绑定着色器和VAO。

updateBuffers函数通常通过指针写入缓冲区对象(使用glNamedBufferStorage初始化),该指针使用GL_MAP_WRITE_BITGL_MAP_PERSISTENT_BIT和{{1}映射整个缓冲区标志。为了确保我不会覆盖仍然由GPU使用的任何数据,我总是写入缓冲区的不同分区。因此,在每次更新之前,我将写入偏移量增加先前更新的大小(如果更新超过存储大小,则将其设置为0)。

因为着色器应该可以看到更新后的数据,所以我还必须更新着色器绑定的绑定点。我通过调用glBindBufferRange为均匀缓冲区(由均匀块使用)和glVertexArrayVertexBuffer为每个更新的顶点缓冲区(对于顶点属性)执行此操作,以使每个缓冲区的绑定偏移量从位置开始更新的数据。

这总是适用于统一缓冲区绑定(偏移量用glBindBufferRange更新)但是当我更新VAO的顶点缓冲区的绑定(使用glVertexArrayVertexBuffer)然后绑定并取消绑定该VAO在再次致电glVertexArrayVertexBuffer之前不止一次,我收到GL_MAP_COHERENT_BIT错误。

为什么glVertexArrayVertexBuffer导致VAO表现得像这样?更新VAO绑定到顶点缓冲区的偏移量的正确方法是什么?

0 个答案:

没有答案