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.