opengl - 当我更新顶点缓冲区对象时,应该如何更新顶点数组对象?

标签 opengl

通过 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"

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/

相关文章:

OpenGL 透视

c++ - 旧版 OpenGL 纹理立方体

c++ - 为什么基本的镜面反射着色是流体,而不是锯齿状的?

opengl - 为什么 gl_ClipDistance[] 不起作用?

c++ - 使用 OpenGL 插入数据缓冲区?

qt - 如何旋转位图图像

c++ - 从 obj 文件绘制模型

opengl - 显式多重采样与 OpenGL 中的常规多重采样有何不同

opengl - '平滑' : no matching overloaded function found

c++ - OpenGL绘制多个对象的正确方法?