Ich denke an eine Minecraft-Szene, in der mit Voxel eine Welt von Blöcken gemeint ist, die tatsächlich mit Polygonen gerendert werden:
Wenn Sie einen Geometrie-Shader verwenden, ist es schwierig, genau drei Flächen (oder was auch immer) pro Voxel zu vermeiden.
Wenn Sie viele benachbarte Blöcke haben, die die gleiche Textur haben, können Sie das Kacheln der Texturen verwenden, um in einem VBO-Ansatz viel weniger Dreiecke in Ihrem (entarteten) Streifen zu haben. Ich meine, wenn es eine schöne große, flache 6x6-Fläche mit Grasvoxeln gibt, können Sie die gesamte Oberseite in nur zwei Dreiecken anstatt in 64 zeichnen.
Mit dem GS-Ansatz können Sie die triviale Auslese von Gesichtern, die von benachbarten Voxeln verdeckt werden, nicht durchführen, was auch mit einem VBO-Ansatz sehr einfach ist.
Ich habe den GS-Ansatz nicht ausprobiert, aber ich kann sagen, dass der VBO-Ansatz mit dem Kombinieren von sich wiederholenden benachbarten Kacheln sehr gut funktioniert. Ich fand, dass das Durcheinander mit Elementindizes viel langsamer ist, als nur die Eckpunkte zu wiederholen. Wenn Sie Ihre Welt in schöne kleine Würfel aufteilen, können Sie in der Regel nur ein Byte pro Komponente und Scheitelpunkt verwenden und sogar die Texturinformationen und Normalen (eine Fläche auf einem achsenausgerichteten Würfel hat nur 3 mögliche Normalen) usw. in ein viertes Byte packen 4 Bytes pro Vertex, das ist schön und schnell.
Ich habe für jedes der 6 Gesichter separate VBOs verwendet - es müssen immer nur maximal 3 davon gezeichnet werden. Dies passt gut zu den verschiedenen Texturen, die normalerweise für die oberen Teile von Minecraft-Voxeln verwendet werden. Denn für jeden Satz ist das Normal und So dann einheitlich.
Mit vertikal gekachelten Pixmaps in einem Atlas mit GL_REPEAT
horizontaler Achse und um 90 Grad gedrehten Versionen der Pixmaps im selben Atlas kann ich mit demselben VBO im selben Aufruf massenhaft scheinbar unterschiedliche Blöcke zeichnen. Im 6x6-Grasflächenbeispiel hätte ich das in 12 Dreiecke aufgeteilt, da ich in meinem Atlas nur Wiederholungen in einer Dimension habe.
Ich habe es meistens auf das sehr niedrige Niveau von integrierten Grafikchips und Mobilgeräten gebracht, bei denen GS nur etwas ist, wovon ich träumen kann, wenn ich eines Tages damit spiele.
Was ist mit der dritten Option, bei der instanziierte Arrays verwendet werden? Grundsätzlich zeichnen Sie mit einem einzigen Draw-Aufruf sehr viele Kästchen (bestehend aus einem einfachen 8-Vertex-Würfel), wobei Sie die Positionen (und andere Daten) als instanzspezifische Attribute aus dem Voxeldaten-VBO beziehen (mit
glVertexAttribDivisor
OpenGL, da bin ich mir sicher) DX hat das auch). Dies ist möglicherweise schneller als der Geometrie-Shader-Ansatz, obwohl der Anwendungscode (kein Shader) ziemlich ähnlich sein sollte, da ich mich an Geometrie-Shader erinnere, die den Ruf haben, langsam zu sein, obwohl ich noch keine Erfahrung mit ihnen habe (oder sie instanziiere) auf 2.1 Hardware.Auf jeden Fall sollten entweder Geometrie-Shader oder instanziierte Arrays besser geeignet sein als von der CPU erstellte Voxel-Geometrie, insbesondere wenn sich die Voxel-Daten ändern können. In Verbindung mit Transformations-Feedback (Stream-Ausgabe in DX?) Können Sie möglicherweise eine gute GPU-basierte Culling-Technik einrichten.
quelle
Geometry-Shader-Version klingt für mich viel besser. Sie können nur point vbo und construct box on the fly (Eingabepunkt, Ausgabedreieck-Stream) verwenden. Es ist schnell (noch schneller, wenn Sie die Tessellationseinheit im Shader-Modell 5 (Äq. DX11) verwenden) und reduziert die Bandbreite extrem. Es ist eine schöne und saubere Lösung.
Über GS. Es wird zwischen Vertex-Shader und Pixel-Shader eingefügt und modifiziert den ausgegebenen Vertex-Stream (primitive Streams). Während der Vertex-Shader nur für die Vertices funktioniert, funktioniert der Geometrie-Shader für ganze Primitive. Die Ausgabe dieses Streams geht nur an den Pixel-Shader (und wird davor gerastert :)), und es gibt keine Möglichkeit, ihn zu speichern. (Vielleicht durch ein verrücktes Rendern, um es zu texturieren und dann zu analysieren ... aber keine wirklich einfache Möglichkeit)
Leistungshinweis: Sie sollten in der Lage sein, auf alles im Geometrie-Shader zuzugreifen und den Vertex-Shader zu überspringen (nur Daten zu übergeben). Aber es ist nicht der beste Weg. Besser (schneller) ist es, den Vertex-Shader so gut wie möglich zu transformieren und das Geometrie-Shader-Programm so gering wie möglich zu halten. Haben Sie keine Angst, es für den Zyklus zu verwenden, wenn Sie es benötigen (zum Beispiel zum Erstellen von Boxen). Compiler wird es für Sie ausrollen.
quelle