„Letzte Worte“ – VR-Experience im Making-of

Die VR-Experience „Letzte Worte“ entführt den Spieler auf eine anspruchsvolle, emotionale Reise. Als Lisa sieht man sich früh mit dem Tod des eigenen Bruders Leo konfrontiert. Die lebendigen und detaillierten Orte eröffnen dem Spieler einen Einblick in die Charaktere, deren Beziehungen und die näheren Umstände hinter Leos Tod. Neben Lisas Wohnung können auch Umgebungen aus der gemeinsamen Vergangenheit erkundet werden, darunter das Elternhaus und Baumhaus. Uns ist wichtig, dass der Spieler die Gefühle der Machtlosigkeit, die Lisa quälen, hautnah erfährt.

Letzte Worte wurde im Zuge des Masterstudiums Digital Arts in Hagenberg entwickelt – von Matthias Patscheider, Samantha Povolny und Bianca Zankl. Bianca kümmert sich vorwiegend um Programmierung und Game Design, Samantha ist sowohl für Audio als auch Grafikdesign verantwortlich. Mein Zuständigkeitsbereich umfasst den gesamten 3D-Bereich. Das Spiel basiert auf der Unreal Engine 4.19. Es kann kostenlos von Steam heruntergeladen werden. Um es spielen zu können, benötigt man die HTC Vive oder Oculus Rift mit einem raumfüllenden Spielbereich, 360-Grad-Ortung und Bewegungscontrollern.

Abb. 1: Beschreibung und Refe­renzen zu Lisas Zimmer
Abb. 1: Beschreibung und Refe­renzen zu Lisas Zimmer

Vorbereitung

Die visuelle Ausarbeitung beginnt mit dem Sammeln passender Referenzen, dem Erstellen von Moodboards und Konzeptzeichnungen (siehe Abbildung 1). PureRef ist ein geniales Tool, um Referenzen immer im Blick zu behalten. Parallel startet die Planung des Level Designs mit sehr groben und einfachen 2D-Layouts. Abbildung 2 zeigt ein solches Layout für Lisas Zimmer.

Abb. 2: Frühes 2D-Layout für Lisas Zimmer
Abb. 2: Frühes 2D-Layout für Lisas Zimmer

Darauf basierend entstehen früh die ersten 3D-Prototypen in der Unreal Engine. Um diese zu erstellen, bietet Unreal sogenannte Geometry Brushes. Diese ermöglichen das schnelle Formen der Level-Layouts mit Grundformen, die ähnlich zu Booleschen Operationen sowohl additiv als auch subtraktiv verwendet werden können (Abbildung 3). Währenddessen werden bereits die ersten Grundmechaniken implementiert. Die Logik für unseren VR-Controller basiert dabei auf dem Proteus VR Template. Der frühe Prototyp vermittelt ein Gefühl für den Raum, die Komposition, und die Navigation im Level. Er ermöglicht eine erste Einschätzung des Projektumfangs sowie der benötigten Assets. Die daraus gefertigte Asset-Liste dient als Richtwert für Umfang und Fortschritt während des gesamten Projekts.

Abb. 3: 3D-Prototyp mit Ausnahme des Baums ausschließlich bestehend aus Unreals Geometry Brushes
Abb. 3: 3D-Prototyp mit Ausnahme des Baums ausschließlich bestehend aus Unreals Geometry Brushes

Um Assets umgehend in der Game Engine testen zu können, werden die einfachen Blöcke durch grobe, nicht optimierte Meshes mit automatisch generierten UV-Maps ersetzt. Diese verwenden einfachste Shader und sich wiederholende, nahtlose Texturen meist aus Bibliotheken.

Abb. 4: Gegenüberstellung des frühen 3D-Prototyps zum finalen Produkt (siehe Aufmacherbild)
Abb. 4: Gegenüberstellung des frühen 3D-Prototyps zum finalen Produkt (siehe Aufmacherbild)

