6

假设我使用新的(从 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 重用?” 但无论如何,现在似乎这两个问题都得到了回答:不,你不能重用“绑定点”,不,你不需要以这种方式避免索引冲突。

4

1 回答 1

7

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

您在代码片段中使用的bindingIndex0andbindingIndex1值没有任何特殊含义。它们只是在您绑定到绑定索引的缓冲区与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]]

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

于 2015-03-24T02:59:07.410 回答