Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Interne Rendering-Architektur

Diese Seite gibt einen Überblick über das interne Renderer-Design von Godot 4. Sie gilt nicht für frühere Godot-Versionen.

Das Ziel dieser Seite ist es, Design-Entscheidungen zu dokumentieren, die getroffen wurden, um der Godot Design-Philosophie am besten zu entsprechen, und gleichzeitig einen Ausgangspunkt für neue Rendering-Mitwirkende zu bieten.

Wenn Sie Fragen zu Rendering-Interna haben, die hier nicht beantwortet werden, können Sie diese im #rendering-Kanal des Godot Mitwirkenden-Chat stellen.

Bemerkung

Wenn Sie Schwierigkeiten haben, die Konzepte auf dieser Seite zu verstehen, ist es empfehlenswert, ein OpenGL-Tutorial wie LearnOpenGL durchzuarbeiten.

Moderne Low-Level-APIs (Vulkan/Direct3D 12) erfordern Zwischenkenntnisse über Higher-Level-APIs (OpenGL/Direct3D 11), um effektiv genutzt werden zu können. Glücklicherweise müssen die Mitwirkenden nur selten direkt mit Low-Level-APIs arbeiten. Godots Renderer basieren vollständig auf OpenGL und RenderingDevice, das unsere Abstraktion von Vulkan/Direct3D 12 ist.

Rendering-Methoden

Forward+

Dies ist ein Vorwärts-Renderer, der einen Cluster-Ansatz für die Beleuchtung verwendet.

Bei der Cluster-Beleuchtung wird ein Compute-Shader verwendet, um die Lichter in einem an 3D-Frustum-ausgerichteten Raster zu gruppieren. Zur Renderzeit können die Pixel dann nachsehen, welche Lichter die Rasterzelle, in der sie sich befinden, beeinflussen, und nur Lichtberechnungen für Lichter durchführen, die dieses Pixel beeinflussen könnten.

Dieser Ansatz kann die Rendering-Performance auf Desktop-Hardware erheblich beschleunigen, ist aber auf mobilen Geräten wesentlich weniger effizient.

Forward Mobile

Dies ist ein Vorwärts-Renderer, der einen traditionellen Single-Pass-Ansatz für die Beleuchtung verwendet.

Gedacht für mobile Plattformen, kann aber auch auf Desktop-Plattformen ausgeführt werden. Diese Rendering-Methode ist für eine gute Performance auf mobilen GPUs optimiert. Mobile GPUs haben eine ganz andere Architektur als Desktop-GPUs, da sie besondere Einschränkungen in Bezug auf den Batterieverbrauch, die Wärmeentwicklung und die allgemeine Bandbreitenbeschränkung beim Lesen und Schreiben von Daten haben. Auch Compute-Shader werden nur sehr eingeschränkt oder gar nicht unterstützt. Infolgedessen verwendet der Mobile-Renderer ausschließlich rasterbasierte Shader (Fragment/Vertex).

Im Gegensatz zu Desktop-GPUs führen mobile GPUs Tile-Based-Rendering durch. Anstatt das gesamte Bild als eine Einheit zu rendern, wird das Bild in kleinere Kacheln unterteilt, die in den schnelleren internen Speicher der mobilen GPU passen. Jede Kachel wird gerendert und dann in die Zieltextur geschrieben. Dies geschieht alles automatisch durch den Grafiktreiber.

Das Problem ist, dass dies zu Engpässen in unserem traditionellen Ansatz führt. Beim Desktop-Rendering werden zunächst alle undurchsichtigen Geometrien gerendert, dann der Hintergrund bearbeitet, dann die transparenten Geometrien und schließlich die Nachbearbeitung. Jeder Durchlauf muss das aktuelle Ergebnis in den Kachel-Speicher einlesen, seine Operationen durchführen und es dann wieder herausschreiben. Anschließend warten wir, bis alle Kacheln fertiggestellt sind, bevor wir zum nächsten Durchgang übergehen.

Die erste wichtige Änderung im mobilen Renderer ist, dass der mobile Renderer nicht die RGBA16F-Texturformate verwendet, die der Desktop-Renderer verwendet. Stattdessen wird ein R10G10B10A2 UNORM-Texturformat verwendet. Dadurch halbiert sich die erforderliche Bandbreite und es ergeben sich weitere Verbesserungen, da die mobile Hardware häufig für 32-Bit-Formate optimiert ist. Der Nachteil ist, dass der mobile Renderer aufgrund der reduzierten Präzision und der Maximalwerte in den Farbdaten nur begrenzte HDR-Fähigkeiten hat.

