Lightmaps und globale Beleuchtung
Einführung
Hinweis: Ab Qt 6.4 befindet sich das Lightmap-Backing in einem frühen Stadium der technischen Vorschau. Änderungen an den Funktionen, der Qualität und der API werden wahrscheinlich in zukünftigen Versionen erfolgen.
Mit gebackenen Lightmaps kann die direkte Beleuchtung von Lichtern wie DirectionalLight, PointLight und SpotLight vorgeneriert werden, einschließlich der von den Lichtern geworfenen Schatten. Anstatt zur Laufzeit die entsprechenden Berechnungen im Fragment-Shader durchzuführen und im Falle von Schatten die potenziell kostspieligen Shadow Maps in Echtzeit zu generieren, wird stattdessen die vorgenerierte Image Map abgetastet.
Pro Model wird eine Lightmap erzeugt. Selbst wenn ein Model mehrere Submeshes hat und daher mit mehreren Materialien verbunden ist, wird ein einziges Lightmap-Bild für das gesamte Modell erzeugt.
Lightmaps werden mit Raytracing erzeugt, das von Natur aus für eine korrekte Okklusion ("Licht geht nicht durch Wände") und möglicherweise realistischere Schatten sorgt als die Echtzeittechniken für Beleuchtung und Schattenmapping.
Noch wichtiger ist, dass Lightmaps auch das Backen von indirekter Beleuchtung ermöglichen und eine Lösung für globale Beleuchtung bieten. Dabei werden Lichtstrahlen, die von anderen Oberflächen in der Szene reflektiert werden, berücksichtigt.
Nachfolgend ein einfaches Beispiel. Die Szene enthält vier Rechteck- und ein Kugelmodell mit einem nach unten zeigenden DirectionalLight und einem PointLight. Die Rechteckmodelle sind um 0 und 90 Grad gedreht, was die Einschränkungen der Echtzeit-Beleuchtungsberechnungen übertreibt, da sie alle entweder parallel oder senkrecht zur Richtung des DirectionalLight sind.
Im zweiten Bild wird die Szene mit aktiviertem Lightmapping gerendert, nachdem die Lightmaps für alle fünf Modelle gebacken wurden. Beide Lichter sind auf vollständig gebacken eingestellt, d. h. sowohl die direkte als auch die indirekte Beleuchtung sind gebacken. Für die indirekte Beleuchtung werden 256 samples und maximal 3 bounces verwendet. Die resultierenden Lightmaps wurden dann entrauscht. Das Ergebnis ist ein wesentlich realistischeres Bild.
Beleuchtung in Echtzeit
Vollständig gebackene Beleuchtung
Der folgende Ausschnitt zeigt, wie die Lightmapping-Ergebnisse erzielt wurden. Der Unterschied liegt in den Eigenschaften usedInBakedLighting, bakeMode und bakedLightmap. In diesem Beispiel wurde die Größe der Lichtkarte mit der Eigenschaft texelsPerUnit reduziert, um Speicherplatz zu sparen und die Ladezeiten der Anwendung zu verringern.
DirectionalLight { bakeMode: Light.BakeModeAll eulerRotation.x: -90 brightness: 0.5 castsShadow: true shadowFactor: 75 } PointLight { bakeMode: Light.BakeModeAll y: 200 z: 100 color: "#d9c62b" castsShadow: true shadowFactor: 75 } Model { usedInBakedLighting: true bakedLightmap: BakedLightmap { enabled: true key: "sphere1" } source: "#Sphere" materials: PrincipledMaterial { } y: 100 } Model { usedInBakedLighting: true bakedLightmap: BakedLightmap { enabled: true key: "rect1" } source: "#Rectangle" materials: PrincipledMaterial { } eulerRotation.x: -90 scale: Qt.vector3d(10, 10, 10) } // ... three additional Rectangle models, with rotations 0, 90, and -90
Im obigen Beispiel wurden vollständig gebackene Lichter verwendet. Ein Licht kann auch so konfiguriert werden, dass nur die gebackene Beleuchtung für die indirekte Beleuchtung verwendet wird, während die direkte Beleuchtung und die Schattenzuordnung in Echtzeit erfolgen. In der folgenden Szene gibt es 5 Punktlichter, die für den zweiten Screenshot alle auf BakeModeIndirect eingestellt sind. Während die direkte Beleuchtung und die Schatten identisch aussehen, sieht das zweite Bild aufgrund der zusätzlichen globalen Beleuchtung deutlich besser aus.
Beleuchtung in Echtzeit
Mit gebackener indirekter Beleuchtung
Wichtige Überlegungen bei der Arbeit mit Lichtkarten
Bei Lichtern, die zur gebackenen Beleuchtung beitragen, ist die Eigenschaft bakeMode entweder auf Light.BakeModeIndirect oder Light.BakeModeAll eingestellt. Letzteres bedeutet, dass sowohl der direkte als auch der indirekte Beitrag für dieses bestimmte Licht von der Lichtkarte stammt. Der direkte Beitrag umfasst immer auch Schatten. Andererseits, wenn die Absicht mit der Lightmap nur darin besteht, der Szene eine indirekte Beleuchtung für ein bestimmtes Licht hinzuzufügen, während immer noch eine direkte Beleuchtung in Echtzeit berechnet wird (und Schatten-Mapping durchgeführt wird), dann sollte das Licht stattdessen Light.BakeModeIndirect verwenden.
Hinweis: Lightmaps sind im Allgemeinen für Modelle geeignet, die in Bezug auf Transformation, Geometrie und Materialien statisch sind. Das Gleiche gilt für die Lichter, die an der gebackenen Beleuchtung teilnehmen.
Eine Szene, die zum Beispiel ein Model durch Animieren der Eigenschaft eulerRotation dreht, wird visuell falsche Ergebnisse liefern, wenn eine Lightmap auf dieses Model angewendet wird. Die Rendering-Ergebnisse für diese spezielle Model werden falsch sein, da die vorgenerierte Lightmap nur einen einzigen Rotationszustand für das Objekt erfasst. Das Gleiche gilt, um ein anderes Beispiel zu nennen, wenn das Material für eine der Untermaschen des Modells seine baseColor Eigenschaft dynamisch ändert, basierend auf der Zeit (Animation) oder einer Benutzerinteraktion. Die Lichtkarte kann nur ein bestimmtes Material baseColor erfassen. Das Gleiche gilt für Lichter. Zum Beispiel ist eine DirectionalLight, die sich dreht, ihre Helligkeit, Farbe usw. mit der Zeit ändert, nicht für gebackene Beleuchtung geeignet.
Hinweis: Andererseits ist es immer eine Entscheidung des Designers, wann er Lightmapping verwenden möchte. Besonders bei BakeModeIndirect Lichtern ist es wahrscheinlich, dass es Szenen gibt, bei denen die Ergebnisse immer noch visuell zufriedenstellend sind, auch wenn einige der Objekte in der Lightmapping-Szene ein dynamisches Verhalten aufweisen.
Lightmapping ist ein komplexes Engine- und Tooling-Feature. Es ersetzt und implementiert mehrere Teile der Rendering-Pipeline der Engine neu. Beim Backen von Lightmaps wird mit einem grundlegend anderen Rendering-Modell gearbeitet, wobei jedoch dieselbe Szenenstruktur, dieselben Asset-Daten und dieselben Datenstrukturen der Engine verwendet werden und mit ihnen interagieren. Die auf Raytracing basierenden Ergebnisse sind den Echtzeit-Alternativen oft überlegen, manchmal sogar deutlich, was auf Kosten von Einschränkungen geht, wie z. B. der obligatorischen Statik der beteiligten Modelle und Lichter und manchmal Qualitäts- und Rendering-Artefakt-Problemen, die spezifisch für Lightmapping sind.
In der Praxis wird es eine künstlerische Entscheidung der Designer sein, welche Art von Beleuchtung sie wann verwenden. Alle drei Einstellungen von bakeMode haben ihre Berechtigung, und in komplexen, größeren Szenen kann es durchaus vorkommen, dass alle drei für verschiedene Beleuchtungen verwendet werden, je nachdem, was für einen bestimmten Abschnitt der Szene als geeignet erachtet wird und welche Art von Modellen, Materialien und dynamischem Verhalten vorhanden ist. Lightmapping ist kein einfacher Ein/Aus-Schalter, der für jede Szene und Anwendung aktiviert werden kann, sondern eine leistungsstarke Funktion, die eine sorgfältige Bewertung der Beleuchtungsanforderungen einer bestimmten Szene voraussetzt und oft erfordert, dass der Inhalt und das Verhalten der Szene entsprechend gestaltet werden, kombiniert mit einer Test- und Abstimmungsschleife, in der verschiedene Lightmap-Backing- und Qualitätseinstellungen erforscht und getestet werden, bevor man sich für den endgültigen Ansatz und die entsprechenden Einstellungen entscheidet.
Hinweis: Lightmaps unterstützen keine zweiseitigen Oberflächen. Bei Echtzeit-Beleuchtung kehrt ein Material mit einer cull mode von Material.NoCulling
die Normalen automatisch um, je nach der Ausrichtung des Fragments. Dies ist bei Lightmaps nicht möglich, da das Backen von Lightmaps nicht im View Space funktioniert. Vermeiden Sie daher gebackene Beleuchtung für Modelle, die darauf angewiesen sind.
Backen von Lightmaps
Eigenschaften und Typen, die für das Baking von Lightmaps relevant sind, d. h. den Offline-Prozess der Erzeugung von Image Maps, die direkte und indirekte Beleuchtung erfassen und vom Renderer in nachfolgenden Durchläufen der Anwendung verwendet werden können:
- Model::usedInBakedLighting
- Model::lightmapBaseResolution,
- Light::bakeMode,
- Lightmapper und SceneEnvironment::lightmapper
- BakedLightmap und Model::bakedLightmap
Ab Qt 6.4 muss der Lightmap-Backvorgang manuell ausgelöst werden. Immer wenn das Kommandozeilenargument --bake-lightmaps
vorhanden ist oder die Umgebungsvariable QT_QUICK3D_BAKE_LIGHTMAPS
auf 1
(oder einen anderen Wert ungleich Null) gesetzt ist, arbeitet die Engine im Backmodus und beendet die Anwendung, sobald das Backen abgeschlossen ist. Die Schritte des Backvorgangs können anhand der Meldungen in der Debug-Ausgabe nachvollzogen werden. Das Ergebnis ist eine Binärdatei (standardmäßiglightmaps.bin
), die in das aktuelle Arbeitsverzeichnis geschrieben wird und alle gebackenen Lightmaps in der Szene enthält. Es wird auch eine .raw
Datei erstellt, die die gesamte Lightmap und einige zusätzliche Daten enthält, die für das Denoising benötigt werden. Jede Lightmap wird in der Datei durch den eindeutigen Schlüssel von BakedLightmap::key eindeutig identifiziert.
Die Vorbereitung einer Lightmap-Szene erfolgt in den folgenden Hauptschritten:
- Identifizieren Sie, welche Modelle eine Lightmap verwenden sollen und welche Modelle zur Lightmap beitragen sollen. Modelle, die Teil der Lightmap-Szene sind, sollten Model::usedInBakedLighting auf true setzen. Modelle, die lightmapped sind (d.h. für die eine Lightmap gebacken werden soll), sollten zusätzlich Model::bakedLightmap auf ein aktiviertes BakedLightmap Objekt setzen, das einen eindeutigen Schlüssel bereitstellt, der die bestimmte Model-Objektinstanz dauerhaft identifiziert (dies ist so, weil Qt einen Schlüssel benötigt, um die Modelldaten im persistenten Plattenspeicher zu identifizieren). Nur Modelle mit statischer Geometrie, Transformation und Materialien haben garantiert korrekte Ergebnisse, wenn sie zur Laufzeit mit Licht abgebildet werden. In der Regel wird alles, was zu einer nicht statischen Welttransformation über die Zeit führt, wie z.B. eine dynamisch veränderte oder animierte Position, Rotation oder Skalierung, das Modell von der Teilnahme ausschließen. Künstlerische Anforderungen können dies jedoch außer Kraft setzen, insbesondere bei Modellen, die nur zur gebackenen indirekten Beleuchtung beitragen, aber selbst nicht beleuchtet sind. Für diese kann es oft visuell akzeptabel sein, dynamische Transformationen zu haben, aber das hängt immer von dem Modell und der betreffenden Szene ab.
- Legen Sie fest, welche Lichter in welchem Ausmaß beitragen sollen. Light::bakeMode bietet drei Optionen:
- Light.BakeModeDisabled, die Standardeinstellung, bei der das Licht für alle Lightmapping-Zwecke effektiv ignoriert wird.
- Light.BakeModeIndirect ist oft die "sichere" Wahl, wenn das einzige Ziel darin besteht, ein gewisses Maß an globaler Beleuchtung (indirekte Beleuchtung) in der Szene zu haben, ohne die Rendering-Ergebnisse für das Licht auf andere Weise zu beeinflussen. In diesem Modus führt der Renderer weiterhin alle Beleuchtungen, einschließlich diffuser, spiegelnder, Himmels-/Umgebungsbeiträge und Schattenzuordnung für dieses Licht unter Verwendung der Standard-Echtzeittechniken aus. Das Licht trägt jedoch zur indirekten Beleuchtung bei, indem es die vorgebackenen Daten verwendet, was dazu führen kann, dass Oberflächen beleuchtet werden, die ansonsten von den Standard-Echtzeitbeleuchtungsberechnungen unberührt bleiben.
- Light.BakeModeAll ist eine Option, die wahrscheinlich nur für bestimmte Lichter verwendet wird, basierend auf der Einschätzung der Designer, was für eine bestimmte Szene als angemessen erachtet wird. In diesem Modus wird der gesamte Beitrag des Lichts gebacken, einschließlich der Schatten. Seit Qt 6.4 werden spiegelnde Lichter nicht mehr als Teil der gebackenen Beleuchtung unterstützt, so dass solche Lichter keine spiegelnden Beiträge haben. Auf der anderen Seite erzeugen sie raytraced, gebackene Schatten und haben eine korrekte Okklusion für das Licht (gehen z.B. nicht durch Wände), da hier alle direkten Beleuchtungsbeiträge, die aus dem Licht resultieren, zum Zeitpunkt des Backens der Lightmap raytraced werden, anstatt zur Laufzeit berechnet zu werden. Außerdem wird die indirekte Beleuchtung gebacken, genau wie bei BakeModeIndirect.
- Ausführen der Szene (Anwendung) im Backmodus, um sicherzustellen, dass Lightmaps erfolgreich erzeugt werden. Ab Qt 6.4 wird erwartet, dass Anwendungen so strukturiert sind, dass die Lightmap-Szene die erste Ansicht ist, die angezeigt wird, oder dass die betreffende Szene mit einem QML-Viewer wie dem
qml
Tool geladen werden kann. Nach Abschluss des Backvorgangs, dessen Fortschritt in der Konsole/Debug-Ausgabe verfolgt werden kann, wird die Anwendung beendet. - Die Szene (Anwendung) wird normal ausgeführt, um zu sehen, wie sie mit den geladenen Lightmaps aussieht. Dann kann das Tuning beginnen:
- Bei einigen Modellen wird es sinnvoll sein, texelsPerUnit vom Standardwert auf einen kleineren Wert zu reduzieren. Dies gilt vor allem für die eingebauten Primitive und alles mit einfacher Geometrie. Dies führt zu kleineren Lightmaps und schnelleren Bake-Zeiten. Beim ersten Backen sollte der Standardwert ausreichend sein, danach kann der Wert angepasst werden.
- Das Lightmapper-Objekt bietet zahlreiche Einstellungen mit vernünftigen Standardwerten, aber es ist nicht unwahrscheinlich, dass einige davon angepasst werden müssen, damit sie den Erwartungen der Designer entsprechen. Zum Beispiel können samples und bounces geändert werden, um die Qualität der indirekten Beleuchtung zu beeinflussen, während indirectLightFactor es ermöglicht, den indirekten Beitrag stärker hervorzuheben. Wenn Artefakte, insbesondere im Schattenbereich, auftreten, kann bias feiner abgestimmt werden.
- Die Entrauschung der erzeugten Lichtkarten ist unerlässlich. Die indirekte Beleuchtung wird mit Hilfe der Pfadverfolgung berechnet, die je nach Anzahl der verwendeten samples verrauschte Bilder erzeugt. Eine Erhöhung der Stichprobenzahl verringert das Rauschen, erhöht aber die für die Erstellung der Lichtkarte benötigte Zeit. Unabhängig von der Anzahl der Samples ist es fast immer sinnvoll, die erzeugten Lightmaps, bei denen es sich um 32-Bit-RGBA-Fließkommabilder handelt, die in einer Binärdatei gespeichert sind, mit einem Denoiser zu bearbeiten.
Seit Qt 6.5 wird eine Laufzeitlösung interaktiv über DebugView bereitgestellt. Unter Tools gibt es nun eine Schaltfläche, die bei Betätigung den Backprozess auslöst. Es öffnet sich ein Fenster, das den aktuellen Prozess anzeigt. Der Vorgang kann entweder durch Drücken der Schaltfläche Abbrechen oder durch Schließen des Fensters abgebrochen werden. Wenn der Vorgang abgeschlossen ist, wird die Lightmap-Binärdatei in das aktuelle Verzeichnis geschrieben.
Rauschunterdrückung
Unten sehen Sie ein Beispiel für eine Cornell-Box-Szene, die zunächst mit der Lightmap Baked mit 256 samples und maximal 3 bounces gerendert wurde. Im zweiten Beispiel wurde die erzeugte Bilddatei entrauscht, und die Ergebnisse sehen deutlich besser aus, da das Rauschen weitgehend verschwunden ist.
Original
Entrauscht
Die Entrauschung wird automatisch für jede gebackene Lightmap durchgeführt. Es ist möglich, nur eine Entrauschung vorzunehmen, wenn eine gebackene .raw
Lightmap-Datei im Arbeitsverzeichnis vorhanden ist, indem Sie auf die Schaltfläche Denoise
in DebugView klicken. Es ist auch möglich, eine Entrauschung durchzuführen, indem Sie die Anwendung mit dem Argument --denoise-lightmaps
aufrufen. Um die Stärke der Rauschunterdrückung einzustellen, kann die Eigenschaft denoiseSigma verwendet werden.
Lightmap-UVs
Lightmap-UV-Koordinaten verwenden nicht die gleichen UV-Daten wie reguläre Texturen. Beim Rendering mit Lightmaps werden weder die UV0- noch die UV1-Daten vom Renderer beim Abtasten der Lightmap verwendet. Stattdessen gibt es einen zusätzlichen, dedizierten UV-Kanal im Mesh, der UV-Karten enthält, die so angeordnet sind, dass sie für die Zwecke des Lightmappings geeignet sind. Dazu gehört, dass Überschneidungen vermieden werden und gegebenenfalls Polsterungen vorhanden sind. Für reguläre UV-Daten gibt es keine derartigen Anforderungen, und man kann sehr wohl dieselben U- und V-Koordinaten für mehr als einen Scheitelpunkt verwenden wollen.
Der Prozess der Erzeugung eines geeigneten UV-Sets wird Lightmap-UV-Unwrapping genannt. Qt führt dies beim Backen von Lightmaps durch und speichert das resultierende Mesh in der Lightmaps-Datei, so dass immer ein kompatibles Mesh geladen und für die erzeugte Lightmap verwendet wird. Das bedeutet, dass, wenn ein Modell immer gebackene Beleuchtung verwendet, die Quell-Mesh-Datei nicht mit der Anwendung ausgeliefert werden muss.
Größe der Lightmap-Textur
Für jedes Modell, einschließlich aller seiner Submeshes, bestimmt der Lightmap-Backprozess während der Lightmap-UV-Erzeugungsphase eine geeignete Lightmap-Texturgröße. Dies hat Auswirkungen auf die Qualität, die Leistung und den Ressourcenverbrauch (sowohl auf der Festplatte als auch im Speicher).
Die Standardeinstellung ist oft geeignet und muss nicht angepasst werden, insbesondere bei Modellen mit mittlerer bis hoher Komplexität.
Bei sehr einfachen Modellen kann es jedoch wünschenswert sein, die Größe manuell zu verringern, da eine geringere Größe der Lichtkarte immer noch visuell gut aussehende Ergebnisse liefern kann, während die Verringerung der Größe des Assets (Lichtkartenbild) sowohl Festplattenplatz als auch Speicherplatz spart. Setzen Sie dazu texelsPerUnit auf eine entsprechend kleine Zahl. Die tatsächliche Lightmap-Breite und -Höhe wird dann, je nach Größe und Geometrie des Modells, versuchen, sich der Texeldichte anzunähern, so dass sie mit texelsPerUnit übereinstimmt.
Wenn man den Wert ändert, sollte man die Lightmaps immer neu backen und die Ergebnisse visuell überprüfen, um die Auswirkungen der geänderten Lightmap-Größe zu beurteilen.
Verwendung von Lightmaps zur Laufzeit
Eigenschaften und Typen, die bei der Verwendung der vorgebackenen Lightmaps zur Laufzeit relevant sind:
Nach erfolgreichem Abschluss des Backvorgangs wird die Anwendung bei normaler Ausführung (ohne Befehlszeilenargument oder Umgebungsvariable) die erzeugten Lightmap-Bilder aufnehmen und korrekt rendern, was erst nach dem Backen der Lightmaps möglich ist. Falls gewünscht, kann die Anwendung diese an einem anderen Ort ablegen oder sie als Teil der ausführbaren Datei über das Qt Resource System ausliefern. Dies wird durch die Eigenschaft source ermöglicht.
Nimmt man den Beispielcode mit der Kugel und den vier Rechtecken von oben, erzeugt der Baking-Prozess eine lightmaps.bin
Datei, die alle gebackenen Meshes und Lightmaps enthält. Die Anwendung muss diese Datei ausliefern, damit sie von der Engine gefunden werden kann, und zwar an dem durch source angegebenen Ort.
Siehe auch Qt Quick 3D - Baked Lightmap Beispiel.
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.