¿Cuál es el propósito de los objetos de matriz de vértices de OpenGL?

36

Acabo de comenzar con OpenGL. Todavía no entiendo qué son los objetos Vertex Array y cómo se pueden emplear.

Si se usan objetos de búfer de vértices para almacenar datos de vértices (como sus posiciones y coordenadas de textura) y los VAO solo contienen indicadores de estado, ¿dónde se pueden usar? ¿Cuál es su propósito?

Por lo que entendí del GL Wiki (muy incompleto y poco claro), los VAO se usan para establecer las banderas / statūs para cada vértice, siguiendo el orden descrito en el Elemento Array Buffer, pero el wiki fue realmente ambiguo al respecto y yo ' No estoy muy seguro de lo que realmente hacen los VAO y cómo podría emplearlos.

Vaillancourt
fuente

Respuestas:

49

Creo que comprenderá mejor su propósito con una muestra. Al leer los comentarios, comprenderá cómo se utilizan los 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
Pombal
fuente
2
¿Puedo hacer esto con los datos del búfer GL_DYNAMIC_DRAW también? ¿La parte de representación solo contendría glBindVertexArray (), glBufferData () y luego glDrawElements ()?
Piku
¿Cómo manejas las normales en este ejemplo? Quiero decir, ¿qué pasa si agregas un GLfloat normal[3]en tu clase Vertex y quieres subir los normales al cliente?
linello
1

Los VAO son útiles, ya que no tiene que configurar cada vez todos los atributos. También debería ser más rápido, solo vincula un VAO en lugar de establecer todos los atributos.

zacharmarz
fuente
1

Este es mi enlace favorito: http://www.songho.ca/opengl/gl_vertexarray.html

Debería ayudarlo a comprender mejor las diferencias entre VAO y VBO. Además, recomendaría leer un capítulo en OpenGL superbible sobre este tema. Hace un buen trabajo al explicar estos conceptos básicos en detalle y con ejemplos.

brainydexter
fuente
66
El artículo que vinculó no cubre VAO, solo matrices de vértices (que han existido por un tiempo más). Estoy desconcertando sobre las diferencias específicas entre estos dos yo mismo.
Steven Lu
No hay mucha diferencia El VAO simplemente encapsula todo el estado con respecto a las matrices de vértices y sus usos y formatos, excepto los datos de la matriz en sí, que se almacenan en VBO. Pero tiene razón en que esta respuesta (o el enlace) en realidad no habla de VAO.
Chris dice que reinstala a Mónica el