Welcher Status ist in einem OpenGL Vertex Array Object (VAO) gespeichert und wie verwende ich das VAO richtig?

25

Ich habe mich gefragt, welcher Status in einem OpenGL VAO gespeichert ist. Ich habe verstanden, dass ein VAO einen Status enthält, der mit den Scheitelpunktspezifikationen von gepufferten Scheitelpunkten zusammenhängt (welche Attribute befinden sich in den Puffern und welche Puffer sind gebunden, ...). Um die korrekte Verwendung von VAOs besser zu verstehen, möchte ich genau wissen, welchen Status sie haben.


Wie ich davon ausgehe, sollten VAOs verwendet werden

Aus einfachen Beispielen habe ich verstanden, dass die korrekte Verwendung von VAOs wie folgt lautet:

Installieren

Generate VAO
BindVAO
---- Specify vertex attributes
---- Generate VBO's
---- BindVBO's
-------- Buffer vertex data in VBO's
---- Unbind VBO's
Unbind VAO

Rendern

Bind VAO
---- Draw
Unbind VAO

Ich gehe davon aus, dass zumindest die Vertex-Pufferbindungen und die Vertex-Attributspezifikationen in der VAO gespeichert sind. Ich bin mir jedoch nicht sicher, wie sich dieses Verwendungsmuster auf Situationen erstreckt, in denen (mehrere) Texturen und (mehrere) Shader-Programme ins Spiel kommen. Ist das aktive Shader-Programm in der VAO gespeichert? Und werden die Texturbindungen (mit ihren Sampling- / Wrapping-Einstellungen ) auch im VAO gespeichert? Das Gleiche gilt für Uniformen ?


Daher sind meine Fragen:

  • Welcher genaue Status ist in einem OpenGL VAO gespeichert ? (VBO-Bindungen, Attributspezifikationen, Active Shader-Programm, Texturbindungen, Einstellungen für Texturabtastung / -umhüllung, Uniformen ...?)
  • Wie verwende ich VAOs korrekt in einem komplexeren Rendering-Setup, in dem (mehrere) Texturen mit zugehörigen Sampling- / Wrapping-Einstellungen, (mehreren) Shader-Programmen und Uniformen beteiligt sind?
Jelle van Campen
quelle
1
VAO speichert Daten über Scheitelpunktattributpositionen. Es speichert auch IDs von VBOs, in denen diese Attribute enthalten sind. Sie müssen VBO nicht binden, wenn Sie etwas zeichnen. Sie müssen es binden, bevor Sie glVertexAttribPointer () aufrufen, wenn Sie VAO erstellen.
HolyBlackCat

Antworten:

18

VAO speichert Daten über Scheitelpunktattributpositionen. (Und einige andere Daten, die sich auf sie beziehen.)
"VBO bindings, active shader program, texture bindings, texture sampling/wrapping settings, uniforms"Sind völlig unabhängig davon.

Sie können fragen, warum es sich nicht an die VBO-Bindung erinnert. Da Sie VBO nicht binden müssen, um etwas zu zeichnen, müssen Sie es nur binden, wenn Sie VAO erstellen: glVertexAttribPointer(...)VAO merkt sich beim Aufrufen , an was VBO derzeit gebunden ist. Und VAO übernimmt Attribute von diesen VBOs, wenn Sie sie zeichnen, auch wenn diese VBOs derzeit nicht gebunden sind.


VAOs und VBOs müssen auch geringfügig anders verwendet werden:

Das wird nicht funktionieren

Generate VAO
BindVAO
---- Specify vertex attributes
---- Generate VBO's
---- BindVBO's
-------- Buffer vertex data in VBO's
---- Unbind VBO's
Unbind VAO

weil Sie VBO binden müssen, um Attributspeicherorte anzugeben.

Also solltest du es so machen:

Generate VAO
BindVAO
Generate VBO's
BindVBO's
Specify vertex attributes

Sie können die Daten von VBO jederzeit ändern, müssen sie jedoch vorher binden.

Und das Zeichnen sollte so aussehen:

Bind VAO
Draw


Wie Sie vielleicht bemerkt haben, habe ich unbindAnrufe von Ihren Listen entfernt. Sie sind fast völlig nutzlos und verlangsamen Ihr Programm ein wenig, daher sehe ich keinen Grund, sie aufzurufen.

HolyBlackCat
quelle
9
"Also sehe ich keinen Grund, sie anzurufen." um zu verhindern, dass sie versehentlich geändert werden. Besonders ein Problem bei der Verwendung von Bibliotheken von Drittanbietern.
Ratschenfreak
Vielen Dank für die tolle Antwort! Kurz gesagt, der VAO speichert nur die Vertex-Attributpositionen. VBOs werden beim Binden einer VAO nicht zurückgebunden, da die VAO weiß, in welchen Puffern die Attribute zu finden sind. Alle anderen Zustände sind im globalen OpenGL-Zustand enthalten.
Jelle van Campen
@ JellevanCampen Ja, richtig. Zu Ihrer Information , es speichert auch den Aus / Ein-Zustand von Attributen ( gl{Enable|Disable}VertexAttribArray()), ihre Standardwerte ( glVertexAttrib*()), ihren Instanzierungsmodus ( glVertexAttribDivisor()) und wahrscheinlich noch etwas anderes.
HolyBlackCat
@HolyBlackCat Sind Sie sicher, dass der Standardstatus (glVertexAttrib ()) Teil des VAO-Status ist? Das OpenGL-Wiki behauptet etwas anderes und gibt an, dass es sich um einen Kontextstatus handelt.
Rdb
@ndb Nein, ich bin nicht sicher. Ich habe erwartet, dass sie Teil des VAO-Staates sind, und ich habe es nicht überprüft.
HolyBlackCat
4

