如您所知,这是OpenGL 4.3中引入的相对较新的功能。根据规范,属性和缓冲区之间的映射现在具有一定的间接性:
1. 每个属性都有一个属性,指定它使用哪个绑定索引。
2. 缓冲区绑定到绑定索引。
您可以将此视为两个表格:一个定义了从属性索引到绑定索引的映射,另一个定义了从绑定索引到缓冲区名称的映射。这两个表格都是VAO状态的一部分。
我认为这些可以完全独立地指定,并且可以按任何顺序进行指定。 glVertexAttribBinding()建立第一个关联,即属性索引和绑定索引之间的关联。 glBindVertexBuffer()建立了绑定索引和缓冲区名称之间的关联。
规范中的状态表确认了这一理解。 GL 4.4规范中的表23.4标题为“顶点数组对象状态”,列出了以下内容:
- VERTEX_ATTRIB_BINDING,可以使用glGetVertexAttribiv()查询,是给定属性索引的绑定索引的值。
- VERTEX_BINDING_BUFFER,可以使用glGetIntegeri_v()查询,是给定绑定索引的缓冲区名称的值。
基于此,回答您的具体问题:
创建时,VAO是否仅跟踪VBO索引(通过glBindVertexBuffer),还是跟踪绑定到这些索引的VBO名称?
它们都会跟踪。
我是否可以在绘制调用之前将不同的VBO绑定到索引0,并使用该VBO的内容?
是的,如果您将不同的VBO绑定到绑定索引0,则具有绑定索引0的所有属性都将使用该VBO的内容。
我发现很多示例在调用glVertexAttribFormat和glVertexAttribBinding之前先调用glBindVertexBuffer,如果VAO仅跟踪索引,则这不应该是必需的。
VAO跟踪所有这些调用设置的状态,因此使用它们作为设置VAO的一部分是有意义的。在VAO中跟踪整个顶点设置状态是拥有VAO的主要目的。它允许您在初始化期间仅设置一次状态,然后在绘制调用之前仅需要单个调用glBindVertexArray()即可再次设置整个状态。
glVertexAttribBinding
之后,它可以忘记索引值)。无论哪种方式,我的困惑都来自于OpenGL官方文档中的这一部分:https://www.opengl.org/wiki/Vertex_Specification#Multibind_and_separation。从中可以看到:“...在快速切换多个缓冲区的同时保持相同的格式...” - jorganderglVertexAttribPointer()
是定义属性的传统方式。我们在这里讨论的是OpenGL 4.3中引入的新的更灵活的方法。如果符合您的需求,您显然可以使用更简单的glVertexAttribPointer()
,因为它仍然可用于最新版本的OpenGL。 - Reto Koradi