Terrain Rendering

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
xq
Establishment
Beiträge: 1581
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Terrain Rendering

Beitrag von xq »

Hey!

Da die Idee im Vorstellungsthread aufkam, dachte ich, ich erstelle mal nen Thread zum Thema Terrain Renderering.
Der Thread soll als Sammel- und Diskussionsthread dienen, in dem man über Terrain Rendering quatschen kann.

Mein aktuelles Projekt ist ein Terrain Renderer, der eine Welt in der Größe 8x8 km rendern soll, aber einen Detailreichtum hin zu geometrischem Gras bieten.
Der Ansatz ist folgender: Ich rendere ein Terrain-Mesh mit der Größe 256², welches via einem Tesselation Shader und einer Bitmap auf 8192² bzw. 16384² erweitert wird, was mir eine effektive Auflösung von 1m / 0,5m pro Quad gibt.
Sofern die GPU des PCs noch mehr Tesselation Power her gibt, wird das Terrain lokal via Displacement Maps der Terraintexturen erweitert.

Soweit der Plan.

Aktuelle Umsetzung: Erstellen des 256² Meshes und der Unterteilung via Tesselation. Nächste Schritte: Terrainheightmap via Textur auslesen, eventuell sogar via texelFetch und korrekten LOD-Levels.


Wie stehts bei euch um Terrains, welche Tricks nutzt ihr für großes Terrain/hohe Weitsicht?

Grüße
Felix
terrainx_4.png
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Benutzeravatar
Top-OR
Establishment
Beiträge: 330
Registriert: 02.03.2011, 16:32
Echter Name: Jens H.
Wohnort: Esslingen/Dessau
Kontaktdaten:

Re: Terrain Rendering

Beitrag von Top-OR »

Moin Master Felix.

Zuerstmal: DasTerrain auf dem Screenshot sieht wie gemalt aus – sowas will ich „spielen“. Schön!

Über Terrain habe ich mir auch den Kopf zerbrochen. Ich glaube, so ein "Brainstorming/Ideenvergleichs"-Thread ist ne gute Idee.
Ich arbeite, wie bereits im anderen Thread angedeutet, in "ähnlicher End-Größendimension". Ich glaube nicht, dass eine "unendlich große Welt" für die meisten Anwendungen/Spiele WIRKLICH nötig ist.

Ich finde die Idee mit der Tessellation interessant und habe auch immer wieder drüber nachgedacht, Tessellation zu benutzen, das Ganze ist aber aufgrund mehrerer Dinge „gescheitert“:

1) "Ich kanns nicht!": Ich habe keine Erfahrung mit Tessellation bzw. wie ich sie in OGL 3.3 benutze (<- wenn das überhaupt geht). Welches Grafikinterface benutzt du? Falls es OGL ist, hast du ein paar nette PRAXISNAHE Papers oder Tutorials, die man sich mal diesbezüglich zu Gemüte führen könnte? Einfach mal ein Polygon zu tessellieren?

2) "Es geht nicht!?": Ich wollte am Anfang der Endwicklung des Terrain-Systems nicht eine so starke Graka (die Tessellation unterstützt) voraussetzen. Soweit ich das aufm Schirm habe, ist das bei OGL erst ab 4.0 drin? Ist das so oder hab ich das falsch im Kopf?

3) "Ich brauche die Geometrie für Queries(auf der CPU)!": Ich bin mir nicht sicher, ob „nur Tessellation“ (und andere GPU-only Effekte) bei Terrain „reicht“, da sie nur den optischen Aspekt einbindet. Ich mache zum Beispiel ständig Geometrische Operationen auf dem Terrain wie Clipping und dergleichen. Wenn die „schöne runde Welt“ nur auf der Graka existiert, müsste ich diese Infos irgendwie selektiv zurücklesen können, um damit auf der CPU was zu machen.
Wie löst du dieses „Physik“-Problem, wenn du eine zu kleine Map (256x256) so stark aufpustest? "Brauche" ich die Geometrie wirklich auf der CPU oder könnte ich auch die Graka performant "fragen"?

Mich nervt, dass mein Terrain so viel CPU und RAM verbläst und jetzt auch nicht unbedingt eine Geschwindigkeitsrakete ist. Vielleicht kann ich mir hier ja nochn paar Denkanstöße sammeln.. ;-)

Beste Grüße,
Jens
--
Verallgemeinerungen sind IMMER falsch.
Benutzeravatar
xq
Establishment
Beiträge: 1581
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Re: Terrain Rendering

Beitrag von xq »

Hey, zu deinen Fragen:

1, 2)
Effiziente Tesselation ist erst mit OpenGL 4.0/DIrectX11 verfügbar, ich nutze in meinem Fall OpenGL. In OpenGL 3.3 kannst du Geometry Shader verwenden, um deine Polygone manuell zu tesselieren, dabei musst du aber bedenken, dass Geometry Shader wesentlich langsamer sind als die Tesselation Unit.

2)
Soweit ich weiß, sind die meisten "neueren" Grafikkarten (also seit Windows 7-Zeiten, vielleicht sogar ein bisschen früher) OpenGL 4.0 fähig. Die OpenGL-Version ist ja meist eher eine Treibergeschichte. Kann mich aber auch gewaltig irren.

3)
Für Queries auf der CPU sollten doch die "rohen" Terraindaten reichen, die ich bei mir in die Textur speichern werde. Damit kannst du ja on-the-fly die passenden Polygone/Quads interpolieren, die man für Queries braucht. Soweit jedenfalls mein Plan. Für eine Physik-Engine bräuchte man wohl mehrere kleinere Terrains, welche dann die hohe Auflösung verwenden und dynamisch hinzu-/weggeschaltet werden, damit die Performance nicht komplett wegdroppt.

