OpenGL - Vertex Array Objects
-
Hallo,
ich versuche mich momentan an OpenGL und habe leichte Verständnisprobleme bzg. der Vertex Array Objects (VAO).
Werden die überhaupt noch gebraucht?In diesem Tutorial wird beispielsweise nicht ein einziges Mal glGenVertexArrays aufgerufen. Stattdessen wird mittels glBindBuffer(GL_ARRAY_BUFFER, buffer) gearbeitet, was laut der OpenGL Spec 4.1 auch das gleiche ist, wenn ich den folgenden Absatz richtig interpretiere:
glspec41.core Absatz 2.9.6 schrieb:
For example, the VertexAttribPointer command copies the value of ARRAY_BUFFER_BINDING (the queriable name of the buffer binding corresponding to the target ARRAY_BUFFER) to the client state variable VERTEX_-ATTRIB_ARRAY_BUFFER_BINDING for the specified index.
Gruß,
OGL
-
Nein, schau in den deprecated Bereich:
Wenn kein VAO gesetzt wird, wird als default das VAO mit Index 0 genommen. Das VAO 0 ist aber deprecated.
Seite 417 der gl 4.1 spec:
"Calling VertexAttribPointer when no buffer object or no vertex array object is bound will generate an INVALID_OPERATON error, as will calling any array drawing command when no vertex array object is bound"Die im Tutorial aufgerufenen befehle sind Korrekt. der Array_Buffer ist ein ganz bestimmter Buffertyp der von VAOs verwendet wird.
-
Ich denke du bringst hier ein Paar Dinge durcheinander. In OpenGL gibts mittlerweile Vertex Arrays (VAs), Vertex Buffer Objects (VBOs) und Vertex Array Objects (VAOs). Erstere stammen noch aus dem vorigen Jahrtausend. Letzere sind gerade eben erst neu dazugekommen. Unter VAs versteht man im Prinzip wenn du einfach einen Zeiger auf ein normales C Array (im RAM) an glVertexPointer() etc. übergibst und dann z.B. ein glDrawArrays() machst. Das ist gerade mal eine Stufe besser als glBegin(), glVertex3f() und dem restlichen uralten Kram. VBOs erlauben es dir Vertexdaten wenn möglich direkt im VRAM der Grafikkarte oder z.B. im GART Memory (aka AGP Memory) abzulegen, das ist was man heutzutage verwendet. VAOs dienen jetzt einfach nur dazu den ganzen State der mit der Verwendung von VBOs verbunden ist in einem Object abzulegen sodass du nicht ständig immer wieder glBindBuffer(), glVertexAttribPointer(), glEnableVertexAttrib(), usw. aufrufen musst sondern einfach nurmehr das VAO bindest und damit all den darin gespeicherten State für die Vewendeung von VBOs mit einem API call setzen kannst.
-
Danke für die Antworten! Langsam kommt Licht ins Dunkel.
Nur um zu überprüfen, ob ich es verstanden habe:
Ich nehme mal an ich hätte eine Klasse RenderObject. Dann könnte ich erstmal ein VAO dafür erstellen und binden, danach die dazugehörigen Vertices, Normalen, etc. laden und an die Shader binden (glVertexAttribPointer). Diese ganzen Bindings werden im aktuell gebundenen VAO gespeichert (könnte z.B. Membervariable des RenderObjects sein).
Wenn ich dann später ein bestimmtes RenderObject rendern will, muss ich einfach nur dessen VAO binden und die ganzen Bindings zu den Shadern werden automatisch wieder geladen.Ist das soweit korrekt?
Wenn kein VAO gesetzt wird, wird als default das VAO mit Index 0 genommen. Das VAO 0 ist aber deprecated.
D.h. der Code im Tutorial nutzt eigentlich Funktionalität, die deprecated ist (das Default-VAO)?
Gruß,
OGL
-
OGL schrieb:
Danke für die Antworten! Langsam kommt Licht ins Dunkel.
Nur um zu überprüfen, ob ich es verstanden habe:
Ich nehme mal an ich hätte eine Klasse RenderObject. Dann könnte ich erstmal ein VAO dafür erstellen und binden, danach die dazugehörigen Vertices, Normalen, etc. laden und an die Shader binden (glVertexAttribPointer). Diese ganzen Bindings werden im aktuell gebundenen VAO gespeichert (könnte z.B. Membervariable des RenderObjects sein).
Wenn ich dann später ein bestimmtes RenderObject rendern will, muss ich einfach nur dessen VAO binden und die ganzen Bindings zu den Shadern werden automatisch wieder geladen.Ist das soweit korrekt?
Ja - ist korrekt.
Man würde dann wohl eine render-Methode von RenderObject aufrufen, in der das VAO gebunden wird, die draw-calls gemacht werden und anschliessend die Bindung wieder gebrochen wird.OGL schrieb:
D.h. der Code im Tutorial nutzt eigentlich Funktionalität, die deprecated ist (das Default-VAO)?
Nein - es werden einfach keine VAOs genutzt - und das ist völlig legitim.
otze schrieb:
Nein, schau in den deprecated Bereich:
Wenn kein VAO gesetzt wird, wird als default das VAO mit Index 0 genommen. Das VAO 0 ist aber deprecated.
Kann ich aus den specs nicht erkennen. Wie willst du sonst das binding zu einem VAO wieder brechen?
Auszuag aus Specs 4.1 core profile - E.2.2 Removed Features:Application-generated object names - the names of all object types, such as
buffer, query, and texture objects, must be generated using the corresponding
Gen* commands. Trying to bind an object name not returned by a Gen*
command will result in an INVALID_OPERATION error. This behavior is already
the case for framebuffer, renderbuffer, and vertex array objects. Object
types which have default objects (objects named zero), such as vertex array,
framebuffer, and texture objects, may also bind the default object, even
though it is not returned by Gen.*
-
Ich hab auch eine Frage zu VAOs, welche aber mit dem ursprünglichen Problem nichts zu tun hat:
Und zwar möchte ich gerne OpenGL 3.3 Core lernen und habe auch ein kleines Tutorial gefunden.
Der Aufbau ist in etwa so:
main() lege shader und programm an, nutze dieses lege float array an und erzeuge vao while running: clear GLDrawArrays()
Es wird ein Viereck dargestellt. Nun ist meine Frage wie ich ein zweites Viereck zeichnen könnte.
Was funktioniert hat war:
main() lege shader und programm an, nutze dieses while running: clear lege float array an und erzeuge vao GLDrawArrays() lege neues float array an und ninde an die selbe vao-variable GLDrawArrays()
Ich bin mir aber nicht sicher ob das so gut oder erwünscht ist,
vielleicht sollte ich mir die vielen DrawArrays sparen und einfach neue Punkte anhängen?
Oder soll ich gar mehrere vao erzeugen?Naja ich kenn mich leider nocht nicht so gut aus und fand
glBegin() und End() schön übersichtlich, aber ich will mal was aktuelleres lernenWenn ihr Beispielcode habt nehm ich den gerne an, auch grob skizziert wie ich es getan hab ist ok
-
inter2k3 schrieb:
OGL schrieb:
D.h. der Code im Tutorial nutzt eigentlich Funktionalität, die deprecated ist (das Default-VAO)?
Nein - es werden einfach keine VAOs genutzt - und das ist völlig legitim.
Nein, immer noch nicht. glspec 4.1 (eine Seite weiter als dein Zitat):
Client vertex and index arrays - all vertex array attribute and element array index pointers must refer to buffer objects. The default vertex array object (the name zero) is also deprecated. Calling VertexAttribPointer when no buffer object or no vertex array object is bound will generate an INVALID_OPERATON error, as will calling any array drawing command when no vertex array object is bound."
inter2k3 schrieb:
Kann ich aus den specs nicht erkennen. Wie willst du sonst das binding zu einem VAO wieder brechen?
Binding mit 0 brechen ist erlaubt, aber nicht die Verwendung oder Änderung. Stell es dir vor als wäre VAO 0 der "kein VAO" marker.
@nicht op
mach bitte einen eigenen Thread auf
-
Ich habs nun mal ausprobiert und was soll ich sagen:
Du hast recht - ich ziehe also meine Aussage zurück.Allerdings wird in dem Tutorial auch glut eingesetzt und ich bin mir nicht sicher, welches Profile standardmässig gewählt wird (ich tippe einfach mal auf compatibilty).
Daher ist es also kein Problem in dem Beispiel.