Die Abbildung 4 zeigt eine Gegenüberstellung dieses frühen Stadiums mit dem finalen Produkt. Änderungen sind noch immer ohne großen Zeitaufwand möglich. Das ermöglicht das Experimentieren und Iterieren mit diversen Formen und Variationen in der Engine.

Das Erstellen von Props

Da Objektoberflä­chen in VR aus beliebiger Nähe betrachtet werden können, haben wir uns das Ziel gesetzt, eine hohe Texel Density von 1.024 x 1.024 Pixel pro Quadratmeter für Umgebungen und Assets bzw. 2.048 x 2.048 für Grafiken und Schriften zu erreichen. Texel Density beschreibt das Verhältnis von Texturauflösung zur Oberfläche eines Objekts. Um das zu erreichen, kombinieren wir verschiedene Shading-Ansätze für verschiedene Asset-Typen.

Abb. 5: Auf einem Texturatlas zusammengefasste Assets und deren Texturen (Base Color, Normal und Roughness Metalness Ambient Occlusion)
Abb. 5: Auf einem Texturatlas zusammengefasste Assets und deren Texturen (Base Color, Normal und Roughness Metalness Ambient Occlusion)

Für kleinere Gegenstände erstellen wir High- und Low-Poly-Meshes und projizieren die Details anschließend. Die Objekttexturen werden mit konsistenter Texel Density auf Texturatlanten zusammengefasst, um die Anzahl an Texturen pro Level zu reduzieren. Abbildung 5 zeigt verschiedene Gegenstände mit dazugehörigem Texturatlas. Zum Sicherstellen einer konsistenten Texel Density greifen wir auf das Add-on Texel Density Checker für Blender zurück. Dieses skaliert die UV-Koordinaten entsprechend der gewünschten Werte. Mit Multi Object Editing in Blender 2.80 wird das Erstellen der Atlanten erheblich vereinfacht gegenüber früheren Workarounds. Das Anordnen der UV-Inseln kann durch das Add-on Shotpacker für Blender weitgehend automatisiert werden. Dabei kann über verschiedene Settings die Anordnung (u.a. Rotation und Skalierung) der UV-Inseln beeinflusst werden.
Das Baken der diversen Maps (u.a. Normal, ID, AO) erfolgt in Marmoset Toolbag. Dies sticht durch den intuitiven Workflow hervor. Die Baking Cages werden visuell dargestellt – bei diesen handelt es sich um Hüllen, von denen aus die Strahlen beim Baking-Prozess ausgesandt werden. Des Weiteren können die Entfernungen der Cages objektspezifisch angepasst werden und an Problemzonen (z.B. Stofffalten) spezifisch manipuliert werden. Fehler im Baking können so schnell behoben werden, ohne große Änderungen an den Meshes vorzunehmen. Ähnlich wie bei Substance Painter liefert Marmoset die Möglichkeit, genauer zu definieren, welches High-Poly-Objekt auf welche Low-Poly gebacken wird.
Die generierten Maps dienen anschließend als Grundlage beim Texturieren in Substance Painter. Mithilfe der ID-Maps, Smart Materials und der prozeduralen Masken kann schnell ein gutes Ergebnis erzielt werden. Substance Painter verfügt über ein optimiertes Export Preset, Unreal Engine 4 (Packed), das für unsere Zwecke erweitert wurde. Neben Base Color, Occlusion Rough­ness Metalic, Normal und Emissive werden zusätzliche, optionale Masken zum Steuern von diversen Shader-Effekten exportiert, z.B. für den Glow interaktiver Objekte oder Bereiche mit zufälligen Farben. Beide Effekte finden bei den Farbdosen in einem frühen Level Einsatz, siehe Abbildung 6.

Abb. 6: Zusätzliche Masken zum Steuern, Shading-Effekte wie Farbspritzer, Bereiche mit zufälliger Einfärbung und leuchtende Outlines
Abb. 6: Zusätzliche Masken zum Steuern, Shading-Effekte wie Farbspritzer, Bereiche mit zufälliger Einfärbung und leuchtende Outlines

Mastermaterial

