2012-08-06 11 views
80

Ich beginne gerade OpenGL heute von diesem Tutorial zu lernen: http://openglbook.com/the-book/
Ich kam zu Kapitel 2, wo ich ein Dreieck zeichne, und ich verstehe alles alles außer VAOs (ist diese Abkürzung OK?). Das Tutorial hat diesen Code:Was sind Vertex Array Objekte?

glGenVertexArrays(1, &VaoId); 
glBindVertexArray(VaoId); 

Ich verstehe zwar, dass der Code notwendig ist, ich habe keine Ahnung, was es tut. Obwohl ich VaoId niemals über diesen Punkt hinaus verwende (außer um es zu zerstören), funktioniert der Code ohne ihn nicht. Ich nehme an, dies ist, weil es erforderlich ist, gebunden zu sein, aber ich weiß nicht warum. Muss dieser genaue Code nur Teil jedes OpenGL-Programms sein? Das Lernprogramm erläutert VAOs als:

Ein Vertex-Array-Objekt (oder VAO) ist ein Objekt, das beschreibt, wie die Vertex-Attribute in einem Vertex Buffer-Objekt (oder VBO) gespeichert werden. Dies bedeutet, dass das VAO nicht das eigentliche Objekt ist, das die Eckendaten speichert, sondern der Deskriptor der Eckendaten. Vertex-Attribute können durch die glVertexAttribPointer-Funktion und ihre beiden Schwesterfunktionen glVertexAttribIPointer und glVertexAttribLPointer beschrieben werden, von denen die erste unten erläutert wird.

Ich verstehe nicht, wie der VAO die Vertex-Attribute beschreibt. Ich habe sie in keiner Weise beschrieben. Erhält es die Informationen vom glVertexAttribPointer? Ich denke, das muss es sein. Ist der VAO einfach ein Ziel für die Informationen von glVertexAttribPointer?

Nebenbei bemerkt, ist das Tutorial, dem ich folge, akzeptabel? Gibt es etwas, auf das ich achten sollte oder ein besseres Tutorial?

Antwort

77

"Vertex Array Object" wird Ihnen vom OpenGL ARB Subcommittee für Silly Names präsentiert.

Betrachten Sie es als ein Geometrieobjekt. (Als eine alte Zeit SGI Performer Programmierer, nenne ich sie Geosets.) Die Instanzvariablen/Mitglieder des Objekts sind Ihre Eckpunktzeiger, Normalzeiger, Farbzeiger, Attrib N Zeiger, ...

Wenn ein VAO zuerst ist gebunden, weisen Sie diese Mitglieder durch Aufruf

glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer...; 
glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer...; 

und so weiter zu. Welche Attribute aktiviert sind und welche Zeiger Sie liefern, ist im VAO hinterlegt.

Danach, wenn Sie den VAO erneut binden, werden alle diese Attribute und Zeiger auch aktuell. So ein glBindVertexArray Aufruf entspricht dem Code, der zuvor benötigt wurde, um alle Attribute einzurichten. Es ist praktisch, um Geometrie zwischen Funktionen oder Methoden zu übergeben, ohne eigene Strukturen oder Objekte erstellen zu müssen.

(Einmalige Einrichtung, Mehrfachnutzung ist der einfachste Weg, vaos zu verwenden, aber Sie können auch Attribute nur durch Bindung ändern und mehr aktivieren/Zeiger Anrufe zu tun. Vaos sind keine Konstanten.)

Mehr Informationen in Antwort auf Patricks Fragen:

Der Standardwert für ein neu erstelltes VAO ist, dass es leer ist (AFAIK). Es gibt überhaupt keine Geometrie, nicht einmal Eckpunkte. Wenn Sie also versuchen, es zu zeichnen, erhalten Sie einen OpenGL-Fehler. Dies ist einigermaßen vernünftig, wie in "initialisiere alles auf False/NULL/Zero".

Sie müssen nur glEnableClientState, wenn Sie die Dinge einrichten. Der VAO erinnert sich an den Aktivierungs-/Deaktivierungsstatus für jeden Zeiger.

Ja, der VAO speichert glEnableVertexAttribArray und glVertexAttrib. Die alten Vertex-, Normal-, Farb-, ... Arrays sind die gleichen wie die Attribut-Arrays, Vertex == # 0 und so weiter.

+41

'"Vertex Array Object" wird Ihnen vom OpenGL ARB Subcommittee für Silly Names präsentiert.' Ja, so ein dummer Name für ein ** Objekt **, das ** Vertex ** ** Array ** Bindings speichert. –

+0

