什么是顶点数组对象?

我刚从本教程开始学习OpenGL: http : //openglbook.com/the-book/
我到了第二章,画了一个三angular形,除了VAO,我明白了所有的一切(这个缩写是好的吗?)。 教程有这样的代码:

glGenVertexArrays(1, &VaoId); glBindVertexArray(VaoId); 

虽然我明白代码是必要的,但我不知道它做了什么。 尽pipe我从来没有使用VaoId(除了销毁它),但代码在没有它的情况下不能运行。 我假设这是因为它需要绑定,但我不知道为什么。 这个确切的代码是否需要成为每个OpenGL程序的一部分? 该教程将VAO解释为:

顶点数组对象(或VAO)是描述如何将顶点属性存储在顶点缓冲对象(或VBO)中的对象。 这意味着VAO不是存储顶点数据的实际对象,而是顶点数据的描述符。 顶点属性可以用glVertexAttribPointer函数及其两个姐妹函数glVertexAttribIPointer和glVertexAttribLPointer来描述,我们将在下面探讨其中的第一个。

我不明白VAO如何描述顶点属性。 我没有以任何方式描述它们。 它是否从glVertexAttribpointer获取信息? 我想这一定是它。 VAO只是来自glVertexAttribPointer的信息的目的地吗?

请注意,我接受的教程是否可以接受? 有什么我应该注意的或更好的教程要遵循?

“顶点数组对象”由OpenGL ARB小组委员会为您提供。

把它看作一个几何对象。 (作为一个旧时代的SGI Performer程序员,我称它们为geosets)。对象的实例variables/成员是你的顶点指针,正常指针,颜色指针,attrib N指针,…

首先绑定一个VAO,然后通过调用来分配这些成员

 glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer...; glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer...; 

等等。 哪些属性被启用,你提供的指针存储在VAO中。

之后,当你再次绑定VAO时,所有这些属性和指针也变成最新的。 因此,一个glBindVertexArray调用等同于以前需要设置所有属性的所有代码。 在函数或方法之间传递几何graphics是很方便的,而不必创build自己的结构或对象。

(一次性设置,多次使用是使用VAO的最简单的方法,但是您也可以通过绑定来更改属性,并进行更多的使能/指针调用.VAO不是常量。

更多信息回复帕特里克的问题:

新创build的VAO的默认值是空的(AFAIK)。 根本没有几何体,甚至没有顶点,所以如果你试图绘制它,你会得到一个OpenGL的错误。 这是相当理智的,如“初始化一切为False / NULL /零”。

你只需要设置glEnableClientState 。 VAO记住每个指针的启用/禁用状态。

是的,VAO将存储glEnableVertexAttribArrayglVertexAttrib 。 旧的顶点,普通,颜色,…数组与顶点==#0等属性数组相同。

顶点数组对象就像文字处理程序中的macros一样。 这里有一个很好的描述。

macros只记得你所做的动作,比如激活这个属性,绑定这个缓冲区等等。当你调用glBindVertexArray( yourVAOId ) ,它只是重放那些属性指针绑定和缓冲绑定。

所以你下一次的抽签决定了VAO所使用的任何东西。

VAO不存储顶点数据 。 不可以。顶点数据存储在顶点缓冲区或客户端内存数组中。

VAO是一个代表OpenGLstream水线的顶点提取阶段的对象,用于向顶点着色器提供input。

你可以像这样创build顶点数组对象

 GLuint vao; glCreateVertexArrays(1, &vao); glBindVertexArray(vao); 

首先让我们做一个简单的例子。 在着色器代码中考虑这样一个input参数

 layout (location = 0) in vec4 offset; // input vertex attribute 

要填写这个属性,我们可以使用

 glVertexAttrib4fv(0, attrib); // updates the value of input attribute 0 

尽pipe顶点数组对象为您存储了这些静态属性值,但它可以做更多的事情。

创build顶点数组对象后,我们可以开始填充它的状态。 我们将要求OpenGL使用存储在我们提供的缓冲区对象中的数据自动填充它。 每个顶点属性都可以从绑定到几个顶点缓冲区绑定之一的缓冲区中获取数据。 为此,我们使用glVertexArrayAttribBinding(GLuint vao, GLuint attribindex, GLuint bindingindex) 。 我们还使用glVertexArrayVertexBuffer()函数将缓冲区绑定到其中一个顶点缓冲区绑定。 我们使用glVertexArrayAttribFormat()函数来描述数据的布局和格式,最后通过调用glEnableVertexAttribArray()启用属性的自动填充。

当一个顶点属性被启用时,OpenGL会根据你提供的格式和位置信息glVertexArrayVertexBuffer()glVertexArrayAttribFormat()向顶点着色器提供数据。 当属性被禁用时,顶点着色器将被提供给你提供的静态信息,并调用glVertexAttrib*()

 // First, bind a vertex buffer to the VAO glVertexArrayVertexBuffer(vao, 0, buffer, 0, sizeof(vmath::vec4)); // Now, describe the data to OpenGL, tell it where it is, and turn on automatic // vertex fetching for the specified attribute glVertexArrayAttribFormat(vao, 0, 4, GL_FLOAT, GL_FALSE, 0); glEnableVertexArrayAttrib(vao, 0); 

并在着色器中编码

 layout (location = 0) in vec4 position; 

毕竟你需要调用glDeleteVertexArrays(1, &vao)


你可以阅读OpenGL SuperBible来更好地理解它。