【问题标题】:VAO and GL_ELEMENT_ARRAY_BUFFER associationVAO 和 GL_ELEMENT_ARRAY_BUFFER 关联
【发布时间】:2018-02-18 09:43:58
【问题描述】:

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

与 GL_ARRAY_BUFFER 不同,VAO 存储 GL_ELEMENT_ARRAY_BUFFER 的当前绑定。调用 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER) 在当前绑定的 VAO 中存储对指定缓冲区的引用。 glDrawElements() 等从存储在当前绑定的 VAO 中的缓冲区中获取顶点索引。因此,在 VAO 之间切换会在元素数组之间切换。

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

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

【问题讨论】:

    标签: opengl language-agnostic


    【解决方案1】:

    我是否需要在绑定和取消绑定 VAO 之间调用 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER)

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

    通过绑定 GenVertexArrays 返回的名称来创建顶点数组对象 使用命令
    void BindVertexArray( uint array ); array 是顶点数组对象名称。
    生成的顶点数组对象是一个新的 状态向量,包含所有状态,并具有表 23.3 和 23.4 中列出的相同初始值。
    BindVertexArray 也可用于绑定现有的顶点数组对象。 如果绑定成功,则绑定顶点数组的状态不会发生变化 对象,并且之前的任何绑定都被破坏了

    表 23.3 和 23.4 包含 ELEMENT_ARRAY_BUFFER_BINDING

    这意味着,GL_ELEMENT_ARRAY_BUFFER 必须在 顶点数组对象已绑定 (glBindVertexArray) 之后绑定。
    GL_ELEMENT_ARRAY_BUFFER 对象的“名称”存储在顶点数组对象状态向量中。
    如果顶点数组对象已经解除绑定并再次绑定,则 GL_ELEMENT_ARRAY_BUFFER 也是已知的并再次绑定。


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

    【讨论】:

    • "如果顶点数组对象已经解除绑定并再次绑定,那么GL_ELEMENT_ARRAY_BUFFER 也是已知的并再次绑定。"并且在解除绑定 VAO 后,OpenGL 会重新绑定在绑定 VAO 之前绑定到 GL_ELEMENT_ARRAY_BUFFER 的缓冲区,或者来自 VAO 的缓冲区仍然绑定到此目标?
    【解决方案2】:

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

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

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

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

    这有点令人困惑,因为在实践中,有时绑定 VAO 意味着“我想开始录制一个小宏”(在初始设置时),有时绑定 VAO 意味着“我希望你播放其中的所有绑定我之前录制的宏”(在渲染时)。它在原始 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多