OpenGL VAO最佳实践

use*_*129 77 opengl opengl-3 vao

我面临一个问题,我相信是VAO依赖的,但我不确定..

我不确定VAO的正确用法,我在GL初始化期间做的事情很简单

glGenVertexArrays(1,&vao)
Run Code Online (Sandbox Code Playgroud)

接下来是

glBindVertexArray(vao)
Run Code Online (Sandbox Code Playgroud)

后来,在我的绘图管道中,我只调用glBindBuffer(),glVertexAttribPointer(),glEnableVertexAttribArray()等等,而不关心初始绑定的VAO

这是正确的做法吗?

Rob*_*ani 88

VAO与VBO和纹理的行为方式类似.将单个VAO绑定到程序的整个长度将不会产生任何性能优势,因为您可能只是在没有VAO的情况下进行渲染.事实上,它可能会更慢,具体取决于实现如何在绘制时截取顶点属性设置.

VAO的要点是在初始化期间运行一次绘制对象所需的所有方法,并在主循环期间删除所有额外的方法调用开销.关键是要有多个VAO并在绘图时在它们之间切换.

在最佳实践方面,您应该如何组织代码:

initialization:
    for each batch
        generate, store, and bind a VAO
        bind all the buffers needed for a draw call
        unbind the VAO

main loop/whenever you render:
    for each batch
        bind VAO
        glDrawArrays(...); or glDrawElements(...); etc.
    unbind VAO
Run Code Online (Sandbox Code Playgroud)

这避免了绑定/解除绑定缓冲区的混乱并传递每个顶点属性的所有设置,并仅使用单个方法调用替换它,绑定VAO.

  • 绑定新的VAO取代了旧的VAO.在循环内部解除绑定只是额外的工作. (11认同)
  • 这不是必需的,但我通常会这样做,以防其他一些对象决定在没有VAO的情况下渲染(调试绘图/字体渲染库/等),因为这会(据我所知)替换当前绑定的VAO的属性设置. (3认同)
  • 为什么取消绑定仅发生一次并在循环之外发生?解除绑定是否不应该按批次进行? (2认同)
  • @RobertRouhani 那么最后解除绑定 VAO 有什么好处吗?(解除绑定没有影响吗?) (2认同)

Mār*_*iko 24

不,那不是你如何使用VAO.您应该以与使用VBO或纹理或着色器相同的方式使用VAO.首先进行设置.在渲染过程中只绑定它们,而不进行修改.

所以使用VAO你会做到以下几点:

void Setup() {
    glGenVertexArrays(..);
    glBindVertexArray(..);
    // now setup all your VertexAttribPointers that will be bound to this VAO
   glBindBuffer(..);
   glVertexAttribPointer(..);
   glEnableVertexAttribArray(..);
}

void Render() {
    glBindVertexArray(vao);
    // that's it, now call one of glDraw... functions
    // no need to set up vertex attrib pointers and buffers!
    glDrawXYZ(..)
}
Run Code Online (Sandbox Code Playgroud)

另见这些链接:

  • 应该在`glVertexAttribPointer(...)`之前调用`glEnableVertexAttribArray(...)`.一些司机(包括我的)_really_不喜欢它反过来. (2认同)
  • 赞成,因为大多数示例都不清楚您必须在 VAO 绑定期间调用 glEnableVertexAttribArray。 (2认同)

Nic*_*las 10

这是正确的做法吗?

是的,这是完全合法且有效的.好吗?好...

对这类事情进行了一些非正式的性能测试.看来,至少在测试过的NVIDIA硬件上,VAO的"正确"使用(即:其他人提倡的)在很多情况下实际上都比较慢.如果更改VAO不会更改绑定的缓冲区,则尤其如此.

据我所知,在AMD硬件上没有进行过类似的性能测试.一般来说,除非事情发生变化,否则这是VAO的可接受用途.

  • 当然,一旦每个VAO具有足够可跟踪的各种状态,那么在渲染循环中手动切换缓冲区和属性指针将需要进行多次调用,那么使用VAO可以使我们看到性能的提高吗? (2认同)