Jaki jest cel obiektów wierzchołków tablicy OpenGL?

36

Właśnie zacząłem od OpenGL. Nadal tak naprawdę nie rozumiem, czym są obiekty tablic wierzchołków i jak można je wykorzystać.

Jeśli obiekty bufora wierzchołków są używane do przechowywania danych wierzchołków (takich jak ich pozycje i współrzędne tekstury), a VAO zawierają tylko flagi stanu, gdzie można ich użyć? Jaki jest ich cel?

O ile rozumiem z (bardzo niepełnej i niejasnej) GL Wiki, VAO są używane do ustawiania flag / statūs dla każdego wierzchołka, zgodnie z kolejnością opisaną w buforze tablicy elementów, ale wiki była bardzo niejednoznaczna i ja ' Nie jestem pewien, co naprawdę robią VAO i jak mogę je zatrudnić.

Vaillancourt
źródło

Odpowiedzi:

49

Myślę, że dzięki próbce zrozumiesz ich cel. Czytając komentarze, zrozumiesz, w jaki sposób używane są 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
źródło
2
Czy mogę to zrobić również z danymi bufora GL_DYNAMIC_DRAW? Czy część renderująca zawierałaby tylko glBindVertexArray (), glBufferData (), a następnie glDrawElements ()?
Piku,
Jak radzisz sobie z normalnymi w tym przykładzie? Mam na myśli co jeśli dodasz a GLfloat normal[3]do klasy Vertex i chcesz załadować normalne do klienta?
linello
1

VAO są przydatne, ponieważ nie musisz konfigurować za każdym razem wszystkich atrybutów. Powinno być także szybsze, wystarczy powiązać jedno VAO, a nie ustawić wszystkie atrybuty.

zacharmarz
źródło
1

To jest mój ulubiony link: http://www.songho.ca/opengl/gl_vertexarray.html

Powinno to pomóc w lepszym zrozumieniu różnic między VAO i VBO. Ponadto polecam przeczytać rozdział w OpenGL znakomity na ten temat. Dobrze objaśnia te podstawowe zasady i podaje przykłady.

brainydexter
źródło
6
Artykuł, który podłączyłeś, nie obejmuje VAO, a jedynie tablice wierzchołków (które istniały nieco dłużej). Zastanawiam się nad konkretnymi różnicami między nimi.
Steven Lu,
Nie ma dużej różnicy. VAO po prostu podsumowuje wszystkie stany dotyczące tablic wierzchołków oraz ich zastosowań i formatów, z wyjątkiem samych danych tablicowych, które są przechowywane w VBO. Ale masz rację, że ta odpowiedź (lub link) tak naprawdę nie mówi o VAO.
Chris mówi Przywróć Monikę