Voxelrendering beschleunigen

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Grinch
Beiträge: 25
Registriert: 16.04.2004, 22:42

Voxelrendering beschleunigen

Beitrag von Grinch »

Hallo zusammen,
ich hatte am Wochenende Lust etwas mit Voxeln zu spielen. Das ganze Testprogramm war ziemlich schnell zusammengebaut. Die Welt wird aus einer Heightmap erstellt (256x256). Ich verwende eine Chunkgröße von 32x32x32 Blocks. Für jeden Block wird die Farbe, Position sowie 1 Byte mit aktiv/inaktiv, sowie jeder aktiven Seite des darzustellenden Würfels gespeichert. Die Aktiven Würfel werden im Indexbuffer gespeichert. Texturen habe ich erstmal außen vorgelassen.
Gerendert wird dann als Pointlist im Geometryshader, der alle Blockinformationen bekommt und daraus dann die Würfel abhängig von den sichtbaren Seiten zusammenstellt.
Eigentlich funktioniert das schon ganz gut, aber die Performance stimmt noch nicht. Wenn alle Chunks dargestellt werden bricht die Framerate auf 56-60fps ein. Der Geometryshader scheint nicht der Bottleneck zu sein, da sich die Framerate auch nicht ändert, wenn ich nur 1 Seite der Würfel darstellen lasse.
Zum Vergleich: Die gleiche Map als Heightmap als normale Heightmap per Geometryshader und jeweils 4 Dreiecken pro Heightmap-Punkt rendert meine Grafikkarte auf 300fps. Und Minecraft im Vergleich läuft mit Standardrendering ohne Geometryshader auf konstant 90fps und da wird nicht nur allein gerendert.

Folgende Optimierungen habe ich bereits implementiert:
- Hiddenfaces entfernen für alle komplett umschlossenen Blöcke
- Hiddenfaces entfernt an den Chunkgrenzen, wenn 2 Chunks aneinander stoßen
- Frustumculling für Chunks

Ich hatte noch überlegt, ein Occlusion Culling einzubauen und dafür immer einen inneren Würfel pro Chunk zu berechnen, der immer komplett von den aktiven Chunkblöcken umschlossen ist. Nur ob das soviel bringt weiß ich auch nicht.

Hat jemand noch Ideen oder Quellen, wie man das Rendering beschleunigen kann?
Dateianhänge
voxel2.png
voxel1.png
Benutzeravatar
Artificial Mind
Establishment
Beiträge: 802
Registriert: 17.12.2007, 17:51
Wohnort: Aachen

Re: Voxelrendering beschleunigen

Beitrag von Artificial Mind »

Geometryshader sind ziemlich teuer und du hast ja leider eine relativ hohe max Anzahl von Vertices ( 6 * 4 vertices ), die das ganze teuer macht auch wenn du kaum was rauswirfst.
Ich würde die Boxen schon auf CPU-Seite zusammenbauen bzw. die Geometryshader per Transform Feedback (OpenGL-Begriff) speichern und dann nur noch den fertigen Buffer zeichnen.

Dann kommt es natürlich noch darauf an was du per-pixel tust.
Grinch
Beiträge: 25
Registriert: 16.04.2004, 22:42

Re: Voxelrendering beschleunigen

Beitrag von Grinch »

Danke für den Tipp. Ich habe es so umgebaut, dass ich einmal die sichtbaren Würfelseiten erzeuge und dann nur noch per VertexBuffer ohne Indices rendere. Jetzt habe ich 130fps. Evtl. geht da auch noch mehr.
Allerdings ist die Buffergröße damit auch erheblich gestiegen.
Ich hatte eigentlich gedacht, dass man mit dem Geometryshader einige Probleme effizienter lösen kann und nicht soviel Bufferoverhead erzeugt. Aber so wie es aussieht sind die Einsatzmöglichkeiten für Geometryshader doch eher beschränkt.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Voxelrendering beschleunigen

Beitrag von Krishty »

Ändern sich die Voxel in jedem Frame?

Ich denke, nicht. Aber du berechnest die Würfeloberflächen trotzdem jedes Mal neu. Darum ist es so langsam.

Geometry Shader sind performanter als die entsprechende nicht-Geoshader-Lösung: Nämlich, den Würfel-Vertex-Buffer auf der CPU vorzuberechnen. Und das würdest du auch nicht in jedem Frame tun.

Wie Artificial Mind schon sagte: Berechne die Würfeloberflächen einmal im Geometry Shader und speicher sie danach auf der GPU, um aus diesem Puffer zu zeichnen. Artifial Minds Transform Feedback heißt unter Direct3D, falls du das benutzt, Stream Output.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Artificial Mind
Establishment
Beiträge: 802
Registriert: 17.12.2007, 17:51
Wohnort: Aachen

Re: Voxelrendering beschleunigen

Beitrag von Artificial Mind »

Problem ist jetzt noch, dass du den Post-Transform-Cache nicht nutzt. Ich würde wieder Indices nutzen und entweder zwei Dreiecke (aka 6 indices) oder ein Triangle Fan (4 Indices + 1 Primitive Restart (DX-äquivalent?)) nehmen.
Außerdem kannst du zusammenhängende Würfelflächen zusammenfassen und dort weniger Dreiecke nutzen.

Ich hatte mal nen Blogartikel mit Algorithmen wie man schnell und effizient die Würfelseiten zusammenfasst gefunden, allerdings find ich den auf die schnelle nicht mehr.

EDIT:
http://0fps.wordpress.com/2012/06/30/me ... raft-game/
Grinch
Beiträge: 25
Registriert: 16.04.2004, 22:42

Re: Voxelrendering beschleunigen

Beitrag von Grinch »

Das mit dem Stream-Output hatte ich mir nach dem Hinweis von Artificial Mind schon angeschaut, aber es dann erstmal noch auf der CPU gemacht, weil ich 1. dafür einiges im Programm hätte umbauen müssen und 2. bisher im Netz noch nicht gefunden habe, mit was oder wo ich den Outputbuffer festlegen kann bevor ich DrawAuto aufrufe. Und so wie ich das verstanden habe, muss der Outpubuffer dann immer so groß sein, wie die Menge, die maximal aus dem GS herauskommen kann?! Die Menge dürfte bei mir ja im nie erreicht werden können und wenn ich die Menge vorher berechne, kann ich auch gleich wieder alles auf der CPU machen.
Ich werde als nächstes die Indices nochmal einbauen und schauen, ob dies noch Performance bringt.
Danke für den Artikel: Mit dieser Methode wird die Performance dann wahrscheinlich optimal werden.

Edit: Ok also Streamoutput geht mit SOSetTargets.
Grinch
Beiträge: 25
Registriert: 16.04.2004, 22:42

Re: Voxelrendering beschleunigen

Beitrag von Grinch »

Kurzes Update: Habe jetzt auf indizierte Vertexbuffer umgestellt. Jetzt läuft das Ganze auf 430fps im Releasemode und mit 130fps im Debugmodus. Sollte fürs erste reichen ;-)
Danke für die Hinweise.
Antworten