Es werden nur die Scheitelpunktbindung und die Indexpufferbindung gespeichert

Das sind alle Parameter von glVertexAttribPointerplus dem Puffer, der zum Zeitpunkt des Aufrufs von glVertexAttribPointerVertex_Array_buffer und dem gebundenen Element_Array_buffer an Vertex_Array_buffer gebunden ist.

Uniformen sind Teil des aktuellen Programms.

Alles andere ist globaler Staat.

Im Zweifelsfall können Sie die Statustabellen in der Spezifikation der von Ihnen verwendeten Version überprüfen.

Ratschenfreak
quelle
Danke auch für die Antwort! Das klärt die Dinge für mich auf.
Jelle van Campen
4

Hier ist eine einfache, aber effektive Erklärung: Grundsätzlich hat ein Pufferobjekt Informationen, die als einfache Rohdaten interpretiert werden können, die für sich genommen nichts bedeuten. Es sind also REIN die Daten, die wirklich in irgendeiner Weise betrachtet werden können

i.e float vbo[]={1.0,2.0,34.0...}

Und die Art und Weise, wie OpenGL entwickelt wurde, ist, dass Sie DEFINIEREN müssen, wie die Daten aussehen sollen, die Sie an die verschiedenen Shader übergeben

Sie müssen auch definieren, wie diese Daten gelesen werden, in welchem ​​Format sie vorliegen und was damit zu tun ist und wie sie verwendet werden und wofür all diese Informationen in der VAO gespeichert werden

Sie können beispielsweise Daten deklarieren, die in einem Array wie diesem gespeichert sind float vbo = {11.0,2.0,3.0,4.0}

Was an dieser Stelle als Nächstes erforderlich ist, ist, wie diese Daten von der VBO in der VAO zu interpretieren sind, und was dies bedeutet, ist wie folgt

Der VAO kann so eingestellt werden, dass er 2 Floats pro Vertex liest (was 2 Vektoren mit zwei Dimensionen x, y ergeben würde), oder Sie können den vao anweisen, ihn als 1 Vektor mit 4 Dimensionen zu interpretieren, dh x, y, z, w usw

Aber auch andere Attribute dieser Daten werden im VAO definiert und gespeichert, wie zum Beispiel das Datenformat (obwohl Sie ein Array von float deklariert haben, können Sie den Shader anweisen, es als Ganzzahl einzulesen, wobei das System natürlich die Rohdaten konvertiert der Prozess von float zu integer und hat seine eigenen Regeln, was unter solchen Umständen zu tun ist)

Das VBO ist also im Grunde genommen die Daten, und die VAO speichert, wie diese Daten zu interpretieren sind, da die Shader und der OpenGL-Server sehr neugierig sind und alles wissen müssen, bevor sie entscheiden, wie und was sie wo zu verarbeiten sind um es auszudrücken

Natürlich ist es nicht wirklich neugierig, sondern es scheint am effizientesten zu sein, da es diese Daten auf dem Grafikserver speichern muss, damit es die effizienteste und schnellste Verarbeitung erhält (es sei denn, es entscheidet, dass es dies nicht tun muss, wenn Die Daten dürfen nicht auf diese Weise verarbeitet und für andere Informationen verwendet werden, auf die nicht häufig zugegriffen wird. Daher müssen die Details, was mit den Daten geschehen soll und wie sie verarbeitet werden sollen, in der VAO gespeichert werden Der VAO ist wie ein Header und der VBO ist wie die reinen Rohdaten, die der Header verwendet und definiert (in diesem Fall werden sie an die Shader-Vertex-Attribute übergeben), mit der Ausnahme, dass der VBO nicht darauf beschränkt ist, nur von einem VAO verwendet zu werden kann verwendet und wiederverwendet und an viele VAOs gebunden werden, zum Beispiel:

Sie können ein Pufferobjekt an VAO1 binden und (separat) dasselbe Pufferobjekt an VAO2 binden, wobei jedes Objekt unterschiedlich interpretiert wird, sodass Ihr Shader die Daten verarbeitet, je nachdem, welches VAO das richtige ist Bound würde dieselben Rohdaten unterschiedlich zum Frambuffer verarbeiten (Pixel in Fenster zeichnen), was zu einer unterschiedlichen Anzeige derselben Daten führen würde, die davon abhängt, wie Sie ihre Verwendung in der VAO definiert haben

hopjopper
quelle
Das ist die beste Antwort!
CodingMadeEasy