In meiner Engine erstelle ich mit dem auf der CPU berechneten Perlin-Rauschalgorithmus unendliches Terrain.
Die Erstellung von Terrain sieht folgendermaßen aus:
- Wenn sich die Kamera in der Nähe des entladenen Patches befindet, erstellen Sie ihn
- Berechnen Sie das 513x513-Rauscharray mit vorgegebenen Grenzen
- Berechnen Sie Normalen, Tangenten, Binormale und Indizes
- Übergeben Sie Daten an vbo
Vorteile:
- Muss nur bei Bedarf gerendert werden
- Einfache Kollision
Con
- Slow 64 513x513 Patches werden in 3,1s (ein Thread) erstellt. Für jede Kachel ~ 20 ms Rauschbildung ~ 25 ms Eckpunkte, Normalen, Tangenten, Bitangens, Indizes. Wenn sich die Kamera schnell bewegt, kann der Benutzer das Laden von Kacheln bemerken.
- Speicher verbrauchen ???
Jetzt habe ich mich gefragt, wie ich das beschleunigen kann, indem ich Terrain komplett auf der GPU generiere. Aber es gibt einige Zweifel:
- Wenn Shader jeden Frame ausführen, ist dies nicht eine Verschwendung von Rechenleistung, um Rauschen immer wieder zu berechnen? Dies kann vermieden werden, indem das Ergebnis in die RBGA-Textur geschrieben und später im Vertex-Shader für die Verschiebung verwendet wird, aber die Speichernutzung erhöht wird. Wenn die Erstellung hingegen sehr schnell wäre, sollten nur sichtbare Kacheln im Speicher bleiben. Das Trennen des Puffers führt jedoch zu einer GPU-CPU-Synchronisierung, die die App verlangsamen kann (habe ich recht?)
- Wenn das Gelände nur ein flaches Gitter ist, das durch den Vertex-Shader verschoben wird, muss die gleiche Arbeit an der CPU ausgeführt werden, um die Höhe und Normalen an einem bestimmten Punkt für die Kollision zu berechnen.
- Dies ist nur ein Konzept, aber um alles zu beschleunigen, habe ich darüber nachgedacht, ein Raster auf das Ansichtsfenster zu projizieren, sodass nur eine minimale Anzahl von Scheitelpunkten verwendet wird. Glaubst du, das würde funktionieren?
Meine letzte Frage ist:
Was ist die beste / schnellste / am weitesten verbreitete Technik, um auf der GPU unendliches Terrain zu schaffen?
Antworten:
Nun, wenn ich versuchen würde, die GPU für so etwas zu verwenden, würde ich mich für compute / opencl / cuda entscheiden.
Unabhängig von der Verwendung der GPU oder der CPU (was ich tatsächlich mache) würde ich dies jedoch asynchron tun. Die Entscheidung, dass Sie neues Terrain für den aktuellen Frame benötigen, ist wahrscheinlich zu spät (z. B. 1000 ms / 60 = 16,666 ms). und der gesamte Rahmen will dazu passen).
Beginnen Sie mit dem Generieren (oder Laden aus komprimierten Dateien) von Terrain in einem Worker-Thread und stellen Sie es dem Rest des Spiels und dem Rendern zur Verfügung, sobald dieser Worker fertig ist. Im Allgemeinen ist dies der nächste Frame oder vielleicht der Frame danach Benutzer werden den Unterschied dort nicht wirklich bemerken, aber es macht die Dinge reibungsloser.
quelle