Wenn ich Sie richtig verstehe, ruft 'glGenVertexArrays (1, & VaoId);' und 'glBindVertexArray (VaoId);' einen VAO mit vernünftigen Standardeinstellungen auf, um Sie vor 'glEnableClientState' zu schützen? Oder missverstehe ich dich völlig? In Zukunft werde ich wahrscheinlich sehr viel 'glEnableClientState' verwenden? – Patrick

+2

Sind VAOs überhaupt mit 'glVertexAttribPointer' verbunden? – Patrick

8

Vertex Array Objekte sind wie Makros in Textverarbeitungsprogrammen und dergleichen. Eine gute Beschreibung findet sich here.

Makros nur erinnern die Aktionen, die dieses Attribut haben, wie activate, binden diesen Puffer, etc. Wenn Sie glBindVertexArray(yourVAOId) nennen, es ist einfach Replays diese Attributzeigerbindungen und Pufferbindungen.

Also Ihr nächster Aufruf zum Zeichnen verwendet, was auch immer der VAO gebunden war.

VAO's nicht speichern Eckpunktdaten. Nein. Die Vertex-Daten werden in einem Vertex Puffer oder in einem Array von Client-Speicher gespeichert.

+12

-1: Sie sind nicht wie Makros. Wenn dies der Fall wäre, würde die Bindung eines neuen VAO die von einem vorherigen VAO aktivierten Vertex-Arrays nicht deaktivieren, es sei denn, der neue VAO hat Sie * explizit * mit der Deaktivierung dieser Arrays "registriert". VAOs, wie * alle * OpenGL-Objekte, enthalten * Status *, keine Befehle. Befehle ändern * einfach * den Status, aber Objekte werden mit dem Standardstatus festgelegt. Deshalb bindet ein neu erstelltes VAO * immer * alle Attribute ab. –

4

VAO ist ein Objekt, das die Vertex-Abrufstufe der OpenGL-Pipeline darstellt und dazu verwendet wird, dem Vertex-Shader eine Eingabe zu liefern.

Sie können Vertex-Array-Objekt wie dieses

GLuint vao; 
glCreateVertexArrays(1, &vao); 
glBindVertexArray(vao); 

Zuerst wollen wir tun, ein einfaches Beispiel erstellen. Betrachten wir einen solchen Eingabeparameter in einem Shader-Code

layout (location = 0) in vec4 offset; // input vertex attribute 

Um in diesem Attribut füllen wir Ihnen Objekt speichert

glVertexAttrib4fv(0, attrib); // updates the value of input attribute 0 

Obwohl die Vertex-Array diese statischen Attributwerte für verwenden können, kann es eine Menge tun Mehr.

Nach dem Erstellen des Vertex-Array-Objekts können wir damit beginnen, seinen Zustand zu füllen. Wir werden OpenGL bitten, es automatisch mit den Daten zu füllen, die in einem von uns bereitgestellten Pufferobjekt gespeichert sind. Jedes Vertex-Attribut ruft Daten von einem Puffer ab, der an eine von mehreren Vertex-Puffer-Bindungen gebunden ist. Zu diesem Zweck verwenden wir glVertexArrayAttribBinding(GLuint vao, GLuint attribindex, GLuint bindingindex). Außerdem verwenden wir die Funktion , um einen Puffer an eine der Vertex Buffer-Bindungen zu binden. Wir verwenden die glVertexArrayAttribFormat() Funktion, um das Layout und das Format der Daten zu beschreiben, und schließlich aktivieren wir das automatische Ausfüllen des Attributs durch Aufruf von glEnableVertexAttribArray().

Wenn ein Vertex-Attribut aktiviert ist, wird OpenGL-Feed Daten an den Vertex-Shader basierend auf dem Format und Standortinformationen Sie mit glVertexArrayVertexBuffer() und glVertexArrayAttribFormat() zur Verfügung gestellt haben. Wenn das Attribut deaktiviert ist, wird der Vertex-Shader mit den statischen Informationen versehen, die Sie mit einem Aufruf an glVertexAttrib*() bereitstellen.

// First, bind a vertex buffer to the VAO 
glVertexArrayVertexBuffer(vao, 0, buffer, 0, sizeof(vmath::vec4)); 

// Now, describe the data to OpenGL, tell it where it is, and turn on automatic 
// vertex fetching for the specified attribute 
glVertexArrayAttribFormat(vao, 0, 4, GL_FLOAT, GL_FALSE, 0); 

glEnableVertexArrayAttrib(vao, 0); 

Und Code in einem Shader

layout (location = 0) in vec4 position; 

Nachdem alle glDeleteVertexArrays(1, &vao) Sie anrufen müssen.


Sie können OpenGL SuperBible lesen, um es besser zu verstehen.

+2

Es ist gut zu sehen, dass Leute die Verwendung von OpenGL im DSA-Stil fördern. –