我今天刚刚开始从本教程学习OpenGL:http://openglbook.com/the-book/
我到了第2章,在那里我画了一个三角形,除了VAOs(这个首字母缩写OK吗?),我理解了所有的东西。教程中有以下代码:
glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);
虽然我理解代码是必要的,但我不知道它是做什么的。虽然我从来不使用VaoId超过这一点(除了破坏它),但是没有它代码就不起作用。我假设这是因为它被要求绑定,但我不知道为什么。这个确切的代码仅仅需要成为每个OpenGL程序的一部分吗?本教程将VAOs解释为:
顶点数组对象(或VAO)是描述顶点属性如何存储在顶点缓冲区对象(或VBO)中的对象。这意味着VAO不是存储顶点数据的实际对象,而是顶点数据的描述符。顶点属性可以由glVertexAttribPointer函数及其两个姊妹函数glVertexAttribPointer和glVertexAttribPointer描述,下面我们将讨论第一个。
我不明白VAO是如何描述顶点属性的。我没有以任何方式描述过它们。它是否从GLVertexAttribPointer获取信息?我猜肯定就是这个了。VAO仅仅是来自GLVertexAttribPointer的信息的目的地吗?
顺便说一句,我现在遵循的教程可以接受吗?有什么是我应该注意的或者更好的教程可以遵循的吗?
“顶点数组对象”是由OpenGL ARB小组委员会为你带来的傻名字。
把它想象成一个几何对象。(作为一个老的SGI执行程序程序员,我把它们称为Geosets.)对象的实例变量/成员是你的顶点指针,法线指针,颜色指针,attrib N指针,。。。
第一次绑定VAO时,通过调用
glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer...;
glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer...;
等等。已启用的属性和您提供的指针存储在VAO中。
之后,当您再次绑定VAO时,所有这些属性和指针也将变为当前值。因此,一个GLBindVertexArray
调用相当于以前设置所有属性所需的所有代码。它可以方便地在函数或方法之间传递几何图形,而不必创建自己的结构或对象。
(一次设置,多次使用是使用VAO最简单的方法,但是您也可以只通过绑定它和执行更多的启用/指针调用来更改属性。VAO不是常量。)
更多关于Patrick问题的信息:
新创建的VAO的默认值为空(AFAIK)。没有几何图形,甚至没有顶点,所以如果你试图绘制它,你会得到一个OpenGL错误。这是合理的,就像“初始化一切到false/null/zero”一样。
您只需要在进行设置时GlenableClientState
。VAO记住每个指针的启用/禁用状态。
是的,VAO将存储GlenableVertexAttriBarray
和GlVertexAttrib
。旧的顶点,法线,颜色,。。。数组与属性数组相同,顶点==#0等等。
我一直认为VAO是OpenGL使用的数据缓冲区数组。使用现代OpenGL,您将创建一个VAO和顶点缓冲区对象。
//vaoB is a buffer
glGenVertexArrays(1, vaoB); //creates one VAO
glBindVertexArray(vao.get(0));
glGenBuffers(vbo.length, vbo, 0); //vbo is a buffer
glBindVertexArray(vao.get(1));
glGenBuffers(vbo1.length, vbo1, 0); //vbo1 is a buffer
glBindVertexArray(vao.get(2));
glGenBuffers(vbo2.length, vbo2, 0); //vbo2 is a buffer
下一步是将数据绑定到缓冲区:
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER,vertBuf.limit()*4, vertBuf, GL_STATIC_DRAW); //vertf buf is a floatbuffer of vertices
在这一点上,OpenGL看到:
现在我们可以使用glVertexAttribPointer告诉OpenGL缓冲区中的数据代表什么:
glBindBuffer(GL_ARRAY_BUFFER, 0); //bind VBO at 0
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0); //each vertex has 3 components of size GL_FLOAT with 0 stride (space) between them and the first component starts at 0 (start of data)
OpenGL现在在缓冲区中拥有数据,并且知道数据是如何组织成顶点的。同样的过程可以应用于纹理坐标等,但对于纹理坐标,将有两个值。
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER,coordBuf.limit()*4, coordBuf, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
接下来你可以绑定纹理和绘制数组,你会想要创建一个垂直和碎片着色器,编译并附加到一个程序(这里不包括)。
glActiveTexture(textureID); //bind our texture
glBindTexture(GL_TEXTURE_2D, textureID);
glDrawArrays(GL_TRIANGLES,0,6); //in this case 6 indices are used for two triangles forming a square
顶点数组对象就像字处理程序中的宏等等。这里有一个很好的描述。
宏只会记住您所做的操作,例如激活这个属性,绑定那个缓冲区等。当您调用GLBindVertexArray(yourVAOId)
时,它只会简单地重放那些属性指针绑定和缓冲区绑定。
因此下一次调用draw使用VAO绑定的任何内容。
VAO不存储顶点数据。不。顶点数据存储在顶点缓冲区或客户端内存数组中。