理解顶点数组对象(glGenVertexArrays)

32

我对创建顶点数组对象(VAO)的意义感到困惑:

glGenVertexArrays(GLsizei n, GLuint *arrays);

glBindVertexArray(GLuint);

即使我没有创建VAO,我仍然可以创建缓冲对象(例如顶点),并使用glVertexAttribPointerglEnableVertexAttribArray描述该缓冲对象。

我的问题是,如果您不必实际创建VAO来描述缓冲对象中的数据,那么诸如《OpenGL超级圣经第5版》之类的资料为什么在创建VBO时还包括调用创建VAO的函数呢?它们只用于我尚未发现的更高级主题吗?还是我完全弄错了?

另外,我是在阅读维基百科关于VBO及其示例代码时遇到这个问题的,其中没有调用glGenVertexArrays()函数,但他们仍然使用glVertexAttribPointer()进行数据描述。维基百科VBO页面 -- 创建VAO的示例是用于什么目的?

3个回答

22

性能改进。

在许多情况下,在主机上设置属性需要进行大量的API调用,并且在实现中需要进行重要的验证。

只需进行所有这些操作一次,然后使用VAO将其分摊。

例如,可以查看Graham Sellers的分析以获取实际数据。


然而,它们有一个缺陷 - 它们无法在不同的上下文中共享,使得它们在游戏场景之外几乎没有用处。 - cmannett85
2
而且在GL4中,不使用VAOs已经成为过时的风格。因此,除了它们的优点之外,如果您想要向前兼容,还必须使用它们。 - Christian Rau
默认名称为0的VAO仍然可以在不生成VAO的情况下使用,因此在4.1中您不一定需要显式地生成它。但是,当然现在我更好地理解了,您应该这样做。 - bluth
4
“默认名称为0的VAO仍然可以在不生成VAO的情况下使用”:不,它不可以。根据OpenGL 3.1及以上版本的核心规范,不能这样做。如果您处于兼容模式下,则可以这样做。但在核心OpenGL中不行。请注意,NVIDIA没有正确实现规范的这部分内容,并允许0作为VAO。但是AMD遵循规范,因此如果您在其硬件上请求核心OpenGL上下文,则必须在程序中创建和绑定一个VAO。 - Nicol Bolas

17

假设你正在构建一个需要三个VBO的对象(例如各种渲染数据,例如位置、法线和一些高级特效参数)。每次你要绘制这个对象时,都需要绑定所有这些VBO并设置任何附加参数。如果使用VAO,你只需要使用一个调用(绑定顶点数组),这将为特定对象设置整个环境。


1
这个加上ShannonLiu的有趣比喻帮助我更好地理解了这个。 - Tek

7
答案并不像你想象的那么难。把它看作一个有趣的比喻就好了:VertexArrayObject 是老板,管理着几个员工,这些员工就是VetexBufferObjects

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接