Was ist der Zweck von OpenGL Vertex Array Objects?


36

Ich habe gerade mit OpenGL angefangen. Ich habe immer noch nicht richtig verstanden, was Vertex-Array-Objekte sind und wie sie eingesetzt werden können.

Wenn Vertex Buffer Object zum Speichern von Vertex-Daten (wie z. B. deren Positionen und Texturkoordinaten) verwendet werden und die VAOs nur Statusflags enthalten, wo können sie verwendet werden? Was ist ihr Zweck?

Soweit ich aus dem (sehr unvollständigen und unklaren) GL-Wiki weiß, werden VAOs verwendet, um die Flags / Status für jeden Scheitelpunkt in der im Element-Array-Puffer beschriebenen Reihenfolge festzulegen. Ich bin mir nicht sicher, was VAOs wirklich tun und wie ich sie einsetzen könnte.

Antworten:


49

Ich denke, Sie werden ihren Zweck mit einer Probe besser verstehen. Wenn Sie die Kommentare lesen, werden Sie verstehen, wie VAOs verwendet werden.

// 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
Kann ich das auch mit GL_DYNAMIC_DRAW-Pufferdaten machen? Würde der Rendering-Teil nur glBindVertexArray (), glBufferData () und dann glDrawElements () enthalten?
Piku

Wie gehen Sie in diesem Beispiel mit Normalen um? Was ist, wenn Sie eine GLfloat normal[3]in Ihre Vertex-Klasse einfügen und die Normalen in den Client hochladen möchten?
Linello

1

VAOs sind nützlich, da Sie nicht jedes Mal alle Attribute einrichten müssen. Es sollte auch schneller sein, wenn Sie nur eine VAO binden und nicht alle Attribute festlegen.


1

Dies ist mein Lieblingslink: http://www.songho.ca/opengl/gl_vertexarray.html

Dies soll Ihnen helfen, die Unterschiede zwischen VAO und VBOs besser zu verstehen. Ich würde auch empfehlen, ein Kapitel in OpenGL superbible zu diesem Thema zu lesen. Es macht gute Arbeit, diese Grundlagen ausführlich und anhand von Beispielen zu erklären.


6
Der Artikel, den Sie verlinkt haben, behandelt nicht VAOs, sondern nur Vertex-Arrays (die schon eine Weile länger sind). Ich rätsele selbst über die spezifischen Unterschiede zwischen diesen beiden.
Steven Lu

Es gibt keinen großen Unterschied. Der VAO kapselt nur alle Zustände in Bezug auf die Vertex-Arrays und ihre Verwendungen und Formate, mit Ausnahme der Array-Daten selbst, die in VBOs gespeichert sind. Aber Sie haben Recht damit, dass diese Antwort (oder der Link) nicht wirklich über VAOs spricht.
Chris sagt Reinstate Monica

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.