Fast alle Materialien der einzelnen Props lassen sich von wenigen gemeinsamen Master Materials ableiten. Änderungen werden automatisch auf alle Materialinstanzen weitergegeben. Das jeweilige Master Material definiert die verfügbaren Parameter. Im Material Editor ist es sehr einfach, ein solches Master Material zu erstellen. Online finden sich unzählige Beispiele und Tutorials. Das Master Material ist so strukturiert, dass sich die Parameter zum Aktivieren und Deaktivieren von Shading Features am Anfang befinden. Im Material Editor werden diese über Static Switches implementiert. Nicht aktive Features werden nicht kompiliert, benötigen somit keine Ressourcen, können aber nicht zur Laufzeit geändert werden.

Abb. 7: Eine Material-Instanz, die vom Master Material ableitet
Abb. 7: Eine Material-Instanz, die vom Master Material ableitet

Anschließend folgen die dynamischen Parameter. Diese definieren die Materialtexturen, Farbüberlagerungen sowie die Manipulation der UV-Koordinaten (u.a. Tiling und Offset der Texturen), Roughness, Ambient-Occlussion-Werte, siehe Abbildung 7.

Layered Materials

Viele der größeren Assets wie Möbel und Wände werden mittels Material Layering geshadet. Dabei definieren Masken den Wirkungsbereich der einzelnen Basismaterialien. Für diese Assets werden keine High-Poly-Meshes erstellt. Die Objekttexturen werden im Substance Painter direkt vom Low-Poly-Mesh generiert und mit Ausnahme der Ambient Occlusion Map nur zum Erstellen der Masken verwendet. Beim Export werden die Masken in den RGB-Kanälen und die Ambient Occlusion Map im Alpha-Kanal gespeichert (Abbildung 8).

Abb. 8: Komponenten des Material Layerings: links die Basismaterialien, rechts die Blendingmasken und Ambient Occlusion Map sowie das Resultat in der Mitte
Abb. 8: Komponenten des Material Layerings: links die Basismaterialien, rechts die Blendingmasken und Ambient Occlusion Map sowie das Resultat in der Mitte

Anstelle der generierten Normal Maps erhalten die Kanten einen einfachen Bevel. Dieser sorgt in Kombination mit Face-Weighted Normals für das richtige Shading, auch ohne zusätzliche Support Loops. In Blender 2.80 kann das einfach mittels des Weighted Normal Modifiers erreicht werden (Abbildung 9 und 10).
Für die nötigen Oberflächendetails sorgen abschließend die Basismaterialien des Layered Materials. Scharniere und Türgriffe nutzen kein Material Layering, sondern denselben Shading-Ansatz wie Props.

Abb. 9: Vergleich aus Smooth Shading, Bevel mit Smooth Shading und Bevel mit Face-Weighted Normals
Abb. 9: Vergleich aus Smooth Shading, Bevel mit Smooth Shading und Bevel mit Face-Weighted Normals
Abb. 10: Blenders Modifier Panel mit dem Weighted Normal Modifier
Abb. 10: Blenders Modifier Panel mit dem Weighted Normal Modifier

Der große Vorteil ist, dass beliebig viele Objekte mithilfe derselben Basismaterialien geshadet werden können (Abbildung 11). All diese Objekte nutzen dieselben nahtlosen Texturen und benötigen keine einzigartigen 4K-Texturen. Die Basismaterialien können einfach iteriert und ausgetauscht werden. Die Auflösung der Masken ist in diesem Fall lediglich 512 x 512 Pixel für alle diese Objekte gemeinsam. Die Auflösung der nahtlosen Basismaterialien beträgt zwischen 256 und 1.024 Pixel.

Abb. 11: Assets mit Layered Materials und denselben Basismaterialien
Abb. 11: Assets mit Layered Materials und denselben Basismaterialien

