OpenGL顶点缓冲区绑定点可以在不同的VAO中重用吗?

时间:2015-03-23 21:06:55

标签: 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上下文中;它们绑定不同的缓冲区,用于绘制不同的东西。

bindingIndex0是否需要与bindingIndex1不同?两个指数的平等(或不平等)是否有任何意义?

...

修改

在收到答案后,我开始明白,对于一个真正知道“顶点缓冲区绑定点”是什么的人,特别是它的范围是什么,我的问题可能似乎是在问一些与我的意图不同的东西。也许一个更好的措辞就是“为了防止冲突,是否需要尽量避免重复使用OpenGL顶点缓冲区绑定点索引,甚至跨多个VAO?”但无论如何,似乎现在已经回答了这两个问题:不,你不能重复使用“绑定点”,也不需要以这种方式避免索引冲突。

1 个答案:

答案 0 :(得分:6)

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

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

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

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

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

换句话说,旧式连接是:

attribute index --> buffer

这些4.3+来电的新风格:

attribute index --> buffer index --> buffer

这种新灵活性的一个优点是您可以通过一次调用将新缓冲区绑定到多个属性。只要所有这些属性具有相同的缓冲区索引,您只需要调用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]]

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