Vertex Color Baked Lighting mit Wonderland Engine

Für ihr Mini-Golf-Spiel “Above Paradowski” nutzten Colin Freeman, Ayushman Johri und James Kane eine großartige Technik, um das Licht in ihrer Szene zu backen. Sie sparten sich Lightmap-Textur-Lookups im Fragmentshader und erzielten dennoch einen sehr polierten Look für ihr Erlebnis.

In diesem Artikel werden wir erklären, warum diese Technik clever ist und wie Du sie verwenden kannst in der Wonderland Engine.

Vertex Color Baked Lighting mit Wonderland Engine
Vertex Color Baked Lighting mit Wonderland Engine

Screenshot einer schwebenden Insel in Blender: flache Beleuchtung (links), gebackene Vertexfarben (rechts).

Motivation 

Die Berechnung von Licht dauert lange. Für ein realistisches Ergebnis musst Du Lichtwege und -reflexionen nachverfolgen, wobei jeder Reflexion weitere Lichtwege und -reflexionen zu berechnen sind. Die Arbeitsmenge explodiert!

So werden animierte Filme gerendert, aber in Echtzeit-VR haben wir statt Minuten pro Frame nur etwa 11 Millisekunden für zwei Frames (linkes und rechtes Auge) bei 90 Hz für Standalone-VR-Geräte. Statt GPU-Renderfarmen haben wir eine mobile GPU.

Da das Halten von 60-90 Hz wichtig für Komfort und Immersion in VR ist, müssen wir das Problem anders angehen. Die Wonderland Engine implementiert bereits viele großartige Methoden und Optimierungen, um schnell zu rendern, sogar mit Echtzeit-Schatten, aber für extrem große Szenen brauchen wir jede Performance, die wir bekommen können.

Licht-Backen 

Statt die Beleuchtung zur Laufzeit zu berechnen, können wir sie im Voraus berechnen und das Ergebnis in unserem Asset speichern, zum Beispiel, indem wir Schatten auf unsere Texturen zeichnen oder berechnen. Dieser Prozess wird “backen” genannt.

Wir können sogar die gleichen Methoden wie in der 3D-Animation verwenden und so sehr realistische Ergebnisse erzielen.

Texturen funktionieren gut, da sie eine große Menge an Details mit feinen Schatten- und Lichteffekten speichern können. Insbesondere mit dem Texture Streaming der Wonderland Engine kannst Du sehr hochauflösende Texturen verwenden und erstaunlich aussehende Szenen erstellen.

Texturen benötigen jedoch viel Speicherplatz, auch wenn sie gut komprimiert sind. Stattdessen können wir einige Details gegen die Downloadgröße austauschen und ein zusätzliches Farb-Attribut in Deinem Mesh pro Vertex speichern.

Lightmap-Texturen vs. Vertexfarben 

Beim Backen von Licht in Texturen wird unsere Lichtberechnung auf der GPU hauptsächlich auf einen Textur-Read reduziert: Für jedes Pixel, das wir auf den Bildschirm rendern, suchen wir das richtige Pixel in der Lightmap. Jedes gerenderte Pixel kann eine andere Farbe aus der Lightmap holen, was sehr hochfrequente Details ermöglicht.

Vertexfarben hingegen sind Eingaben für den Vertexshader und werden zwischen den Vertices interpoliert. Die Frequenz der Details hängt von der Auflösung Deines Meshes ab und ist allgemein sehr niedrig. Dies reduziert die Berechnung der Pixel-Farbe noch weiter auf das einfache Durchreichen der interpolierten Farbe vom Vertexshader zum Output-Framebuffer.

Performance 

Was ist performanter? Die Antwort auf jede Performancefrage lautet immer: Es kommt darauf an. Besonders auf Deine Engpässe.

Viele WebXR-Apps sind heute Zeichnungsaufruf-gebunden: Die CPU kann keine zusätzliche Arbeit leisten, daher hat die Optimierung der GPU-Arbeitslast keinen Effekt. Möglicherweise auf die Akkulaufzeit, aber nicht auf Deine Framerate.

Die Wonderland Engine löst dies vollständig mit ihren Optimierungen und rendert Zehntausende dynamischer Objekte in weniger als zehn Zeichnungsaufrufen in fast jedem Fall. Dass einige andere Apps durch Vertex-Shading begrenzt sind, indem sie viele animierte Charaktere skinnieren, wird mit einer hoch performanten, VR-optimierten Skinning-Methode gelöst, die hunderte unterschiedlicher geskinnerter Meshes effizient verarbeiten kann.

Aber selbst Wonderland Engine-Apps können durch Fragmentshading eingeschränkt sein. Mehr Anweisungen und teurere Operationen in Deinem Fragmentshader erfordern mehr Rechenleistung von der GPU pro Pixel auf dem Bildschirm. Unser “Physical” (PBR) Shader hat mehr Anweisungen als “Phong”, der wiederum mehr als “Flat” hat.