Die zweite wichtige Änderung ist die Verwendung von Sub-Passes, wann immer dies möglich ist. Mit Sub-Passes können wir die Rendering-Schritte Ende-zu-Ende pro Kachel durchführen und so den Overhead einsparen, der durch das Lesen von und Schreiben in die Kacheln zwischen den einzelnen Rendering-Durchgängen entsteht. Die Möglichkeit, Sub-Passes zu verwenden, wird durch die Unmöglichkeit eingeschränkt, benachbarte Pixel zu lesen, da wir auf die Arbeit innerhalb einer einzelnen Kachel beschränkt sind.

Diese Einschränkung von Subpasses führt dazu, dass Features wie Glow und Schärfentiefe nicht effizient implementiert werden können. Ähnlich verhält es sich, wenn aus der Bildschirmtextur oder der Tiefentextur gelesen werden muss, so dass das Rendering-Ergebnis vollständig ausgeschrieben werden muss, was die Möglichkeit der Verwendung von Subpasses einschränkt. Wenn solche Features aktiviert sind, wird eine Mischung aus Sub-Passes und normalen Passes verwendet, und diese Features führen zu einem erheblichen Performanceverlust.

Auf Desktop-Plattformen hat die Verwendung von Sub-Passes keine Auswirkungen auf die Performance. Dennoch kann diese Rendering-Methode bei einfachen Szenen aufgrund ihrer geringeren Komplexität und geringeren Bandbreitennutzung besser abschneiden als Clustered Forward. Dies macht sich besonders auf leistungsschwachen Grafikprozessoren, integrierten Grafiken oder in VR-Anwendungen bemerkbar.

Da diese Rendering-Methode auf das einfache Rendering ausgerichtet ist, bietet sie keine High-End-Rendering-Features wie SDFGI und Volumetrischer Nebel und Nebelvolumen. Verschieden Nachbearbeitungseffekte sind ebenfalls nicht verfügbar.

Kompatibilität

Bemerkung

Dies ist die einzige Rendering-Methode, die bei Verwendung des OpenGL-Treibers verfügbar ist. Diese Rendering-Methode ist nicht verfügbar, wenn Sie Vulkan oder Direct3D 12 verwenden.

Dies ist ein traditioneller (nicht geclusterter) Vorwärtsrenderer. Er ist für alte GPUs gedacht, die keine Vulkan-Unterstützung haben, funktioniert aber auch auf neuerer Hardware sehr effizient. Insbesondere ist er für ältere und leistungsschwächere Mobilgeräte optimiert. Allerdings werden viele Optimierungen übernommen, sodass er auch für ältere und leistungsschwächere Desktop-Geräte eine gute Wahl ist.

Wie der mobile Renderer verwendet auch der Kompatibilitäts-Renderer eine R10G10B10A2 UNORM-Textur für das 3D-Rendering. Im Gegensatz zum mobilen Renderer werden die Farben im sRGB-Format gespeichert, sodass keine HDR-Unterstützung vorhanden ist. Dadurch wird ein Tonemapping-Durchgang überflüssig und wir können die Textur mit niedrigeren Bits ohne erhebliches Banding verwenden.

Der Kompatibilitäts-Renderer verwendet einen traditionellen Forward-Single-Pass-Ansatz zum Zeichnen von Objekten mit Lichtern, aber er verwendet einen Multi-Pass-Ansatz, um Lichter mit Schatten zu zeichnen. Insbesondere kann er im ersten Durchgang mehrere Lichter ohne Schatten und bis zu einem DirectionalLight3D mit Schatten zeichnen. In jedem weiteren Durchgang kann er bis zu einem OmniLight3D, einem SpotLight3D und einem DirectionalLight3D mit Schatten zeichnen. Lichter mit Schatten wirken sich anders auf die Szene aus als Lichter ohne Schatten, da die Beleuchtung im sRGB-Raum und nicht im linearen Raum gemischt wird. Dieser Unterschied in der Beleuchtung wirkt sich auf das Aussehen der Szene aus und muss bei der Gestaltung von Szenen für den Kompatibilitätsrenderer berücksichtigt werden.

Angesichts des Low-End-Schwerpunkts bietet diese Rendering-Methode keine High-End-Rendering-Features (noch weniger als Forward Mobile). Die meisten Nachbearbeitungseffekte sind nicht verfügbar.

Warum kein verzögertes Rendering?

Forward Rendering bietet im Allgemeinen einen besseren Kompromiss zwischen Performance und Flexibilität, insbesondere wenn ein Cluster-Ansatz für die Beleuchtung verwendet wird. Verzögertes Rendering kann zwar in einigen Fällen schneller sein, ist aber auch weniger flexibel und erfordert die Verwendung von Hacks, um MSAA nutzen zu können. Da Spiele mit einem weniger realistischen Grafikstil sehr von MSAA profitieren können, haben wir uns bei Godot 4 (wie bei Godot 3) für Forward Rendering entschieden.

