Voxel-Displacement-Renderer – Modernisierung der Retro-3D-Ästhetik
(blog.danielschroeder.me)- Daniel Schroeder entwickelt einen Echtzeit-Renderer, der das pixelige Oberflächengefühl von 3D-Spielen der 90er um kleine Voxel-Oberflächendetails erweitert; als Eingabe-Assets dienen vertraute Low-Poly-Dreiecksmeshes und Texturen
- Statt die gesamte Szene in ein Voxelraster zu verwandeln, lässt er nur die Oberflächen über Displacement Maps voxelartig erscheinen und zielt damit auf einen visuellen Stil für statische Umgebungen im Stil von Doom, Quake und Duke Nukem
- Die CPU wandelt Dreiecksmeshes und begrenzte Displacement-Informationen in Geometriedaten für die GPU um und bereitet Texturen vor; das Frame-Rendering übernimmt die GPU weitgehend eigenständig
- Die Demo erreicht auf einer Radeon RX 5700 XT bei 1440p Frame-Zeiten von 4 bis 9 ms; auf dem Steam Deck OLED bei 800p kommt sie auf über 60 FPS und in vielen Abschnitten auf stabile 90 FPS
- Da Umgebungen weiterhin als Dreiecksmeshes behandelt werden können, lassen sich Kollisionen, Character Controller und Pfadfindung mit bestehenden Physikbibliotheken und meshbasierter Verarbeitung lösen; nur einige benötigte Systeme müssen die Voxel-Detailgeometrie berücksichtigen
3D-Ästhetik der 90er mit Voxel-Oberflächen erweitern
- Ziel ist es, die einfache Umgebungsgeometrie und die scharfen Texturgrenzen klassischer 3D-Spiele der 90er beizubehalten und gleichzeitig blockartige 3D-Details auf den Oberflächen hinzuzufügen
- 3D-Spiele der frühen bis mittleren 90er wie Doom, Quake und Duke Nukem hatten großen Einfluss auf Technik und Gameplay; zuletzt werden die damaligen visuellen Beschränkungen selbst als Retro-Reiz wahrgenommen
- Ausgangspunkt ist die Frage: „Was wäre, wenn man Oberflächendetails statt mit Pixeln mit Voxeln erzeugt?“
- Eine Kopfsteinpflasterwand könnte zum Beispiel auch aus der Nähe ihr pixeliges Gefühl behalten und zugleich geometrische Tiefe haben
- Das Ergebnis ist so gestaltet, dass es zwischen dem Erscheinungsbild von 90er-Jahre-Spielen und einer moderneren Darstellung liegt
Einschränkungen üblicher Voxel-Ansätze
- Ein typisches Voxelmesh ist ein dreidimensionales Raster, bei dem jede würfelförmige Zelle angibt, ob sie gefüllt oder leer ist
- Wie in Minecraft können große Voxel texturiert werden
- Es können auch kleine, einfarbige Voxel wie in Teardown verwendet werden
- Um voxelbasierte Umgebungen zu bauen, muss man entweder die gesamte Geometrie in einem gemeinsamen Raster platzieren oder mehrere unabhängige Voxelmeshes im selben Raum anordnen
- Es gibt Werkzeuge zum direkten Erstellen von Voxelgeometrie, doch der Produktionsprozess dauert oft lange und ist häufig auf kleinere Meshes beschränkt
- Man kann Bausteine wie gekachelte Wände oder Böden erstellen und daraus große Strukturen zusammensetzen; das passt gut zu rasterausgerichteten Gebäuden, aber weniger zu freiem Terrain
- Prozedurale Generierung ist nützlich für natürliche Umgebungen und Kombinationen von Bausteinen, bringt aber eigene Schwierigkeiten mit sich und eignet sich nur für bestimmte Arten von Spielen
- Bestehende Dreiecksmeshes lassen sich auch in ein Voxelraster rasterisieren, doch wenn die resultierende Geometrie in einem einzigen Voxelraster liegt, können unerwünschte ästhetische Ergebnisse entstehen
- Achsenausgerichtete Flächen können wie flache Voxelplatten wirken, 45-Grad-Flächen wie Treppen
- Wenn die kanonische Repräsentation der Szene aus Voxeln besteht, muss womöglich nicht nur das Rendering, sondern auch Spiellogik wie Physik, Character Controller und NPC-Pfadfindung auf Voxel-Ebene arbeiten
- Dafür bieten Voxelmeshes wie in Minecraft und Teardown den Vorteil, dass sich Geometrie leicht hinzufügen oder entfernen lässt
Grenzen üblicher Displacement-Verfahren
- Displacement Mapping nutzt zusammen mit einer Textur eine Displacement Map, die für jeden Pixel der Textur definiert, wie weit er auf der Mesh-Oberfläche nach innen oder außen verschoben werden soll
- 3D-Modellierungssoftware kann ein Mesh unterteilen und anschließend die neuen Vertices verschieben, um Displacement zu echter Geometrie zu machen
- Dieser Ansatz wirkt sich auch auf die Silhouette eines Objekts aus
- Die Polygonzahl des resultierenden Meshes steigt stark an
- Eingabemeshes mit harten Kanten oder Ecken müssen für gute Ergebnisse angepasst werden
- In Echtzeitgrafik können Oberflächen-Shading-Effekte wie Parallax Occlusion Mapping den Eindruck feiner Geometrie erzeugen, ohne die tatsächliche Form zu verändern
- Auf großen Böden und Wänden kann das gut aussehen
- An Objektkanten bleibt die Geometrie aber weiterhin flach, wodurch die Illusion bricht
- Shell Mapping ist ein Zwischenansatz, der Displacement auch an der Silhouette eines Objekts sichtbar machen kann, ohne ein hochgradig unterteiltes Mesh zu benötigen
- Bereiche mit hoher Krümmung im Eingabemesh sind schwer zu handhaben
- Auch Eingabemeshes mit harten Kanten oder Ecken lassen sich nicht leicht an diese Technik anpassen
Implementierungsansatz: Voxel und Displacement Mapping kombinieren
- Dieser Renderer erstellt Umgebungen wie in klassischen 3D-Spielen als Low-Poly-Dreiecksmeshes, definiert Oberflächendetails im Voxelmaßstab über Displacement Maps und rendert sie so, als wären sie aus echten Voxeln zusammengesetzt
- Da er auf Umgebungen mit vielen scharfen Kanten, etwa Gebäudeecken, ausgerichtet ist, werden auch in Bereichen voxelartige Ergebnisse benötigt, in denen normales Displacement Mapping Schwierigkeiten hat
- Die aktuelle Implementierung ist ein eigenständiges C++-/Vulkan-Projekt
- Die Infrastruktur erledigt drei Hauptaufgaben
- Sie nimmt Dreiecksmeshes und begrenzte Informationen aus Displacement Maps entgegen und wandelt sie in Geometriedaten um, die die GPU zum Zeichnen des verformten Meshes nutzt
- Dieser Schritt läuft vor dem Frame-Rendering auf der CPU
- In einem veröffentlichten Spiel könnten die Ergebnisse auf die Festplatte gebacken werden
- Die Umwandlung der gesamten Demo-Umgebung im Video dauert auf einem einzelnen Thread 0,5 Sekunden
- Sie verarbeitet Texturen vor und erzeugt Informationen wie Normal Maps, die während des Renderings benötigt werden
- Die Arbeit selbst ist grundlegend, aber langsam, weshalb Baking geeignet ist
- Sie zeichnet die Voxel-Displacement-Geometrie auf der GPU anhand der erzeugten Mesh- und Texturzustände
- Pro Frame ist kaum CPU-Beteiligung nötig
- Sie nimmt Dreiecksmeshes und begrenzte Informationen aus Displacement Maps entgegen und wandelt sie in Geometriedaten um, die die GPU zum Zeichnen des verformten Meshes nutzt
- Die Performance ist bereits praxistauglich
- Auf einer Radeon RX 5700 XT wird die Demo-Sequenz bei 1440p mit Frame-Zeiten von 4 bis 9 ms gerendert
- Das entspricht 250 bis 110 FPS
- Auf dem Steam Deck OLED in nativen 800p bleibt sie über 60 FPS, viele Abschnitte sind auf 90 FPS fixiert
Erstellung der Art-Assets
- Für die Content-Erstellung werden zwei Arten von Assets benötigt: Texturen und Meshes
- Jede Textur wird als Albedo Map und Displacement Map erstellt
- Albedo hilft dabei, den visuellen Stil überzeugend zu machen, wenn sie die begrenzte Palette von Retro-Spielen nachahmt
- Die Displacement Map liefert feine Höhenwerte; der Renderer kann die Intensität über Skalierung anpassen
- Nach der Skalierung gibt die Höheneinheit an, um wie viele Voxel die Oberfläche nach innen oder außen verschoben wird
- Der Renderer verschiebt nur auf die nächste ganzzahlige Voxel-Einheit, nutzt die genauen Höhenwerte aber zur Berechnung der Normal Map
- Auch Merkmale, die niedriger als ein Voxel sind, können die Beleuchtung beeinflussen
- Meshes sind gewöhnliche Low-Poly-Dreiecksmeshes mit Textur-Mapping und Shading-Normalen
- Die Normalen zeigen an, welche Bereiche glatt gekrümmte Oberflächen sind und welche Kanten scharf sind
- Der Renderer führt zusätzliche Schritte aus, um an scharfen Kanten gute Ergebnisse zu erzielen
- Für den visuellen Stil wird versucht, die Voxelgröße beim Texture Mapping konstant zu halten, zwingend erforderlich ist das aber nicht
- Für Mesh-Struktur und Texture Mapping gibt es Einschränkungen
- Einige Einschränkungen lassen sich künftig entfernen
- Manche Einschränkungen sind durch die Funktionsweise des Renderers unvermeidbar
- Da die Assets keine spezielle Voxel-Repräsentation, sondern Dreiecksmeshes sind, können sie mit vielen Werkzeugen erstellt werden
- Die Demo-Umgebung wurde in Blender modelliert
- Das aktuelle Exportformat aus Blender für die Demo sind OBJ-Dateien
Vorteile und Einsatzbereich bei der Spieleentwicklung
- Dieser Ansatz ermöglicht es, Inhalte mit einem vertrauten Workflow zu erstellen, statt mit speziellen Voxel-Editing-Tools
- Gute Texturen zu erstellen kann schwierig sein, doch einmal erstellt lassen sie sich leicht auf vielen Geometrien wiederverwenden
- Ein großer Teil der Geometrie in der Video-Demo nutzt eine einzige Steinblock-Textur in drei Farben
- Da die Umgebung als Dreiecksmesh erstellt wird und die Voxelmerkmale Oberflächendekoration sind, kann man die Umgebung bei Bedarf als Polygongeometrie behandeln
- Die Demo-Anwendung unterstützt Bewegung aus der Ich-Perspektive, Kollisionen, Treppensteigen und Wandkollisionen
- Es wurde keine eigene Physik-Engine und kein eigener Character Controller geschrieben
- Integriert ist das Open-Source-Projekt Jolt Physics
- Als Kollisionsgeometrie wird das ursprüngliche Dreiecksmesh verwendet
- Gegnerbewegung und Pfadfindung lassen sich ebenfalls auf Basis desselben Meshes lösen
- Nur einige Gameplay-Systeme müssen voxelbewusst sein
- In einem First-Person-Shooter könnte man zum Beispiel eine displacement-aware Raycast-Funktion implementieren, damit Kugeln der exakten Form der verschobenen Geometrie folgen
- Viele voxelbasierte Spiele verwenden eigene Engines, weil mehrere Spielsysteme maßgeschneidert werden müssen; bei diesem Ansatz muss der Großteil der Logik außerhalb des Renderings die Details im Voxelmaßstab nicht kennen
- Die Integration dieser Rendering-Technik in bestehende Engines ist der realistischste Weg
Offene Aufgaben und nächste Schritte
- Die aktuelle Implementierung eignet sich gut für die Erstellung von Levelgeometrie, doch Spielumgebungen brauchen auch dynamische Elemente wie kleine Objekte, Dekorationen und Gegner
- Künftig soll ergänzt werden, wie sich kleine oder animierte Objekte in diesen Art Style integrieren lassen
- Die Beleuchtung der Demo sieht bereits gut aus, die aktuelle Implementierung hat jedoch Einschränkungen
- Es wird nur eine kleine Anzahl von Lichtern unterstützt
- Schatten, Ambient Occlusion und fortgeschrittenere Funktionen fehlen
- Der Renderer zielt nicht wie typische Voxelspiele auf sehr dynamische Geometrie, sondern auf die weitgehend statischen Umgebungen, die die meisten Spiele haben
- Je nach Anforderungen einer konkreten Anwendung gibt es verschiedene Möglichkeiten für die Beleuchtungsverarbeitung, einschließlich Baking
- Derzeit gibt es kein Anti-Aliasing, was besonders auf entfernten Bodenflächen auffällt
- Die weiteren Pläne für das Projekt und die Diskussion für Entwickler und Studios werden im zweiten Beitrag fortgesetzt
1 Kommentare
Meinungen auf Hacker News
Vielleicht bin ich alt genug, um mich noch an die Zeit zu erinnern, als man Spiele mit einem 2400-Baud-Modem heruntergeladen hat, aber diese Ästhetik spricht mich wirklich an
Auch das Video war hervorragend und hat für mich persönlich eine starke Atmosphäre heraufbeschworen
In Abschnitten, in denen das Dach sehr niedrig war, spürte ich sogar Klaustrophobie und Beklemmung; die Höhlen mit Fels- und Sandboden sowie die Höhlen mit Felsen waren wirklich wunderschön, sodass ich gern ein Myst- oder LucasArts-artiges Adventure-Spiel sehen würde, das mit diesem Renderer erstellt wurde
Das dürfte gut zu Themen wie Höhlenerkundung oder archäologischen Ausgrabungen passen
Um die Falling-Sand-Engine auf 3D zu erweitern, könnte man wohl auch Ansätze wie glatte Partikel-Fluiddynamik verwenden
In den Bereichen mit niedriger Decke sahen die von der Decke hängenden Blöcke so aus, als würden sie den Gesetzen der Physik trotzen
https://web.archive.org/web/20240524065427/https://blog.dani...
https://www.youtube.com/watch?v=1xFEbXWstCM
Ein anderer Ansatz ist Deep Bump. Es behandelt dasselbe Problem auf völlig andere Weise
Deep Bump ist ein Machine-Learning-Tool, das aus Texturbildern plausible Normal Maps erzeugt
Für die Stein- oder Ziegeltexturen, die dieser Voxel-Displacement-Renderer verwendet, passt es besonders gut; auch bei Stofftexturen erkennt es bis zu einem gewissen Grad Falten, Taschen und Kragen und liefert Normalen, die Tiefe darstellen
Bei Baumrinde ist es ganz okay, bei Pflanzen eher nicht; das liegt vermutlich am Trainingsdatensatz
Wenn man Spiele im Stil von Doom/Wolfenstein modernisieren will, gibt es bereits ein brauchbares Open-Source-Tool
[1] https://github.com/HugoTini/DeepBump
Dieser Beitrag geht eher in die Richtung, Displacement Maps als kleine voxelbasierte Repräsentation zu behandeln; Tools wie Deep Bump könnten hier höchstens unterstützend verwendet werden, um Textur-Assets für das beschriebene System zu erstellen
Da sie nicht die tatsächliche Geometrie verändern, sondern nur die Illusion von Beleuchtung und Räumlichkeit, ist Displacement an Mesh-Kanten weiterhin die höherwertige Option
Allerdings könnte DeepBump vielleicht nützlich sein, um eine eindimensionale Height Map für traditionelles Displacement zu extrahieren, also eine Map, die nur Höhen enthält und kein vollständiges 3D-Vektor-Displacement
Sieht cool aus, aber ich frage mich, wie gut dieser Ansatz zu animierten 3D-Modellen passt
Selbst im besten Fall dürfte es wohl ähnlich aussehen wie der „Voxel Doom“-Mod für Doom
[1] https://media.moddb.com/cache/images/mods/1/55/54112/thumb_6...
[2] https://media.moddb.com/cache/images/mods/1/55/54112/thumb_6...
„Nachdem ich nun all diesen Kontext erklärt habe, möchte ich dem Voxel-Doom-Mod für Classic Doom Anerkennung zollen. Der Modder ersetzte die Monster und andere Sprites des Spiels durch Voxel-Meshes, um Tiefe hinzuzufügen, und das war wirklich beeindruckende Arbeit. Später, Ende 2022, begann er mit Parallax Mapping zu experimentieren, um der Level-Geometrie Voxel-Details hinzuzufügen. Meiner Meinung nach sah dieser Teil nicht besonders gut aus, nicht wegen der Artwork des Erstellers, sondern wegen grundlegender Einschränkungen, die beim Rendering mit Parallax Mapping entstehen. Dieser Mod war keine Inspiration für mein Projekt. Ich war bereits daran am Arbeiten. Aber zu sehen, wie gut der Mod online ankam, gab mir viel Motivation, meine Arbeit fortzusetzen. ↩“
Der Ansatz selbst soll auch Dinge wie animierte Türen unterstützen; mit einer Kombination aus Mesh und Textur-Flipbook ließe er sich daher wohl auch für Monster verwenden, die wie im ursprünglichen Doom aussehen
Allerdings dürften in Bereichen mit starker Krümmung die Artefakte beim Shell Mapping am schlimmsten sein; außerdem werden die Grenzen der Level-Meshifizierung erwähnt, also vielleicht doch nicht
Es sieht dem ziemlich ähnlich, woran Notch arbeitet. Wenn man sich seinen Twitter-Feed ansieht, macht er eine andere Art von Voxel-Rendering
Allerdings nutzt das hier C++/Vulkan und sieht wirklich fantastisch aus
Ich frage mich, wie sich dieser Ansatz mit Unreal Engine 5 Nanite vergleicht. Vielleicht macht Unreal Engine ja etwas Ähnliches
Ich erinnere mich, dass einer der Gründe für den Einsatz von Voxeln in älteren Spielen, etwa Comanche[1], darin lag, dass man damit komplexes Terrain glaubwürdig darstellen konnte, das bei Modellierung mit Dreiecks-Meshes auf ähnlicher Hardware teurer gewesen wäre
Der Autor erwähnt 110 FPS auf einer RX 5700 XT, aber ich bin mir nicht sicher, wie das im Vergleich zu anderen Ansätzen einzuordnen ist
[1] https://en.wikipedia.org/wiki/Comanche_(video_game_series)
Nanite setzt voraus, dass hochpolygonale Objekte erstellt werden, und streamt vereinfachte Chunks, damit die gerenderten Dreiecke nicht kleiner als Pixel werden
Da sich Geometrie auf natürliche Weise sehr fein detaillieren lässt, sind Displacement Maps ein Stück weit redundant, und es gibt keinen zwingenden Grund, das über Texture Maps zu erledigen
Natürlich gibt es bei Terrain Sonderfälle, aber das sind spezielle Fälle
Der Ansatz dieses Artikels scheint darin zu bestehen, aus Displacement und einem Low-Poly-Mesh beim Laden hochpolygonale, aber „voxelisierte“ Geometrie zu erzeugen
Soweit ich mich erinnere, nutzte Comanche einen Raytracing-Ansatz für das Terrain-Rendering[1]
Es waren keine echten Voxel, sondern eine abgetastete 2D-Heightmap
Da es „VoxelSpace“ genannt wurde, ist die Verwechslung verständlich
[1] https://github.com/s-macke/VoxelSpace
Entgegen der verbreiteten Annahme nutzten diese Spiele keine echten 3D-Voxel, sondern zeichneten per Raymarching eine Heightmap, bei der Farb- und Höhenwerte in der Terrain-Textur gespeichert waren
Wenn man im Shader Raymarching in Richtung der Textur macht, lässt sich derselbe Look reproduzieren, und es dürfte den Ergebnissen im Blogbeitrag sehr ähnlich sehen
Nanite dagegen ist eine GPU-getriebene Rendering-Technik, die die Dreiecksdichte an die angestrebte Qualität anpasst
Nanite kann zwar ebenfalls Displacement Maps und Tessellation verwenden, nutzt dafür aber einen separaten Pfad, der nicht zwingend effizienter ist, als hochpolygonale Assets direkt einzubinden und zu rendern
Es ist immer schön, neue Ansätze im Voxel-Bereich zu sehen
Allerdings ist es etwas schade, dass der Artikel Voxel und bestimmte Rendering-Techniken vermischt
Voxel bedeuten einfach die Verwendung eines 3D-Gitters, und im mittleren Teil wirkt es so, als setze der Autor die Nutzung von Voxeln mit würfelförmigem Rendering gleich, also dem, was man oft Minecraft-artiges Bloxel-Rendering nennt
Er sagt auch, man könne Dreiecksgeometrie importieren und direkt in der Engine nutzen, scheint dabei aber zu vergessen, dass Bloxel oder praktisch jeder Rendering-Prozess genau dasselbe tun kann
Genau so erhalten auch gängige Voxel-Rendering-Plugins mit anderen Stilen First-Class-Support in bestehenden Engines
Ich wünschte, das wäre Open Source. Wirklich
Gefällt mir sehr. Erinnert mich an Ultima Underworld
Das sollte die Zukunft der Modernisierung von Retro-3D-Spielen sein. Wirklich schön