Für Türen, Fenster und Möbel wird das Layered Material um die Möglichkeit erweitert, ein Trim Sheet mittels zusätzlichem UV-Set zu verwenden. Das Trim Sheet beinhaltet wiederverwendbare Texturbereiche, die mittels UV-Koordinaten an beliebige Stellen des Meshes projiziert werden können. Mit diesen Trim Sheets ist es möglich, bestimmte Normal-Map-Details auf unterschiedliche Objekte zu projizieren, so etwa die Kacheln und Leistendetails auf den Kachelofen in Abbildung 12.

Abb. 12: Wiederverwendbare Trim Sheets auf einem eigenen UV-Set ersetzen objektspezifische Normal Maps.
Abb. 12: Wiederverwendbare Trim Sheets auf einem eigenen UV-Set ersetzen objektspezifische Normal Maps.

In den Außenbereichen wird neben Texturen auch Vertex Painting zur Maskierung der Basismaterialien verwendet. Die gesamte Außenszene setzt sich vorwiegend aus fünf Basismaterialien zusammen.
Durch den Einsatz von Vertex Painting können so beispielsweise Pfade direkt in der Engine gezeichnet und angepasst werden. In Kombination mit dem Material Node Height Lerp können so komplexe und detaillierte Übergänge zwischen den Basismaterialien geschaffen werden, selbst bei geringer Polygonzahl (Abbildung 13).

Abb. 13: Das Shading der Außenszenen basiert auf fünf Basismaterialien.
Abb. 13: Das Shading der Außenszenen basiert auf fünf Basismaterialien.

Das Thema wird in der Masterarbeit „Defining Design Patterns for Pattern Based Material Layering in Real-Time Engines“ weiter ausgeführt. Diese ist auf meinem Github-Kanal zu finden.

Spezialmaterialien

Bei spezifischen Anforderungen an das Shading wird ein neues Material erstellt, das sich nicht vom Master Material ableitet, um dessen Übersichtlichkeit beizubehalten. In einer späteren Szene breitet sich überraschend eine schwarze, klebrige Substanz über die zerrissenen Elemente einer Kinderzeichnung aus. Dadurch leuchten zuvor unsichtbare Kritzeleien auf (Abbildung 14).

Abb. 14: Der Wirkungsbereich der Basismaterialien wird hier über Vertex Painting gesteuert.
Abb. 14: Der Wirkungsbereich der Basismaterialien wird hier über Vertex Painting gesteuert.

Die Ausbreitung wird über ein Material-Parameter im Blueprint gesteuert. Blueprints sind die visuelle Scripting-Umgebung in UE4. Abbildung 15 zeigt den Einfluss dieses Parameters. Die Animation wird über verschiedene, sich bewegende Noises und die Manipulation von UV-Koordinaten generiert. Der Effekt ist performant und von den zugrunde liegenden Prinzipien einfach, der visuelle Eindruck jedoch groß.

Abb. 15: Darkness Expansion – Neben Objekt-Materialien kann der Material Editor auch dazu verwendet werden, Lichtfunktionen, Post-Processing-Effekte und Decals zu erstellen. All diese Materialtypen nutzen denselben Editor und identische Nodes.
Abb. 15: Darkness Expansion – Neben Objekt-Materialien kann der Material Editor auch dazu verwendet werden, Lichtfunktionen, Post-Processing-Effekte und Decals zu erstellen. All diese Materialtypen nutzen denselben Editor und identische Nodes.

Stoff und Vegetation

Vegetation und Stoffe geben der Szene das gewisse Etwas. Mit dem Marvelous Designer können auf einfachste Art und Weise Polster, Decken und Ähnliches erstellt werden. In Kombination mit Unreals Cloth Shader tragen sie sehr zur Qualität einer Umgebung bei (Abbildung 16).

Anspruchsvoll wird das Erstellen bei komplexen Schnitten. Es ist wichtig zu verstehen, wie ein reales Schnittmuster aussehen müsste, um dies im Marvelous Designer nachbilden zu können. Für dieses Projekt kam erstmals Speedtree zum Einsatz. Das auf Nodes basierende Erstellen von Vegetation ist benutzerfreundlich, die Assets sind optimiert für die Game Engine und Wind-Animationen können als Bestandteil des Shaders importiert werden. Die Herausforderung in „Letzte Worte“ bestand darin, einen Baum durch ein bestehendes Baumhaus-Mesh wachsen zu lassen (Abbildung 18). Das konnte dank der Möglichkeit, Meshes zu importieren und als Kräfte zu verwenden, Splines für Äste händisch zu zeichnen und bereits generierte Bereiche nachträglich zu manipulieren, erreicht werden.