Allerdings werden Teile des Vorwärtsrenderers mit einem verzögerten Ansatz ausgeführt, um einige Optimierungen zu erreichen, wenn dies möglich ist. Dies gilt insbesondere für VoxelGI und SDFGI.

Für die Zukunft ist die Entwicklung eines "geclusterten verzögerten Renderers" geplant. Dieser Renderer könnte in Situationen verwendet werden, in denen die Performance gegenüber der Flexibilität im Vordergrund steht.

Rendering-Treiber

Godot 4 unterstützt die folgenden Grafik-APIs:

Vulkan

Dies ist der Haupttreiber in Godot 4, auf den der größte Teil der Entwicklung ausgerichtet ist.

Vulkan 1.0 ist als Basis erforderlich, wobei optionale Vulkan 1.1- und 1.2-Features verwendet werden, wenn sie verfügbar sind. volk wird als Vulkan-Loader verwendet, und Vulkan Memory Allocator wird für die Speicherverwaltung verwendet.

Sowohl Forward+ als auch Mobile Rendering-Methoden werden bei Verwendung des Vulkan-Treibers unterstützt.

Vulkan Kontexterstellung:

Direct3D 12 context creation:

Direct3D 12

Wie Vulkan zielt auch der Direct3D 12-Treiber nur auf moderne Plattformen ab. Er ist sowohl für Windows als auch für die Xbox konzipiert (während Vulkan nicht direkt auf der Xbox verwendet werden kann).

Sowohl die Forward+ als auch die Mobile-Rendering-Methoden können mit Direct3D 12 verwendet werden.

Core-Shader werden mit dem Vulkan-Renderer geteilt. Shader werden mit Hilfe von Mesa NIR von GLSL nach HLSL transpiliert (mehr Informationen). Das bedeutet, dass man HLSL nicht kennen muss, um mit dem Direct3D 12 Renderer zu arbeiten, obwohl es empfehlenswert ist, die Grundlagen der Sprache zu kennen, um die Fehlersuche zu erleichtern.

This driver is still experimental and only available in Godot 4.3 and later. While Direct3D 12 allows supporting Direct3D-exclusive features on Windows 11 such as windowed optimizations and Auto HDR, Vulkan is still recommended for most projects. See the pull request that introduced Direct3D 12 support for more information.

Metal

Godot unterstützt Metal-Rendering über MoltenVK, da macOS und iOS Vulkan nicht nativ unterstützen. Dies geschieht automatisch, wenn der Vulkan-Treiber in den Projekteinstellungen angegeben wird.

MoltenVK vereinfacht die Treiberwartung auf Kosten eines gewissen Performance-Overheads. Außerdem hat MoltenVK einige Einschränkungen, die eine native Metal-Treiber-Implementierung nicht hat. Sowohl die geclusterten als auch die mobilen Rendering-Methoden können mit einem Metal-Backend über MoltenVK verwendet werden.

Für eine bessere Performance und Kompatibilität ist für die Zukunft ein nativer Metal-Treiber geplant.

OpenGL

Dieser Treiber verwendet OpenGL ES 3.0 und zielt auf ältere und Low-End-Geräte ab, die Vulkan nicht unterstützen. OpenGL 3.3 Core Profile wird auf Desktop-Plattformen verwendet, um diesen Treiber auszuführen, da die meisten Grafiktreiber auf dem Desktop OpenGL ES nicht unterstützen. WebGL 2.0 wird für Web-Exporte verwendet.

Nur die Rendering-Methode Kompatibilität kann mit dem OpenGL-Treiber verwendet werden.

Core-Shader sind völlig anders als der Vulkan-Renderer.

Mit Stand vom Mai 2023 befindet sich dieser Treiber noch in der Entwicklung. Viele Features sind noch nicht implementiert, insbesondere in 3D.

Zusammenfassung der Rendering-Treiber/Methoden

Die folgenden Kombinationen aus Rendering-API und Rendering-Methode sind derzeit möglich:

  • Vulkan + Forward+

  • Vulkan + Forward Mobile

  • Direct3D 12 + Forward+

  • Direct3D 12 + Forward Mobile

  • Metal + Forward+ (via MoltenVK)

  • Metal + Forward Mobile (via MoltenVK)

  • OpenGL + Kompatibilität

Jede Kombination hat ihre eigenen Einschränkungen und Performancemerkmale. Stellen Sie sicher, dass Sie Ihre Änderungen nach Möglichkeit mit allen Rendering-Methoden testen, bevor Sie einen Pull Request erstellen.

