通过 glBufferData() 更新 VBO(尤其是其大小)可能会更改其物理内存地址,但不会更改 glGenBuffers() 设置的缓冲区对象名称。 VBO 通过调用 glVertexAttribPointer() 链接到 VAO,其中有关 VBO 的信息(缓冲区对象名称?内存地址?)存储在 VAO 中。 当通过 glBindVertexArray() 绑定(bind) VAO 时,它就可用于更新和绘制。 GL当时是否重新计算VBO地址? 当 VAO 链接到的 VBO 通过 glBufferData() 更新时,VAO 可能会或可能不会被绑定(bind)。
根据缓冲区对象名称何时转换为物理内存地址,我可以想象,只需在更改 VBO 后再次绑定(bind) VAO 即可为更改后的 VBO 更新 VAO;或者,可能需要通过再次调用 glVertexAttribPointer() 来更彻底地更新 VAO。
所以这个问题的一部分是:VAO 中存储了有关 VBO 的哪些信息?如果只是缓冲区对象名称,则在更改 VBO 内容后无需再次调用 glVertexAttribPointer()。
也许这些细节不是 API 规范的一部分,因此唯一安全的做法是在每次更新链接的 VBO 后通过 glVertexAttribPointer() 更新 VAO。
最佳答案
您不必担心这一点,因为 VBO 永远不会向您公开底层服务器内存空间。顶点属性指针相对于绑定(bind)到 GL_ARRAY_BUFFER
的对象的开头在您设置它们时。
即使您通过调用 glBufferData (...)
重新分配缓冲区(这会创建一个新数据存储,而不是按照您的问题建议更新它),您的顶点属性指针不会失效。这是因为它们实际上是命名缓冲区内存中的偏移量,而不是任意地址;它需要两条信息(缓冲区名称和偏移量)来建立顶点指针。
更新:(引用实现细节)
以下内容来自 GL_ARB_vertex_attrib_binding
:
Modify Section 2.9.6, "Vertex Arrays in Buffer Objects"
block 引用>When an array is sourced from a buffer object, the vertex attribute's VERTEX_ATTRIB_BINDING indicates which vertex buffer binding is used. The sum of the attribute's VERTEX_ATTRIB_RELATIVE_OFFSET and the vertex buffer binding's VERTEX_BINDING_OFFSET is used as the offset (in basic machine units) of the first element in that buffer's data store.
bindingIndex = VERTEX_ATTRIB_BINDING[attribIndex]; buffer = VERTEX_BINDING_BUFFER[bindingIndex]; if (buffer->name != 0) { address = buffer->baseAddress + VERTEX_BINDING_OFFSET[bindingIndex] + VERTEX_ATTRIB_RELATIVE_OFFSET[attribIndex]; }
这段代码来自 OpenGL (4.3) 的扩展/版本,不属于原始讨论的一部分,但我认为值得一提,因为无论如何,这就是顶点属性指针在幕后工作的方式。新的 API 使您可以自由地指定独立于顶点缓冲区的顶点属性格式(它不关心在您设置属性格式时绑定(bind)到
GL_ARRAY_BUFFER
的内容)。当命令源数组内存(例如
glDrawArrays (...)
)时,地址是间接计算的。
关于opengl - 当我更新顶点缓冲区对象时,应该如何更新顶点数组对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27911630/