通过glBufferData()更新VBO(特别是它的大小)可能会改变它的物理内存地址,但不是glGenBuffers()设置的缓冲区对象名。 VBO通过调用glVertexAttribPointer()链接到VAO,其中有关VBO(缓冲区对象名称?存储器地址?)的信息存储在VAO中。 当通过glBindVertexArray()绑定时,VAO可用于更新和绘图。 GL当时是否重新计算VBO地址? 当链接到的VBO通过glBufferData()更新时,VAO可能绑定也可能不绑定。
根据缓冲区对象名称何时转换为物理内存地址,我可以想象只需在更改VBO后再次绑定VAO就可以为更改的VBO更新VAO;或者,可能需要通过再次调用glVertexAttribPointer()来更彻底地更新VAO。
这个问题的一部分是:关于VBO的哪些信息存储在VAO中?如果它只是缓冲区对象名称,则在更改VBO内容后不必再次调用glVertexAttribPointer()。
也许这些细节不是API规范的一部分,因此唯一安全的做法是在每次更新链接的VBO后通过glVertexAttribPointer()更新VAO。
答案 0 :(得分:7)
您不必担心这一点,因为VBO永远不会向您公开底层服务器内存空间。顶点属性指针相对于设置它们时绑定到GL_ARRAY_BUFFER
的对象的开头。
即使你通过调用glBufferData (...)
重新分配缓冲区(这会创建一个 new 数据存储,而不是像你的问题建议那样更新它),你的顶点属性指针也不会失效。这是因为它们实际上偏移到命名缓冲区的内存而不是任意地址;它需要两条信息(缓冲区名称 和 偏移量)来建立顶点指针。
GL_ARB_vertex_attrib_binding
:修改第2.9.6节,"缓冲区对象中的顶点数组"
从缓冲区对象中获取数组 时,顶点属性为< em> VERTEX_ATTRIB_BINDING指示使用哪个顶点缓冲区绑定。该 属性&rs; VERTEX_ATTRIB_RELATIVE_OFFSET和顶点的总和 缓冲区绑定的VERTEX_BINDING_OFFSET用作偏移量(基本的 机器单元)缓冲区数据存储中的第一个元素。
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使您可以自由地指定独立于顶点缓冲区的顶点属性格式(它不关心在设置属性格式时绑定到GL_ARRAY_BUFFER
的内容)。
当命令源数组内存(例如glDrawArrays (...)
)时间接计算地址。