RenderingDevice-Abstraktion

Bemerkung

Der OpenGL-Treiber verwendet nicht die RenderingDevice-Abstraktion.

Um die Komplexität moderner Low-Level-Grafik-APIs besser handhabbar zu machen, verwendet Godot eine eigene Abstraktion namens RenderingDevice.

Das bedeutet, dass Sie beim Schreiben von Code für moderne Rendering-Methoden nicht direkt die Vulkan- oder Direct3D 12-APIs verwenden. Dies ist zwar immer noch eine niedrigere Ebene als eine API wie OpenGL, aber es macht die Arbeit am Renderer einfacher, da RenderingDevice viele API-spezifische Eigenheiten für Sie abstrahiert. Das RenderingDevice bietet eine ähnliche Abstraktionsebene wie Metal oder WebGPU.

Vulkan RenderingDevice-Implementierung:

Direct3D 12 RenderingDevice implementation:

Architektur der wichtigsten Rendering-Klassen

Dieses Diagramm zeigt die Struktur der Rendering-Klassen in Godot, einschließlich der RenderingDevice-Abstraktion:

../../../_images/rendering_architecture_diagram.webp

View at full size

Core-Shader

Während Shader in Godot-Projekten mit einer eigenen, von GLSL inspirierten Sprache geschrieben werden, werden Core-Shader direkt in GLSL geschrieben.

Diese Core-Shader werden zur Kompilierungszeit in die Editor- und Exportvorlagen-Binärdateien eingebettet. Um Änderungen an diesen GLSL-Shadern zu sehen, müssen Sie den Editor oder die Exportvorlagen-Binärdatei neu kompilieren.

Einige Material-Eigenschaften wie Height Mapping, Refraction und Proximity Fade sind nicht Teil der Core-Shader und werden im Standard-BaseMaterial3D stattdessen mit der Godot-Shader-Sprache (nicht GLSL) ausgeführt. Dies geschieht durch prozedurale Generierung des erforderlichen Shader-Codes in Abhängigkeit von den im Material aktivierten Features.

Konventionell werden Shader-Dateien mit _inc in ihrem Namen in andere GLSL-Dateien eingebunden, um die Wiederverwendung von Code zu verbessern. Um dies zu erreichen, wird die standardmäßige GLSL-Vorverarbeitung verwendet.

Warnung

Core-Material-Shader werden von jedem Material in der Szene verwendet - sowohl mit dem standardmäßigen BaseMaterial3D als auch mit benutzerdefinierten Shadern. Daher müssen diese Shader so einfach wie möglich gehalten werden, um Performanceprobleme zu vermeiden und sicherzustellen, dass die Shader-Kompilierung nicht zu langsam wird.

Wenn Sie if-Verzweigungen in einem Shader verwenden, kann die Performance sinken, da die VGPR-Nutzung im Shader steigt. Dies geschieht selbst dann, wenn alle Pixel in einem bestimmten Frame als true oder false ausgewertet werden.

Wenn Sie die #if-Präprozessorverzweigung verwenden, wird die Anzahl der benötigten Shader-Versionen in der Szene steigen. Im schlimmsten Fall kann das Hinzufügen eines einzigen booleschen #define die Anzahl der Shader-Versionen, die in einer bestimmten Szene kompiliert werden müssen, verdoppeln. In einigen Fällen können Vulkan-Spezialisierungskonstanten als schnellere (aber begrenztere) Alternative verwendet werden.

Das bedeutet, dass es eine hohe Hürde für das Hinzufügen neuer Built-in-Material-Eigenschaften in Godot gibt, sowohl in den Core-Shadern als auch in BaseMaterial3D. BaseMaterial3D kann zwar die dynamische Codegenerierung nutzen, um den Shader-Code nur dann einzubeziehen, wenn das Feature aktiviert ist, aber es müssen immer noch mehr Shader-Versionen generiert werden, wenn diese Features in einem Projekt verwendet werden. Dies kann dazu führen, dass die Shader-Kompilierung in komplexen 3D-Szenen stärker stottert.

Weitere Informationen finden Sie in den Blogbeiträgen The Shader Permutation Problem und Branching on a GPU.

Core-GLSL-Material-Shader:

Material-Shader-Generierung:

Andere GLSL-Shader für Forward+ und Forward Mobile Rendering-Methoden:

Andere GLSL-Shader für die Kompatibilitäts-Renderingmethode:

Trennung von 2D- und 3D-Rendering

Bemerkung

Das Folgende gilt nur für die Rendering-Methoden Forward+ und Forward Mobile, nicht aber für Kompatibilität. Mehrere Viewports können verwendet werden, um dies zu emulieren, wenn das Kompatibilität-Backend verwendet wird, oder um eine 2D-Auflösungsskalierung durchzuführen.