Abb. 18: Das Generieren eines Baumes, angepasst an ein bereits existierendes Baumhaus, mit Speedtree
Abb. 18: Das Generieren eines Baumes, angepasst an ein bereits existierendes Baumhaus, mit Speedtree

Organisation

Das Behalten des Überblicks stellt für mich eine Riesen-Herausforderung dar. Das Projekt umfasst mehrere Hundert Assets, diese verwenden verschiedene Shading-Typen und Materialien, sind auf Texturatlanten zusammengefasst und verwenden zusätzliche UV-Sets für Grafiken, Schriften und Trim Sheets.

Abb. 18: Das Generieren eines Baumes, angepasst an ein bereits existierendes Baumhaus, mit Speedtree
Abb. 18: Das Generieren eines Baumes, angepasst an ein bereits existierendes Baumhaus, mit Speedtree

In der Unreal Engine sammeln wir die Assets in sogenannten Masterlevels (Abbildung 19). Zusammen mit der Assetliste erleichtert es diese Aufstellung, den Überblick zu behalten. Es ist schnell ersichtlich, wie weit der Fortschritt der Assets eines Levels ist. Dieses neutrale Setup erleichtert das Evaluieren von Objekten, Materialien, Texturen sowie technische Aspekte wie Collider, LODs und Light Maps. Wir nutzen ausschließlich Unreals internes LOD-System. Des Weiteren können Anpassungen an den Assets vollzogen werden, ohne etwaige Konflikte in den Spiellevels zu provozieren.

Abb. 19: Alle Assets eines Levels gesammelt in einer Masterszene
Abb. 19: Alle Assets eines Levels gesammelt in einer Masterszene

Beleuchtung

Als Grundlage für das Licht-Setup dienen die Hauptlichtquelle (meist Directional Light) und das Sky Light. Durch das Setzen weiterer Punkt- und Spot-Lichter wird die Beleuchtung weiter ausgearbeitet. Während des Einrichtens der Beleuchtung sollten im Post Processing Volume folgende Werte deaktiviert werden: Auto Exposure, SSAO, SSR, Vignette und Bloom. Besonders Auto Exposure erschwert das Beleuchten durch das dynamische Anpassen der Helligkeit ungemein. Die begehbaren Bereiche werden mit einem Light Mass Importance Volume umschlossen. In dessen Volumen wird das Licht mit einer höheren Qualität berechnet. Die Lichter sollten nach Möglichkeit auf statisch gesetzt werden. Befinden sich beispielsweise mehrere Spot-Lichter an der Decke eines Raumes, können diese auf statisch gesetzt und um ein stationäres Licht erweitert werden. Während die statischen Lichter für hochqualitative und globale Beleuchtung sorgen, ist Letzteres für die Beleuchtung und Schatten der dynamischen Objekte zuständig. Diese einfachen Tricks erwecken den Eindruck einer realistischen Beleuchtung, bei verbesserter Performance.
Statische Lichter müssen zunächst berechnet werden. Dieser Vorgang nimmt im Preview-Modus nur wenig Zeit in Anspruch und vermittelt bereits einen ersten Eindruck für das finale Resultat. Davon ausgehend können weitere Anpassungen vorgenommen werden. Ist das Zwischenergebnis zufriedenstellend, kann die Szene in einer höheren Qualitätsstufe berechnet werden. Nun kann man auch die Auswirkungen der globalen Beleuchtung und Details besser sehen. Neben diesen Qualitätsstufen befinden sich in den World Settings weitere Qualitätseinstellungen wie Qualität und Anzahl der indirekten Bounces sowie die Auflösung der volumetrischen Light Map (Abbildung 20).

