OpenGL-Wie Viele VAOs
Schreibe ich ein OpenGL3+ - Anwendung, und haben eine gewisse Verwirrung über die Verwendung von VAOs. Jetzt habe ich nur einen VAO, ein normierter quad set um den Ursprung. Diese single VAO enthält 3 VBOs; für Positionen, eine für Oberflächen-normalen, und man GL_ELEMENT_ARRAY_BUFFER für die Indizierung (so kann ich laden, nur 4 vertices, anstatt 6).
Habe ich einige helper-Methoden zum zeichnen von Objekten in der Szene, wie drawCube()
welche position nimmt die rotation und Werte und folgt den Verfahren;
- Binden die quad-VAO.
- Pro cube Gesicht:
- Erstellen Sie eine Modell-matrix, repräsentiert dieses Gesicht.
- Laden Sie die Modell-matrix zu den
uniform mat4 model
vertex-shader-variable. - Nennen
glDrawElements()
zu ziehen mit dem quad in die position für das Gesicht.
Ich habe nur die Aufgabe, das hinzufügen von pro-cube-Farben und erkannte, dass ich kann nicht meine Farbe VBO zu den einzelnen VAO, wie es wird sich ändern mit jedem Würfel, und das fühlt sich nicht richtig an.
Ich habe gerade gelesen, die Frage; OpenGL VAO best practices, die mir sagt, dass mein Ansatz falsch ist, und dass ich verwenden soll, mehr VAOs, um die Arbeit sparen, die Einstellung die ganze Szene jedes mal.
Wie viele VAOs sollte verwendet werden? Klar mein Ansatz: 1 ist nicht optimal, sollte es einen VAO für jede statische Oberfläche in der Szene? Was diejenigen, die sich bewegen?
Ich Schreibe, um eine einheitliche variable für jeden vertex, ist das richtig? Ich habe gelesen, dass uniform
shader-Variablen nicht ändern sollte mid-frame, wenn ich in der Lage bin zu schreiben, andere Werte zu meinem uniform
variable, wie Uniformen unterscheiden sich von einfachen in
Variablen im vertex-shader?
- Ein VAO enthält keine VBO. Das ist eine häufige Fehleinschätzung, wie VAOs arbeiten und was Ihre zustandsvektors tatsächlich enthält. Sie können vollständig zu initialisieren einer VAO ohne VBO jemals gebunden. Es wird nicht lassen Sie Sie schieben einen einzelnen Scheitelpunkt entlang der pipeline, aber es ist möglich. That being said, die Terminologie "VBO" ist zweideutig in Ihrem Fall. Normalerweise beziehen Sie sich auf Puffer-Objekt mit Bindung an GL_ARRAY_BUFFER als VBO. Z-buffer-Objekt eine andere Semantik als ein Puffer-Objekt gebunden GL_ELEMENT_ARRAY_BUFFER. Letztere Bindung ist eigentlich VAO Zustand. Jedoch, Sie sind beide einfach nur noch buffer-Objekte.
- "Ich Schreibe, um eine einheitliche variable für jeden vertex, ist das richtig?" Das ist nicht nur falsch, es ist nicht möglich. Entweder du verwechselst deine Bedingungen, oder du tust etwas, was Sie nicht erkennen, Sie tun.
- Ich bin interleaving Aufrufe
glDrawElements
mit anrufen zuglUniformMatrix4
gleichzeitig zu ziehen VAO an verschiedenen Positionen, durch die Aktualisierung der Modell-matrix, erklärt, wieuniform mat4 model
. Ich kann nur annehmen, dass dies so funktioniert, wie meine Würfel erscheinen in den zu erwartenden Positionen und keine andere Verwendung dieser Positionen vorgenommen wird. - danke, ich fühlte, dass die ELEMENT-Puffer war anders, aber wusste nicht, es war falsch, zu beziehen ist als ein VBO. Soll ich mich mit einer VAO für jedes polygon in meiner Welt? Oder man VAO für alle Oberflächen, die die gleiche textur, etc... ich versuche, herauszufinden, was Granularität VAOs sollte verwendet werden.
- Was Nicol Bolas sagt, ist, dass Sie nicht ändern Sie den Wert einer uniform-variable für jeden vertex eingereicht von einem einzigen draw call. Ändern kann man die Uniformen nur zwischen zeichnen Sie Anrufe, aber nie für jeden vertex, es sei denn, Sie ein draw-Aufruf für jedes vertex, das wäre dumm, im Allgemeinen und würde auch nicht für jeden primitiven Typ als PUNKTE.
- Eine uniform ist buchstäblich uniform, Sie es einmal pro Programm, und es wird einheitlich über alle vertex/primitive/fragment einen bestimmten shader-stage-Prozesse.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Absolut nicht. Schalten VAOs ist teuer. Wenn Sie die Zuordnung einer VAO pro Objekt in Ihrer Szene haben, müssen Sie zum schalten der VAO vor dem Rendern dieser Objekte. Skala, die bis zu ein paar hundert oder tausend Objekte, die momentan sichtbar und Sie bekommen nur so viel VAO änderungen. Die Fragen ist, wenn Sie mehrere Objekte, die eine gemeinsame Speicher-layout, d.h. Größen/Typen/Normalisierung/Fortschritte der Elemente sind die gleichen, warum würden Sie wollen, um zu definieren, mehrere VAOs, die allen speichern die gleiche information? Sie Steuern den offset, wo Sie wollen, zu beginnen, ziehen vertex-Attribute direkt mit einem entsprechenden draw-Aufruf.
Für nicht-indizierte geometrie ist dies trivial, da Sie eine erste (oder ein array mit offsets in der multi-draw-Fall) argument, um die gl - [Multi]DrawArrays*() definiert den offset in die entsprechenden ARRAY_BUFFER die Daten zu speichern.
Für indizierte geometrie, und wenn Sie das speichern von Indizes für mehrere Objekte in einem einzigen ELEMENT_ARRAY_BUFFER, die Sie verwenden können, gl[Multi]DrawElementsBaseVertex bieten ein konstanter offset für Indizes oder manuell kompensieren Sie Ihre Indizes, indem Sie eine Konstante offset-vor dem hochladen in das Puffer-Objekt.
Anbieten zu können offsets in einen Puffer zu speichern bedeutet auch, dass Sie mehrere unterschiedliche Objekte in einem einzigen ARRAY_BUFFER und die entsprechenden Indizes in einem einzigen ELEMENT_ARRAY_BUFFER. Jedoch, wie groß die buffer-Objekte sein muss, hängt von Ihrer hardware und Anbieter unterscheiden sich in Ihrer Empfehlungen.
Zunächst, eine Uniform-und shader-Eingabe/Ausgabe-Variablen, die als in/out unterscheiden sich in verschiedenen Instanzen:
Eingabe - /Ausgabe-Variablen definieren eine Schnittstelle zwischen shader-stages, d.h. output-Variablen in einem shader stage werden unterstützt durch eine entsprechende und gleichnamige input-Variablen in der folgenden Etappe. Eine uniform ist in allen Stufen, wenn deklariert mit dem gleichen Namen und ist konstant, bis Sie geändert werden durch die Anwendung.
input-Variablen innerhalb eines vertex-shader sind gefüllt von einem ARRAY_BUFFER. Uniformen innerhalb eines einheitlichen block gesichert werden, eine UNIFORM_BUFFER.
input-Variablen kann auch direkt geschrieben werden mit dem glVertexAttrib* () - Funktionsfamilie. single-Uniform geschrieben werden, mithilfe der glUniform* () - Funktionsfamilie.
die Werte der Uniformen sind Programm Stand. die Werte der input-Variablen nicht.
Den semantischen Unterschied sollte auch klar sein: Uniformen, wie Ihr name andeutet, sind in der Regel konstant zwischen einem Satz von primitiven, in der Erwägung, dass input-Variablen, die in der Regel ändern, die pro vertex oder fragment (durch interpolation).
BEARBEITEN: um Zu klären und zu berücksichtigen Nicol Bolas' Bemerkung: Uniformen kann nicht geändert werden durch die Anwendung für eine Reihe von Eckpunkten vorgelegt, die von einem einzigen draw call, können weder vertex-Attribute durch Aufruf glVertexAttrib*(). Vertex-shader-Eingaben unterstützt durch einen buffer-Objekte ändern, entweder einmal pro vertex oder an einem bestimmten rate von glVertexAttribDivisor.
EDIT2: um Zu klären, wie ein VAO, kann theoretisch Speicherung mehrerer layouts können Sie definieren einfach mehrere arrays mit unterschiedlichen Indizes, aber gleicher Semantik. Zum Beispiel,
und
definieren konnte, zwei arrays mit Indizes 0 und 1, Komponente Größe 3 und 4 und beziehen sich beide auf position Attribute der vertices. Aber je nachdem, was Sie Rendern möchten, können Sie binden eine hypothetische vertex-shader-Eingabe
oder
entweder mit index 0 oder 1 explizit oder glBindAttribLocation() und immer noch die gleichen VAO. AFAIK, die Spezifikation sagt nichts darüber aus, was passiert, wenn ein Attribut aktiviert ist, aber nicht bezogen, die von der aktuellen shader-aber ich vermute, dass die Umsetzung einfach zu ignorieren das Attribut in diesem Fall.
Ob Sie die Quelle der Daten für diese Attribute aus der gleichen oder einer anderen buffer-Objekt ist eine andere Frage, aber natürlich möglich.
Persönlich, ich Neige dazu, verwenden Sie eine VBO und VAO pro layout, d.h. wenn meine Daten aus einer gleichen Anzahl von Attributen mit den gleichen Eigenschaften, ich habe Sie in einer einzigen VBO und eine einzelne VAO.
Allgemein: Sie können Experimentieren mit diesem Zeug viel. Tun Sie es!
in
Variablen durch den AufrufglEnableVertexAttribArray()
gefolgt vonglBindBuffer()
. Sollten diese beiden Aufrufe werden Teil der rendering-Schleife? Austauschen einer anderen 'position' VBO für jede Oberfläche? Jetzt sind Sie Teil von meinem setup.glBindBuffer()
undglVertexAttribPointer()
in der rendering-Zyklus?