2D und 3D werden in getrennten Puffern gerendert, da das 2D-Rendering in Godot im LDR sRGB-Raum durchgeführt wird, während das 3D-Rendering den HDR linearen Raum verwendet.

Das für das 2D-Rendering verwendete Farbformat ist RGB8 (RGBA8, wenn die Property Transparent im Viewport aktiviert ist). Das 3D-Rendering verwendet einen 24-Bit-Tiefenpuffer mit normalisierten unsigned Integer oder 32-Bit-signed Float, wenn ein 24-Bit-Tiefenpuffer von der Hardware nicht unterstützt wird. Beim 2D-Rendering wird kein Tiefenpuffer verwendet.

Die Skalierung der 3D-Auflösung wird unterschiedlich durchgeführt, je nachdem, ob eine bilineare oder eine FSR 1.0-Skalierung verwendet wird. Bei bilinearer Skalierung wird kein spezieller Upscaling-Shader ausgeführt. Stattdessen wird die Textur des Viewports gestreckt und mit einem linearen Sampler angezeigt (wodurch die Filterung direkt in der Hardware erfolgt). Dies ermöglicht die Maximierung der Performance der bilinearen 3D-Skalierung.

Die Funktion configure() in RenderSceneBuffersRD ordnet die 2D/3D-Puffer neu zu, wenn sich die Auflösung oder Skalierung ändert.

Die dynamische Auflösungsskalierung wird noch nicht unterstützt, ist aber für ein künftiges Godot-Release geplant.

C++-Code für 2D- und 3D-Rendering-Bufferkonfiguration:

FSR 1.0:

2D-Rendering-Techniken

Das 2D-Lichtrendering wird in einem einzigen Durchgang durchgeführt, um eine bessere Performance bei großen Mengen von Lichtern zu ermöglichen.

Die Rendering-Methoden Forward+ und Mobile bieten noch keine 2D-Batching-Funktion, diese ist jedoch für ein zukünftiges Release geplant.

Das Kompatibilität-Backend bietet 2D-Batching, um die Performance zu verbessern, was sich besonders bei viel Text auf dem Bildschirm bemerkbar macht.

MSAA kann in 2D aktiviert werden, um ein "automatisches" Antialiasing für Linien und Polygone zu ermöglichen, aber FXAA hat keinen Einfluss auf das 2D-Rendering, da es berechnet wird, bevor das 2D-Rendering beginnt. Godots 2D-Zeichenmethoden wie der Line2D-Node oder einige CanvasItem draw_*()-Methoden bieten ihre eigene Art des Antialiasing basierend auf Triangle Strips und Vertex-Farben, die kein MSAA benötigen, um zu funktionieren.

Ein 2D-Signed Distance Field, das LightOccluder2D-Nodes im Viewport repräsentiert, wird automatisch erzeugt, wenn ein Benutzer-Shader es anfordert. Dies kann für verschiedene Effekte in benutzerdefinierten Shadern verwendet werden, z.B. für die 2D Global Illumination. Es wird auch zur Berechnung von Partikelkollisionen in 2D verwendet.

2D-SDF-GLSL-Shader:

3D-Rendering-Techniken

Batching und Instanziierung

Im Forward+-Backend wird Vulkan-Instanziierung verwendet, um das Rendering identischer Objekte aus Performancegründen zu gruppieren. Dies ist nicht so schnell wie das statische Mergen von Meshes, ermöglicht aber dennoch das individuelle Culling von Instanzen.

Licht-, Decal- und Reflexionsprobe-Rendering

Bemerkung

Reflexions-Probe und Decal-Rendering sind derzeit im Kompatibilitäts-Backend nicht verfügbar.

Wie der Name schon sagt, verwendet das Forward+-Backend eine Cluster-Beleuchtung. Dadurch können Sie so viele Lichter verwenden, wie Sie wollen; die Performance hängt weitgehend von der Bildschirmabdeckung ab. Schattenlose Lichter können fast kostenlos sein, wenn sie nicht viel Platz auf dem Bildschirm beanspruchen.

Alle Rendering-Methoden unterstützen auch das gleichzeitige Rendering von bis zu 8 gerichteten Lichtern (wenn auch mit geringerer Schattenqualität, wenn mehr als ein Licht Schatten aktiviert hat).

Das Forward Mobile-Backend verwendet einen Single-Pass-Beleuchtungsansatz mit einer Begrenzung von 8 OmniLights + 8 SpotLights pro Mesh-Ressource (plus einer Begrenzung von 256 OmniLights + 256 SpotLights in der Kameraansicht). Diese Grenzen sind fest kodiert und können in den Projekteinstellungen nicht angepasst werden.

