OpenGL的顶点数组对象的目的是什么?


36

我刚开始使用OpenGL,但我仍然还不太了解什么是“顶点数组对象”以及如何使用它们。

如果将“顶点缓冲对象”用于存储顶点数据(例如其位置和纹理坐标),并且VAO仅包含状态标志,则可以在哪里使用它们?他们的目的是什么?

据我从(非常不完整和不清楚)的GL Wiki所了解的那样,使用VAO遵循元素数组缓冲区中描述的顺序为每个顶点设置标志/状态,但是Wiki确实对此含糊不清,我我不确定VAO的实际功能以及如何使用它们。

Answers:


49

我认为您将通过样本更好地了解它们的目的。通过阅读注释,您将了解如何使用VAO。

// BEGIN INITIALIZATION
// Define some vertex data 
struct Vertex {
  GLfloat position[3];
  GLfloat texcoord[2];
};
Vertex vertexdata[NUM_VERTS] = { ... };
GLubyte indexdata[NUM_INDICES] = { 0, 1, 2, ... };

// Create and bind a VAO
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

// Create and bind a BO for vertex data
GLuint vbuffer;
glGenBuffers(1, &vbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vbuffer);

// copy data into the buffer object
glBufferData(GL_ARRAY_BUFFER, NUM_VERTS * sizeof(Vertex), vertexdata, GL_STATIC_DRAW);

// set up vertex attributes
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texcoord));

// Create and bind a BO for index data
GLuint ibuffer;
glGenBuffers(1, &ibuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer);

// copy data into the buffer object
glBufferData(GL_ELEMENT_ARRAY_BUFFER, NUM_INDICES * sizeof(GLubyte), indexdata, GL_STATIC_DRAW);

// At this point the VAO is set up with two vertex attributes
// referencing the same buffer object, and another buffer object
// as source for index data. We can now unbind the VAO, go do
// something else, and bind it again later when we want to render
// with it.

glBindVertexArray(0);

// END INITIALIZATION

// BEGIN RENDER LOOP

// This is it. Binding the VAO again restores all buffer 
// bindings and attribute settings that were previously set up
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, NUM_INDICES, GL_UNSIGNED_BYTE, (void*)0);

// END RENDER LOOP

2
我也可以使用GL_DYNAMIC_DRAW缓冲区数据来执行此操作吗?呈现部分仅包含glBindVertexArray(),glBufferData(),然后包含glDrawElements()吗?
Piku

在此示例中,您如何处理法线?我的意思是,如果您GLfloat normal[3]在Vertex类中添加并想将法线上传到客户端,该怎么办?
linello

1

VAO很有用,因为您不必每次都设置所有属性。绑定一个VAO而不是设置所有属性也应该更快。


1

这是我最喜欢的链接:http : //www.songho.ca/opengl/gl_vertexarray.html

它应该可以帮助您更好地了解VAO和VBO之间的差异。另外,Id建议阅读OpenGL精讲中有关该主题的一章。它很好地详尽地解释了这些基础知识并提供了示例。


6
您链接的文章不涉及VAO,仅涉及顶点数组(已经存在了一段时间)。我对这两个我之间的具体差异感到困惑。
史蒂文·卢

没有太大的区别。VAO只是封装了有关顶点数组及其用法和格式的所有状态,除了数组数据本身(存储在VBO中)。但是您是对的,因为这个答案(或链接)并未真正提及VAO。
克里斯说莫妮卡(Monica)恢复2012年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.