Qual è lo scopo degli oggetti Vertex Array di OpenGL?


36

Ho appena iniziato con OpenGL. Non ho ancora capito cosa sono gli oggetti Vertex Array e come possono essere impiegati.

Se l'oggetto buffer vertici viene utilizzato per archiviare i dati del vertice (come le posizioni e le coordinate delle trame) e i VAO contengono solo flag di stato, dove possono essere utilizzati? Qual è il loro scopo?

Per quanto ho capito dal GL (molto incompleto e poco chiaro) GL Wiki, i VAO sono usati per impostare le bandiere / statu per ogni vertice, seguendo l'ordine descritto nell'Element Array Buffer, ma il wiki era davvero ambiguo al riguardo e io ' Non sono davvero sicuro di cosa facciano davvero i VAO e di come potrei impiegarli.

Risposte:


49

Penso che capirai meglio il loro scopo con un campione. Leggendo i commenti capirai come vengono utilizzati i 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
Posso farlo anche con i dati del buffer GL_DYNAMIC_DRAW? La parte di rendering conterrebbe solo glBindVertexArray (), glBufferData () e quindi glDrawElements ()?
— Piku,

Come gestisci le normali in questo esempio? Voglio dire, se aggiungi un GLfloat normal[3]nella tua classe Vertex e vuoi caricare le normali sul client?
— linello,

1

I VAO sono utili, perché non è necessario impostare ogni volta tutti gli attributi. Dovrebbe anche essere più veloce, basta associare un VAO anziché impostare tutti gli attributi.


1

Questo è il mio link preferito: http://www.songho.ca/opengl/gl_vertexarray.html

Dovrebbe aiutarti a comprendere meglio le differenze tra VAO e VBO. Inoltre, ti consiglio di leggere un capitolo di OpenGL superbamente illustrato su questo argomento. Fa un buon lavoro nel spiegare queste basi a lungo e con esempi.


6
L'articolo che hai collegato non copre gli array VAO, ma solo i vertici (che sono in circolazione da un po 'di più). Sto sconcertando le differenze specifiche tra questi due me stesso.
— Steven Lu

Non c'è molta differenza. Il VAO incapsula semplicemente tutto lo stato relativo agli array di vertici e ai loro usi e formati, ad eccezione dei dati dell'array stesso, che sono memorizzati nei VBO. Ma hai ragione nel dire che questa risposta (o il link) in realtà non parla di VAO.
— Chris dice che ripristini Monica il

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.