Das Kompatibilität-Backend verwendet einen hybriden Single-Pass- und Multi-Pass-Beleuchtungsansatz. Lichter ohne Schatten werden in einem einzigen Durchgang gerendert. Lichter mit Schatten werden in mehreren Durchgängen gerendert. Dies ist aus Performancegründen auf mobilen Geräten erforderlich. Daher ist die Performance bei vielen schattenwerfenden Lichtern nicht gut skalierbar. Es wird empfohlen, jeweils nur eine Handvoll Lichter mit Schatten im Kamera-Frustum zu haben und diese Lichter so zu verteilen, dass jedes Objekt nur von 1 oder 2 schattenwerfenden Lichtern auf einmal berührt wird. Die maximale Anzahl der gleichzeitig sichtbaren Lichter kann in den Projekteinstellungen angepasst werden.

Bei allen 3 Methoden sind Lichter ohne Schatten viel billiger als Lichter mit Schatten. Um die Performance zu verbessern, werden Lichter nur aktualisiert, wenn das Licht geändert wird oder wenn Objekte in seinem Radius geändert werden. Godot trennt derzeit nicht zwischen statischem und dynamischem Schattenrendering, aber dies ist für ein zukünftiges Release geplant.

Clustering wird auch für Reflexions-Probes und das Rendering von Decals im Forward+ Backend verwendet.

Shadow-Mapping

Sowohl Forward+ als auch Forward Mobile verwenden PCF, um Shadow Maps zu filtern und einen weichen Halbschatten zu erzeugen. Anstelle eines festen PCF-Musters verwenden diese Methoden ein Vogel-Disk-Muster, das es ermöglicht, die Anzahl der Samples zu ändern und die Qualität stufenlos zu verändern.

Godot unterstützt auch Percentage-Closer Soft Shadows (PCSS) für eine realistischere Darstellung der Schatten-Penumbra. PCSS-Schatten sind auf das Forward+-Backend beschränkt, da sie zu anspruchsvoll sind, um im Forward Mobile-Backend verwendet werden zu können. PCSS verwendet auch einen Vogel-Disk-förmigen Kernel.

Darüber hinaus rotieren beide Shadow-Mapping-Techniken den Kernel auf einer pro-Pixel-Basis, um Unterabtastungsartefakte zu mildern.

Das Kompatibilität-Backend unterstützt noch kein Shadow-Mapping für irgendwelche Lichttypen.

Temporales Antialiasing

Bemerkung

Nur im Forward+-Backend verfügbar, nicht in den Methoden Forward Mobile oder Compatibility.

Godot verwendet eine benutzerdefinierte TAA-Implementierung, die auf der alten TAA-Implementierung der Spartan Engine basiert.

Temporales Antialiasing erfordert Bewegungsvektoren, um zu funktionieren. Wenn die Bewegungsvektoren nicht korrekt erzeugt werden, kommt es zu Geisterbildern, wenn sich die Kamera oder Objekte bewegen.

Die Bewegungsvektoren werden auf der GPU im Hauptmaterial-Shader erzeugt. Dazu wird der Vertex-Shader des vorherigen gerenderten Frames (mit der vorherigen Kameratransformation) zusätzlich zum Vertex-Shader des aktuellen gerenderten Frames ausgeführt und die Differenz zwischen beiden in einem Farbpuffer gespeichert.

Alternatively, FSR 2.2 can be used as an upscaling solution that also provides its own temporal antialiasing algorithm. FSR 2.2 is implemented on top of the RenderingDevice abstraction as opposed to using AMD's reference code directly.

TAA-Resolve:

FSR 2.2:

Global Illumination

Bemerkung

VoxelGI und SDFGI sind nur im Forward+-Backend verfügbar, nicht in den Methoden Forward Mobile oder Kompatibilität.

LightmapGI backen ist nur in den Methoden Forward+ und Forward Mobile verfügbar und kann nur innerhalb des Editors durchgeführt werden (nicht in einem exportierten Projekt). LightmapGI-Rendering wird irgendwann vom Kompatibilität-Backend unterstützt werden.

Godot unterstützt voxelbasiertes GI (VoxelGI), Signed Distance Field-GI (SDFGI), sowie Lightmap-Backen und -Rendering (LightmapGI). Diese Techniken können bei Bedarf gleichzeitig verwendet werden.

Das Backen von Lightmaps erfolgt auf der GPU unter Verwendung von Vulkan-Compute-Shadern. Der GPU-basierte Lightmapper ist in der LightmapperRD-Klasse implementiert, die von der Lightmapper-Klasse erbt. Dies ermöglicht die Implementierung zusätzlicher Lightmapper und ebnet den Weg für eine künftige Portierung des CPU-basierten Lightmappers in Godot 3.x. Dies würde das Backen von Lightmaps unter Verwendung des Kompatibilität-Backends ermöglichen.

