所有这些调用都会修改 VAO 状态。因此,您不能在 VAO 之间重复使用这些设置。您当然可以在多个 VAO 中将它们设置为相同,但是在设置每个 VAO 时必须进行一次必要的状态设置调用。
The bindingIndex0
and bindingIndex1
您在代码片段中使用的值没有任何特殊含义。它们只是在您绑定到绑定索引的缓冲区之间建立连接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
as:
CurrentVAO.bufferIndexBindings[CurrentVAO.attribBufferIndices[attribIndex]]
这也说明了我上面解释的间接,它在这里显示为对状态表的两级查找。