Während moderne GPUs sehr schnell im Lesen von Texturen sind, wird das bloße Lesen der Farben aus den Mesh-Daten während des Vertex-Fetches speichereffizienter und ist schwer zu übertreffen, besonders wenn dies auch bedeutet, dass Du Normalen und Texturkoordinaten aus Deinem Mesh vollständig weglassen kannst. Für diese Technik können wir einen untexturierten Flat-Shader verwenden, der nur Positionen und Farben benötigt.

Dies hinterlässt eine kleinere Menge an Speicher, die pro Vertex gelesen werden muss, und fast keine Arbeit pro Fragment. Dies würde uns nur durch Vertexshading oder Vertex-Fetching begrenzen, jedoch nur bei sehr beeindruckenden Vertex-Mengen in unserer Szene, wie im Summary gezeigt.

Tutorial 

Wir beginnen mit dem Backen von Licht in Vertexfarben in Blender und importieren das Modell dann in die Wonderland Engine.

In Vertexfarben in Blender backen 

Wähle eine Szene und richte Lichter ein. Blender unterstützt bereits vollständig das Backen zu Vertexfarben, daher sind keine Plugins nötig, und das Setup ist einfach:

  1. Öffne ein Skriptfenster in Blender und verwende das folgende Python-Skript, um eine Vertexfarbenschicht zu allen ausgewählten Objekten hinzuzufügen, indem Du dieses Skript ausführst:
1import bpy
2
3for o in bpy.context.selected_objects:
4    if o.type != 'MESH':
5        continue
6    if len(o.data.vertex_colors) != 0:
7        continue
8
9    o.data.vertex_colors.new()
  1. In den Render Properties wechsele die Render-Engine zu Cycles
  2. Finde den Bake-Abschnitt weiter unten und schalte Output > Target auf Vertex Colors um
  3. Setze den Bake Type auf Diffuse
  4. Drücke den Bake-Button oben in diesem Abschnitt

Um das Ergebnis zu sehen, kannst Du die Ansichtseinstellungen so einstellen, dass das Ergebnis visualisiert wird:

  1. In der 3D-Ansicht finde den Pfeil neben den Rendertypen (normalerweise der ganz rechte Button im oberen Menü)
  2. Für Lighting wähle Flat
  3. Für Color wähle Vertex
Vertex Color Baked Lighting mit Wonderland Engine

Zum Schluss exportiere das Modell als GLB, indem Du File > Export > glTF 2.0 (.glb/.gltf) auswählst.

Import in Wonderland Engine 

Erstelle die folgende VertexColor.frag in einem Unterordner shaders in Deinem Projekt:

 1#include "lib/Compatibility.frag"
 2
 3#define USE_COLOR
 4
 5#define USE_MATERIAL_ID
 6#include "lib/Inputs.frag"
 7
 8void main() {
 9    outColor = fragColor;
10}

Als nächstes importieren wir das Modell in die Wonderland Engine und verwenden diesen Shader, um es darzustellen:

  1. Ziehe die .glb-Datei in den Asset-Browser
  2. Von dort ziehe sie in die Szenenansicht
  3. Gehe zu Views > Resources > Pipelines und wähle Phong Opaque oder Phong Opaque Textured, je nachdem, ob Deine Objekte ursprünglich Texturen verwendet haben.
  4. Ändere den Shader in den neuen VertexColor Shader.

Indem wir die bestehende Phong-Pipeline ändern, können wir automatisch alle Materialien ändern. Ein saubereres Setup wäre, die automatisch erstellte “VertexColor”-Pipeline zuzuweisen und sie allen Materialien zuzuweisen, die wir ändern möchten.

Nun solltest Du die Vertexfarben korrekt auf Deine Szene angewendet sehen.

Vertex Color Baked Lighting mit Wonderland Engine

Zusammenfassung 

Das Backen von Licht in Vertexfarben ist eine sehr effiziente Methode, um schön aussehende Visuals zu erzielen. Das folgende Video demonstriert 3,6 Millionen Vertices, die mit dieser Methode mit 60-72 fps auf Meta Quest 2 im Meta Quest Browser gerendert werden.

YouTube Video

Die Demo verwendet die Out-of-the-box-Optimierungen der Wonderland Engine, Fixed-Foveation (bei 1.0) und die in diesem Blogbeitrag beschriebene Methode. Die Szene wird in 2 Draw Calls gerendert (seit 0.9.4, die bevorstehende Unterstützung für Multiview-Rendering wird diese Zahl um 50 % reduzieren). Jedes Objekt könnte immer noch unabhängig über Skripte oder Animationen bewegt werden, ohne die Performance negativ zu beeinflussen.

Last Update: December 2, 2022

Bleiben Sie auf dem Laufenden.