C++-Code für Core GI:

Core GI GLSL Shader:

C++-Code für Lightmapper:

Lightmapper GLSL Shader:

Schärfentiefe

Bemerkung

Nur verfügbar in den Methoden Forward+ und Forward Mobile, nicht im Kompatibilität-Backend.

Die Methoden Forward+ und Forward Mobile verwenden unterschiedliche Ansätze für das Schärfentiefe (DOF)-Rendering mit unterschiedlichen visuellen Ergebnissen. Dies geschieht, um die Performancemerkmale der Zielhardware bestmöglich zu erfüllen. Bei Clustered Forward wird DOF mit einem Compute-Shader ausgeführt. In Forward Mobile wird DOF mit einem Fragment-Shader (Raster) ausgeführt.

Es stehen Box-, Hexagon und Kreis-Bokeh-Formen zur Verfügung (vom schnellsten zum langsamsten). Die Schärfentiefe kann optional bei jedem Bild gejittert werden, um das Erscheinungsbild zu verbessern, wenn das temporale Antialiasing aktiviert ist.

C++-Code zu Schärfentiefe:

GLSL-Shader mit Schärfentiefe (Compute - verwendet für Forward+):

GLSL-Shader mit Schärfentiefe (Raster - verwendet für Forward Mobile):

Screen Space-Effekte (SSAO, SSIL, SSR, SSS)

Bemerkung

Nur im Forward+-Backend verfügbar, nicht in den Methoden Forward Mobile oder Compatibility.

Das Forward+-Backend unterstützt Screen Space Ambient Occlusion, Screen Space Indirect Lighting, Screen Space Reflections und Subsurface Scattering.

SSAO verwendet eine Implementierung, die von Intels ASSAO (konvertiert zu Vulkan) abgeleitet ist. SSIL ist von SSAO abgeleitet, um eine leistungsstarke indirekte Beleuchtung zu ermöglichen.

Wenn sowohl SSAO als auch SSIL aktiviert sind, werden Teile von SSAO und SSIL gemeinsam genutzt, um die Auswirkungen auf die Performance zu verringern.

SSAO und SSIL werden standardmäßig mit halber Auflösung ausgeführt, um die Performance zu verbessern. SSR wird immer mit halber Auflösung ausgeführt, um die Performance zu verbessern.

C++-Code für Screen Space-Effekte:

GSL-Shader für Screen Space Ambient Occlusion:

GSL-Shader für Screen Space Indirect Lighting:

GLSL-Shader für Screen Space Reflections:

GLSL mit Subsurface Scattering:

Himmelsrendering

Siehe auch

Sky-Shader

Godot unterstützt die Verwendung von Shadern zum Rendern des Himmelshintergrunds. Die Radiance Map (die verwendet wird, um Umgebungslicht und Reflexionen für PBR-Materialien bereitzustellen) wird automatisch auf der Grundlage des Himmelsshaders aktualisiert.

Die SkyMaterial-Ressourcen wie ProceduralSkyMaterial, PhysicalSkyMaterial und PanoramaSkyMaterial erzeugen einen Built-in-Shader für das Himmelsrendering. Dies ist vergleichbar mit dem, was BaseMaterial3D für 3D-Szenenmaterialien bietet.

Eine detaillierte technische Implementierung findet sich im Artikel Custom sky shaders in Godot 4.0.

C++-Code für Himmelsrendering:

GLSL-Shader für Himmelsrendering:

Volumetrischer Nebel

Bemerkung

Nur im Forward+-Backend verfügbar, nicht in den Methoden Forward Mobile oder Compatibility.

Siehe auch

Fog-Shader

Godot unterstützt einen Frustum-aligned Voxel (Froxel)-Ansatz für das Rendern von volumetrischem Nebel. Im Gegensatz zu einem Post-Processing-Filter ist dieser Ansatz vielseitiger, da er mit jedem Lichttyp arbeiten kann. Nebel kann auch Shader für benutzerdefiniertes Verhalten verwenden, was die Animation des Nebels oder die Verwendung einer 3D-Textur zur Darstellung von Dichte ermöglicht.

Die FogMaterial-Ressource erzeugt einen Built-in-Shader für FogVolume-Nodes. Dies ist vergleichbar mit dem, was BaseMaterial3D für 3D-Szenenmaterialien bietet.

Eine ausführliche technische Erklärung finden Sie im Artikel Fog Volumes arrive in Godot 4.0.

C++-Code für volumetrischen Nebel:

