2012-08-06 134 views
80

我刚刚开始从本教程开始学习OpenGL:http://openglbook.com/the-book/
我到了第2章,绘制了一个三角形,并且我了解除了VAO之外的所有东西(这个缩写是否可以?)。本教程有这样的代码:什么是顶点数组对象?

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

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

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

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

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

回答

77

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

将其视为几何对象。 (作为旧时代的SGI Performer程序员,我称他们为geosets。)实例变量/对象的成员是你的顶点指针,普通指针,颜色指针,attrib N指针,...

当VAO是第一个请通过致电

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

等指定这些成员。哪些属性已启用,并且您提供的指针存储在VAO中。

之后,当您再次绑定VAO时,所有这些属性和指针也变为当前。所以一个glBindVertexArray调用相当于以前设置所有属性所需的所有代码。无需创建自己的结构或对象,便可在函数或方法之间传递几何图形。

(一次性设置,多次使用是使用VAOs最简单的方法,但你也可以只通过结合,并做更多的启用/指针调用更改属性。VAOs不是常量)。

更多的信息回应Patrick的问题:

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

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

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

+41

''顶点数组对象'由OpenGL ARB小组委员会为您提供。是的,一个存储**顶点** **数组**绑定的**对象**这样一个愚蠢的名字。 – 2012-08-06 01:34:26

+0

如果我正确地理解你,调用'glGenVertexArrays(1,&VaoId);'和'glBindVertexArray(VaoId);'创建一个VAO,并使用理智的默认值将你从'glEnableClientState'中解救出来?或者我完全误解了你?将来我会使用很多'glEnableClientState'吗? – Patrick 2012-08-06 02:13:49

+2

此外,所有与“glVertexAttribPointer”相关的VAOs – Patrick 2012-08-06 02:16:19

8

顶点数组对象在文字处理程序等中类似于。一个很好的描述被发现here

宏刚记得你做的动作,如激活该属性,绑定该缓冲区,等当你调用glBindVertexArray(yourVAOId),它只是重播这些属性指针绑定和绑定缓冲。

所以你下一次抽奖就会使用任何被VAO绑定的内容。

VAO的不存储顶点数据。不可以。顶点数据存储在顶点缓冲区中或存储在客户端存储器阵列中。

+12

-1:它们不像宏。如果是,则绑定新的VAO不会禁用先前VAO启用的顶点阵列,除非新的VAO已经“明确”记录*禁用这些阵列。 VAO与* all * OpenGL对象一样,保存* state *,而不是命令。命令只是改变*状态,但对象以默认状态设置。这就是为什么绑定新创建的VAO将总是禁用所有属性。 – 2013-07-23 22:14:45

4

VAO是一个对象,表示OpenGL流水线的顶点提取阶段,用于向顶点着色器提供输入。

您可以创建这样

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

首先,让我们的顶点数组对象”做了一个简单的例子。在着色器代码

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

为了填补这个属性考虑这样的输入参数,我们可以使用

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

虽然顶点数组对象存储这些静态的属性值 你,它可以做很多更多。

创建顶点数组对象后,我们可以开始填充其状态。我们将要求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以更好地理解它。

+2

很高兴看到有人推广使用DSA风格的OpenGL。 – 2016-01-10 21:53:04