Abb. 20: Light-Mass-Einstellungen für Lisas Zimmer (UE4 4.19)
Abb. 20: Light-Mass-Einstellungen für Lisas Zimmer (UE4 4.19)

Eine Herausforderung ist das Anpassen von statischer und dynamischer Beleuchtung. Interaktive Objekte stechen hell auch in dunklen Ecken hervor, während andere zu dunkel erscheinen. Um das Light Bleeding durch Wände zu minimieren, können zusätzliche dicke Boxen zur Abschirmung der Außenbeleuchtung hinzugefügt werden. Die Verwendung eines raumfüllenden, stationären Punktlichtes in Kombination mit einer deutlich erhöhten Auflösung der volumetrischen Light Map kann dieses Problem weiter vermindern. Auch das Experimentieren mit Radien und Intensität der diversen stationären Lichter kann die Qualität der dynamischen Beleuchtung erheblich verbessern.

Effekte

Nach dem Ausleuchten können die zuvor deaktivierten Post-Processing-Effekte wieder aktiviert und die Werte darin anpasst werden. In VR müssen die Effekte für beide Augen berechnet werden und nehmen so mehr Rechenleistung in Anspruch als bei
Desktopanwendungen. Der bedachte Einsatz von Color Grading und Post-Effekten wertet das Endergebnis nochmals auf (Abbildung 22).

Abschließend kann die Szene durch den Einsatz diverser Effekte verfeinert werden. In VR sind die Effekte wie Light Shafts, Atmospheric Fog und Volumetric Fog nach eigener Erfahrung nicht empfehlenswert, da die Auswirkungen auf die Performance gravierend sind. Ähnliche Effekte können auch über andere Tricks erreicht werden, so z.B. über Partikelsysteme, spezielle Materialien und Light Functions. Epic hat einige Beispielprojekte zur Verfügung gestellt. Dort finden sich eine Vielzahl an Beispielen, u.a. Staub, Partikelsysteme, Dampf, Fake Lens Flares und Godrays. Diese Effekte können für die eigenen Projekte verwendet und angepasst werden.

Fazit

Nach dem Release im Februar haben wir ein Update mit verbesserter Performance und Grafik veröffentlicht. Damit ist das Projekt für uns weitgehend abgeschlossen und wir widmen uns neuen Herausforderungen.
Vor diesem Projekt hat niemand aus unserem Team mit der Unreal Engine oder Virtual Reality gearbeitet. Dieses Wissen mussten wir uns erst im Laufe des Projekts aneignen. In vielen Bereichen haben wir das Projekt als Möglichkeit verstanden, neue Wege zu gehen.
Die anfänglich erdachten Shader und Workflows stellten sich als deutlich komplexer heraus als zunächst geplant. Diese Komplexität blockierte teilweise den kreativen Prozess und die Fähigkeit, schnell zu iterieren. Im Laufe des Projekts konnten wir das verbessern und identische Resultate einfacher erreichen. Ein gutes Beispiel ist die bereits erwähnte Organisation von Assets, wo ein komplexes Asset-System größtenteils durch gut strukturierte 3D-Files, Naming Conventions und ein paar Usability Scripts ersetzt wurde.
Ähnliche Erfahrungen haben wir bei der Performance machen müssen. Zu Beginn haben wir uns in Kleinigkeiten verstrickt und Aspekte optimiert, die nicht das eigentliche Problem darstellten. Mehrmals stellte sich ein unbedacht gesetztes Asset als Ursprung der Performance-Einbußen heraus. Die zuvor getätigten Optimierungen fielen nach Beseitigen des eigentlichen Problems kaum bis nicht ins Gewicht.
Die vermutlich größte Herausforderung jedoch war, die von uns erdachte Geschichte allein durch Umgebungen und Lisas Stimme dem Spieler verständlich zu vermitteln. Die Playtests haben uns hier sehr geholfen, da wir durch die Befragung der Testpersonen Hinweise hinzugefügt oder auch entfernt
haben.

Kommentar schreiben

Please enter your comment!
Please enter your name here

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.