GLSL Shader mit volumetrischem Nebel:

Occlusion Culling

Moderne Grafikprozessoren können zwar viele Dreiecke zeichnen, aber die Anzahl der Draw-Aufrufe in komplexen Szenen kann immer noch ein Bottleneck sein (selbst mit Vulkan und Direct3D 12).

Godot 4 unterstützt Occlusion Culling, um das Überzeichnen zu reduzieren (wenn der Tiefenvordurchlauf deaktiviert ist) und den Vertex-Durchsatz zu verringern. Dies geschieht durch Rasterung eines Puffers mit niedriger Auflösung auf der CPU mit Embree. Die Auflösung des Puffers hängt von der Anzahl der CPU-Threads auf dem System ab, da dies parallel durchgeführt wird. Dieser Puffer enthält Occluder-Shapes, die im Editor gebacken oder zur Laufzeit erstellt wurden.

Da komplexe Occluder die CPU stark belasten können, können gebackene Occluder bei der Erstellung im Editor automatisch vereinfacht werden.

Das Occlusion Culling von Godot unterstützt noch keine dynamischen Occluder, aber OccluderInstance3D-Nodes können ihre Sichtbarkeit umschalten oder verschoben bekommen. Allerdings wird dies bei der Aktualisierung komplexer Occluder auf diese Weise langsam. Daher ist es am besten, die Occluder zur Laufzeit nur bei einfachen Occluder-Shapes wie Quads oder Quadern zu aktualisieren.

Dieser CPU-basierte Ansatz hat einige Vorteile gegenüber anderen Lösungen, wie z.B. Portalen und Räumen oder einer GPU-basierten Culling-Lösung:

  • Keine manuelle Einrichtung erforderlich (kann aber für optimale Performance manuell angepasst werden).

  • Keine Bildverzögerung, die in Zwischensequenzen bei Kameraschwenks problematisch ist, oder wenn sich die Kamera schnell hinter einer Wand bewegt.

  • Funktioniert bei allen Rendering-Treibern und -Methoden gleich, ohne unvorhersehbares Verhalten je nach Treiber oder GPU-Hardware.

Occlusion Culling wird durch die Registrierung von Occluder Meshes durchgeführt, was mit OccluderInstance3D-Nodes geschieht (die ihrerseits Occluder3D-Ressourcen verwenden). RenderingServer führt dann Occlusion Culling durch den Aufruf von Embree in RendererSceneOcclusionCull durch.

C++-Code für Occlusion-Culling:

Sichtbarkeits-Reichweite (LOD)

Godot unterstützt manuell erstellte hierarchisches Level of Detail (HLOD), wobei die Abstände vom Benutzer im Inspektor festgelegt werden.

In RenderingSceneCull sind es die Funktionen _scene_cull() und _render_scene(), in denen der Großteil der LOD-Bestimmung stattfindet. Jeder Viewport kann das gleiche Mesh mit unterschiedlichen LODs rendern (um ein korrektes Split-Screen-Rendering zu ermöglichen).

C++-Code zu Sichtbarkeits-Reichweite

Automatisches Mesh-LOD

Die ImporterMesh-Klasse wird für den 3D-Mesh-Import-Workflow im Editor verwendet. Ihre Funktion generate_lods() behandelt die Generierung mit der Bibliothek meshoptimizer.

Bei der LOD-Mesh-Generierung werden gleichzeitig auch Schatten-Meshes erzeugt. Dabei handelt es sich um Meshes, deren Vertices unabhängig von Glättung und Materialien verschweißt sind. Dies wird verwendet, um die Performance beim Rendern von Schatten zu verbessern, indem der für das Rendern von Schatten erforderliche Vertex-Durchsatz verringert wird.

Die Funktion _render_scene() der Klasse RenderingSceneCull bestimmt, welches Mesh-LOD beim Rendern verwendet werden soll. Jeder Viewport kann das gleiche Mesh mit unterschiedlichen LODs rendern (um ein korrektes Split-Screen-Rendering zu ermöglichen).

Das LOD des Meshes wird automatisch auf der Grundlage einer Bildschirmabdeckungsmetrik ausgewählt. Dabei werden Änderungen der Auflösung und des Kamerabildes berücksichtigt, ohne dass der Benutzer eingreifen muss. Der Schwellenwertmultiplikator kann in den Projekteinstellungen angepasst werden.

Um die Performance zu verbessern, wählen das Schatten-Rendering und das Reflection-Probe-Rendering auch ihre eigenen Mesh-LOD-Schwellenwerte (die sich vom Rendering der Hauptszene unterscheiden können).

C++-Code zu Mesh LOD-Erzeugung bei Import:

C++-Code zur Bestimmung von Mesh LOD: