2009-11-13 12 views
9

Obwohl es scheint, nur sehr wenige aktuelle Referenzen für OpenGL 3.x selbst zu sein, ist die eigentliche Low-Level-Manipulation von OpenGL relativ einfach. Allerdings habe ich ernsthafte Schwierigkeiten, zu versuchen, überhaupt zu konzeptualisieren, wie man VBOs manipulieren würde, um eine dynamische Welt zu schaffen.Wie verwende ich OpenGL 3.x VBOs, um eine dynamische Welt zu rendern?

Offensichtlich sind die unmittelbaren Modusweisen des alten nicht anwendbar, aber von dort wohin gehe ich? Schreibe ich irgendeine Art von Szenenstruktur und wandle diese dann in eine Menge von Vertices um und ströme diese zum VBO, wie würde ich Übersetzungsdaten speichern? Wenn ja, wie würde das Code-weise aussehen?

Grundsätzlich wirklich nicht sicher, wie es weiter geht.

Antwort

9

Wenn Ihre ganze Welt wirklich dynamisch ist, können Sie den GL_STREAM_DRAW_ARB Verwendungs-Flag verwenden und setze die Daten jedes Frames zurück. Mach dir nicht die Mühe, es zu manipulieren, versuche einfach so effizient wie möglich zu streamen.

Ich nehme jedoch an, dass Sie eine Szene haben, die aus mehreren starren Objekten besteht, die sich relativ zueinander bewegen. Verwenden Sie in diesem Fall ein VBO für jedes Objekt und geben Sie das Verwendungskennzeichen GL_STATIC_DRAW_ARB an. Sie können dann die Modelview-Transformation für jede Instanz eines Objekts festlegen und sie mit einem Zeichnungsaufruf pro Instanz rendern.

Eine Faustregel (auf dem PC) ist es, nicht mehr als einen Zeichenaufruf pro MHz Ihrer CPU auszugeben. Dies ist eine grobe Schätzung, aber es gibt etwas Wahres daran. Mach dir keine Sorgen darüber, mehrere unabhängige Objekte in einen einzelnen VBO oder andere Performance-Tricks zu setzen, wenn du unter diesem Limit bleibst.

+1

+1 für die Erkennung Batching als das größte Problem mit Grafik-Codierung in diesen Tagen. 1 Zeichen Anruf pro Mhz scheint optimistisch zu mir nach einigen OpenGL ES iPhone-Codierung - Ich habe festgestellt, ich bin auf 30-40 Chargen beschränkt, um eine anständige Framerate zu erhalten! – tsalter

+0

Ok, ich hätte hinzufügen sollen, dass diese Regel möglicherweise nicht direkt auf Mobilgeräte zutrifft. Ich habe es vor einigen Jahren auf einigen GDC-Folien gesehen und es hat mir auf Windows-PCs gut getan. –

+0

Btw, ich habe die Folien hier gefunden: http://ati.amd.com/developer/gdc/D3DTutorial3_Pipeline_Performance.pdf (hauptsächlich D3D9, OpenGL auf Seite 28) –

5

Die Verwendung von VBOs bedeutet nicht, dass Sie Ihre gesamte Szene mit nur einem einzigen Zeichenaufruf rendern müssen. Sie können weiterhin mehrere Zeichenaufrufe ausführen und auf dem Weg unterschiedliche Transformationsmatrizen einrichten.

Wenn Sie beispielsweise einen Szenengraphen verwenden, kann jedes Modell im Szenengraph einem einzelnen Zeichenaufruf entsprechen. In diesem Fall besteht der einfachste Weg zur Verwendung von VBOs in der Erstellung eines separaten VBO für jedes Modell.

Als Optimierung können Sie möglicherweise mehrere Modelle zu einem einzigen VBO kombinieren und dann Offsets ungleich Null übergeben, wenn Sie Zeichenaufrufe tätigen. Das reißt das richtige Modell aus dem VBO. Es ist auch wünschenswert, mehrere Zeichenaufrufe zu einem einzelnen Zeichenaufruf zu kombinieren, aber das ist nicht möglich, wenn sie unabhängige Transformationen benötigen. (Eigentlich ist es ist möglich, in bestimmten Situationen, wenn Sie instancing oder Vertex-Blending verwenden, aber ich schlage vor, die Grundlagen immer aus dem Weg zuerst.)

9

Kurze Antwort:

Verwenden glMapBufferRange und nur die subrange aktualisieren, die Änderung muss.

Lange Antwort:

Der Trick ist es, die bereits bestehenden Puffer mit glMapBufferRange, kartieren und dann Karte nur den Bereich, den Sie brauchen. Unter diesen Annahmen:

  • Ihre Geometrie verwendet pro-Vertex-Animation
  • Die Vertex-Zählung für die Modelle Morphing ist konstant während der Animation.

Dann können Sie glMapBufferRange verwenden nur die sich ändernden Teile, zu aktualisieren und den Rest der Daten in Ruhe lassen. Volle Uploads mit glBufferData sind langsam wie eine Schildkröte, weil sie den alten Speicher löschen und einen neuen zuweisen. Das ist zusätzlich zum Hochladen der neuen Daten. glMapBufferRange können Sie nur vorhandene Daten lesen/schreiben, keine Zuordnung oder Freigabe.

Wenn Sie jedoch Skeleton-Animationen verwenden, übergeben Sie Vertex-Transformationen als 4x4-Matrizen pro Vertex an den Vertex-Shader und führen Sie die Berechnungen dort durch. Per-Vertex-Daten werden natürlich mit glVertexAttribPointer angegeben.

Denken Sie auch daran, dass Sie Texturdaten im Vertex-Shader lesen können und dass OpenGL 3.1 einige neue Aufrufe von Instanzaufrufen eingeführt hat; glDrawArraysInstanced und glDrawElementsInstanced. Diese Kombination kann für instanzspezifische Suchvorgänge verwendet werden. Das heißt, Sie können Instanzenaufrufe mit derselben Geometriedatenbindung ausführen, aber Positionen oder andere Daten, die Sie als Vertex benötigen, als Texturen oder Textur-Arrays senden. Dies kann Sie davor bewahren, verschiedene Vertex-Array-Datensätze zu mischen und anzupassen.

Stellen Sie sich vor, Sie möchten 100 Instanzen desselben Modells mit unterschiedlichen Positionen oder Farbschemata darstellen. Oder sogar Texturkarten.