opengl - OpenGL 顶点缓冲区绑定(bind)点可以在不同的 VAO 之间重用吗?

标签 opengl vao

假设我使用新的(从 OpenGL 4.3 开始)glBindVertexBuffer 机制设置了两个 VAO:

glGenVertexArrays(1, &vaoIndex0);
glGenVertexArrays(1, &vaoIndex1);

...

glBindVertexArray(vaoIndex0)
glBindVertexBuffer(bindingIndex0, ...)
glEnableVertexAttribArray(0)
glVertexAttribFormat(0, ...)
glVertexAttribBinding(0, bindingIndex0)
...
glBindVertexArray(0)

...

glBindVertexArray(vaoIndex1)
glBindVertexBuffer(bindingIndex1, ...)
glEnableVertexAttribArray(0)
glVertexAttribFormat(0, ...)
glVertexAttribBinding(0, bindingIndex1)
...
glBindVertexArray(0)

假设两者是独立的,除非它们存在于相同的 OpenGL 上下文中;它们绑定(bind)不同的缓冲区并用于绘制不同的东西。

绑定(bind)索引0 是否需要与绑定(bind)索引1 不同?两个指数相等(或不相等)有什么意义吗?

...

编辑:

收到答案后,我开始明白,对于真正知道什么是“顶点缓冲区绑定(bind)点”,特别是其范围是什么的人来说,我的问题似乎提出了与我的意图不同的问题。也许更好的措辞是“是否需要特意阻止 OpenGL 顶点缓冲区绑定(bind)点索引被重用,甚至跨多个 VAO,以防止冲突?”但无论如何,似乎这两个问题现在都已得到解答:不,您不能重用“绑定(bind)点”,并且您不需要以这种方式避免索引冲突。

最佳答案

所有这些调用都会修改 VAO 状态。因此,您不能在 VAO 之间重复使用这些设置。您当然可以在多个 VAO 中将它们设置为相同,但是在设置每个 VAO 时必须进行一次必要的状态设置调用。

您在代码片段中使用的 bindingIndex0bindingIndex1 值没有任何特殊含义。它们只是在您使用 glBindVertexBuffer() 绑定(bind)到绑定(bind)索引的缓冲区与您指定为使用该绑定(bind)索引的属性之间建立连接。

唯一的条件是绑定(bind)索引必须小于可以查询为 MAX_VERTEX_ATTRIB_BINDINGS 的值,该值保证至少为 16。由于这些调用会修改每个 VAO 状态,因此您可以绝对可以对多个 VAO 使用相同的绑定(bind)索引。

查看这些较新的状态设置调用的一种方法是,它们引入了以前不可用的间接级别:

  • 如果没有这些调用,您可以在绑定(bind)所需缓冲区时调用 glVertexAttribPointer(),在顶点属性和缓冲区之间建立直接连接。
  • 通过这些新的调用,顶点属性现在可以与绑定(bind)索引建立连接,该连接是通过 glVertexAttribBinding() 建立的。然后,绑定(bind)索引连接到一个缓冲区,该缓冲区是通过 glBindVertexBuffer() 建立的。

换句话说,在旧式中,连接是:

attribute index --> buffer

这些 4.3+ 调用的新样式:

attribute index --> buffer index --> buffer

这种新灵 active 的一个优点是您可以通过一次调用将新缓冲区绑定(bind)到多个属性。只要所有这些属性都具有相同的缓冲区索引,您只需调用一次 glBindVertexBuffer() 即可为所有属性指定一个新缓冲区。

半正式定义

以下内容根本不是官方符号。我刚刚弥补了。但我认为通过写下一些伪数据结构来更正式地定义关系可能会很有用。

假设每个 VAO 包含两个数组来捕获上面解释的连接:

struct VAO {
    ...
    uint bufferIndexBindings[MAX_VERTEX_ATTRIB_BINDINGS];
    uint attribBufferIndices[MAX_VERTEX_ATTRIBS];
}

这里讨论的两个调用将修改这个结构,如下所示:

glBindVertexBuffer(uint bindingIndex, uint buffer, ...) {
    CurrentVAO.bufferIndexBindings[bindingIndex] = buffer;
}

glVertexAttribBinding(uint attribIndex, uint bindingIndex) {
    CurrentVAO.attribBufferIndices[attribIndex] = bindingIndex;
}

然后使用此状态来获取索引 attribIndex 的给定属性的缓冲区,如下所示:

CurrentVAO.bufferIndexBindings[CurrentVAO.attribBufferIndices[attribIndex]]

这也说明了我上面解释的间接,它在这里显示为状态表的两级查找。

关于opengl - OpenGL 顶点缓冲区绑定(bind)点可以在不同的 VAO 之间重用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29220416/

相关文章:

opengl - 条件语句会减慢着色器的速度吗?

opengl - GL_ARB_vertex_attrib_binding 和索引绘图

c++ - 是否有必要在每一帧绑定(bind)所有 VBO(和纹理)?

opengl - 为什么 glGetUniformLocation 让我失望?

c++ - 如何制作一个在使用时不会暂停我的程序的菜单?

c++ - Qt 4.7 - glTexSubImage2D 返回 GL_INVALID_OPERATION

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

opengl - OpenGL 中的线框

c++ - OpenGL VAO VBO 着色器困惑

c++ - 如何在 OpenGL 中创建网格并用线条绘制