VAO 和 GL_ELEMENT_ARRAY_BUFFER 协会

VAO and GL_ELEMENT_ARRAY_BUFFER association

我无法理解 VAO 和绑定到 GL_ELEMENT_ARRAY_BUFFER 的缓冲区之间的关联(我们称之为 EBO)。我知道它是 VAO 状态的一部分,但不同于与 glVertexAttribPointer 调用一起使用的缓冲区(如果我理解正确的话,这些缓冲区只是被 VAO 记住,因为属性存储省略了绑定它们的需要)。
this 讨论中声称:

Unlike GL_ARRAY_BUFFER, a VAO store the current binding for GL_ELEMENT_ARRAY_BUFFER. Calling glBindBuffer(GL_ELEMENT_ARRAY_BUFFER) stores a reference to the specified buffer in the currently-bound VAO. glDrawElements() etc take the vertex indices from the buffer stored in the currently-bound VAO. So switching between VAOs switches between element arrays.

但是我是否需要在 VAO 的绑定和解除绑定之间调用 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER) 以确保它将 'save' 它处于其状态,或者 VAO 将在创建 VAO 时只获取当前绑定的 EBO?
另外,我不清楚上面引用的答案是 VAO 只是 'knows'(作为属性存储缓冲区)必须从哪些缓冲区索引(glDrawElements)中获取,还是当 VAO 绑定时 VAO 绑定正确的 EBO ?

编辑: 我的第一个问题已得到解答 ,但我相信第二个问题已由 @Rabbid76 回答。

如果设置正确,绘制时您应该只绑定 VAO。这就是重点,避免为每个几何图形重复调用 GL 驱动程序的 CPU 开销。

在初始设置期间,您应该创建并绑定一个 VAO,然后绑定所有属性缓冲区并使用 glVertexAttribPointer 描述它们,使用 glEnableVertexAttribArray 启用它们,最后绑定 GL_ELEMENT_ARRAY_BUFFER。之后,我会将 VAO 绑定到 null,这样您就不会在以下几行中意外绑定其他内容。

(注意属性缓冲区的glBindBuffer本身并没有直接记录到VAO中,而是在glVertexAttribPointer的调用处推断出来的。也就是说,当你调用glVertexAttribPointer时,当前绑定到GL_ARRAY_BUFFER的任何东西将是顶点拉动的 VAO 来源。)

在渲染循环期间,您应该绑定之前创建的不同 VAO。

这有点令人困惑,因为在实践中有时绑定 VAO 意味着 "I want to start recording a little macro"(在初始设置时),有时绑定 VAO 意味着 "I want you to play back all the bindings in that macro I recorded earlier"(在渲染时)。它在原始 RFC 中被描述为:

   The currently bound vertex array object is used for all commands
which modify vertex array state, such as VertexAttribPointer and
EnableVertexAttribArray; all commands which draw from vertex arrays,
such as DrawArrays and DrawElements; and all queries of vertex
array state.

https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_vertex_array_object.txt

另请参阅 GL 标准中的表 6.4 和 6.5,以准确了解存储在 VAO 结构中的字段:

https://www.khronos.org/registry/OpenGL/specs/gl/glspec32.core.pdf

Do I need to call glBindBuffer(GL_ELEMENT_ARRAY_BUFFER) between bind and unbind of VAO?

OpenGL specification (chapter 10.3. VERTEX ARRAYS) 明确表示:

A vertex array object is created by binding a name returned by GenVertexArrays with the command
void BindVertexArray( uint array ); array is the vertex array object name.
The resulting vertex array object is a new state vector, comprising all the state and with the same initial values listed in tables 23.3 and 23.4.
BindVertexArray may also be used to bind an existing vertex array object. If the bind is successful no change is made to the state of the bound vertex array object, and any previous binding is broken.

表 23.3 和 23.4 包含 ELEMENT_ARRAY_BUFFER_BINDING.

这意味着,GL_ELEMENT_ARRAY_BUFFER 必须在 绑定顶点数组对象 (glBindVertexArray) 之后
GL_ELEMENT_ARRAY_BUFFER对象的"name"存储在顶点数组对象状态向量中。
如果顶点数组对象已经解除绑定,又重新绑定,则GL_ELEMENT_ARRAY_BUFFER为也被认识并再次受到约束。


注意,glBufferData 为缓冲区对象创建了一个新的数据存储。 glBufferData 删除任何现有的数据存储,并设置缓冲区对象的状态变量的值。这意味着,在您关联新数据之前,数据与缓冲区对象相关联。 - 参见 Khronos reference page glBufferData and OpenGL 4.6 API Compatibility Profile Specification; 6.1 Creating and Binding Buffer Objects