Und zum RAM: Bei der Auflösung hat man nun mal nen Berg Daten, im Bestfall bekommt man diesen Berg bei 8192² aber in ca. 128 MB Speicher verpackt. Das sollte sowohl GPU als auch für CPU nicht mehr die starke Last sein.

Grüße
Felix
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Spiele Programmierer
Establishment
Beiträge: 426
Registriert: 23.01.2013, 15:55

Re: Terrain Rendering

Beitrag von Spiele Programmierer »

Also ich habe bei meinen Terrain auch über Tesselation nachgedacht, allerdings mich bewusst dagegen entschieden.
Die Gründe dazu sind sehr vielseitig:
  • Gibt es nicht in OpenGL 3
  • Die Daten müssen in Texturen abgelegt werden und bestimmte Bedingungen erfüllen. Zum Beispiel gibt es ja weitere Parameter wie Wasserstand, Material und so weiter. Diese müssten in unterschiedlichen Texturen abgelegt werden.
  • Ein Vorteil von Tesselation und Texturen, wäre möglicherweise vereinfachtes LOD durch Mip Mapping. Ich möchte aber Festkommawerte für die Höhe zweckes der gleichmäßigen Genauigkeit verweden. Die lassen sich aber nicht mehr schön interpolieren.
  • Es gibt verschiedene Berichte, dass Tesselation vergleichsweise sehr viel Leistung verbraucht.
  • Insgesamt scheint mir die ganze Tesselation ein Trugschluss zu sein. Anstatt im Tesselation Shader zu Unterteilen, ist es sehr einfach Unterteilungen im Vertex Shader zu erzeugen.
Konkret mache ich das so: (Teilweise aus anderem Thread)
Ich habe mein Terrain in 256² Blöcken organisiert. Ich speichere nur die Höhe und nicht die X, Z Koordinate eines Punktes um Speicherplatz/Bandbreite zu sparen, die X, Z Koordinaten berechne ich dynamisch aus der Position des Blocks und der VertexID. Geometry Shader verwende ich für die normale Oberfläche keinen, stattdessen setze ich einen Index Buffer ein, der ein Triangle Strip über alle Vertices beschreibt. Ich verwende dabei aber die selben Index Buffer für alle Blöcke des Terrains, denn die Reihenfolge der Vertices ist in den Blöcken überall gleich. LOD realisiere ich einfach, in dem ich den Index Buffer austausche, der weniger Vertices auf dem Terrein umfasst. Interpolation gibt es keine, aber das ist nicht so schlimm. Es ist wahrscheinlich auch nicht optimal für den Cache. Vielleicht ändere ich das irgendwann noch so, dass ich doch unterschiedliche Daten für die verschiedenen LOD Stufen habe.
Das Triangle Strip im Index Buffer habe ich Schlangenartig ausgelegt, um den Post Transform Cache wirken zu lassen. Die Normalen liegen in einer Texturen und ich berechne sie im Voraus, aber auf der GPU. Dafür nehme ich ein FBO und rendere ich die Höhendaten mittels Texture Buffer dorthin. Ein Compute Shader wäre wahrscheinlich effizienter, leider habe ich mir zum Ziel gesetzt zu OpenGL 3.3 kompatibel zu sein. Also wenn dann könnte ich den Compute Shader zusätzlich zum FBO Ansatz einbauen. Der Vorteil davon, die Normalen Die kann ich dann auch bei allen anderer LOD-Stufe exakte Normalen und Beleuchtung genießen kann. Damit die Normalen berechnet werden können überschneiden sich die Blöcke übrigens leicht und 2 Höhenpunkte am Rand sind immer in zwei Blöcken.
An den Rändern der Blöcke mache ich zusätzliche DrawCalls für Wasser und das Gelände um es nach unten zu extrudieren. Ein offenes Gelände hat mich irgendwie immer gestört. Unendlich wird es später in der Praxis nämlich wahrscheinlich nicht, auch wenn es in der Theorie durchaus möglich wäre.
Für das Wasser verwende ich ein 2 Pass verfahren. Erst rendere ich alle anderen Dinge und lege schließlich das Wasser darauf. Ich vergleiche dann die Z Tiefe im Fragment Shader und bestimme so die Dichte des Wassers. Spiegelungen habe ich nie realisiert, weil ich an der Umsetzbarkeit zweifle, wenn das Wasser nicht unbedingt komplett eben ist wie bei mir. Höchstens Screen Space Reflections könnten möglich sein, allerdings führt das vermutlich zu vielen Darstellungsfehlern und ist auch nicht einfach umzusetzen.
Den Himmel berechne ich im Moment vollkommen prozedural. Allerdings ist das ziemlich rechenintensiv und normalerweise ist er auch ziemlich gleichmäßig. Den könnte man in geringerer Auflösung berechnen und seltener updaten.
Benutzeravatar
Artificial Mind
Establishment
Beiträge: 802
Registriert: 17.12.2007, 17:51
Wohnort: Aachen

Re: Terrain Rendering

Beitrag von Artificial Mind »

MasterQ32 hat geschrieben:Die OpenGL-Version ist ja meist eher eine Treibergeschichte. Kann mich aber auch gewaltig irren.
Grobe Richtlinie für die OpenGL Version ist:
Major Versions (1.X, 2.X, 3.X, 4.X) benötigen neue Hardware.
Minor Versions (z. B. 4.3 -> 4.5) können per Treiber nachgeliefert werden.

Einige Hersteller sind mit Treibern etwas langsamer, so hat meistens Apple häufig nicht die neusten Versionen und die Intel HD 3000 z. B. steckt glaube ich noch bei 3.1.
Antworten