Auf dieser Seite

Qt Quick 3D Architektur

Qt Quick 3D erweitert „ Qt Quick “, um das Rendern von 3D-Inhalten zu unterstützen. Es fügt umfangreiche Funktionen hinzu, darunter mehrere neue öffentliche QML-Importe sowie einen neuen internen Szenengraphen und Renderer. Dieses Dokument beschreibt die Architektur von „ Qt Quick 3D “ – von der öffentlichen API bis hin zu den Details der Funktionsweise der Rendering-Pipeline.

Modulübersicht

Qt Quick 3D besteht aus mehreren Modulen und Plugins, die die zusätzlichen 3D-APIs sowie Dienstprogramme zur Aufbereitung und zum Importieren bestehender 3D-Assets bereitstellen.

QML-Importe

  • QtQuick3D - Der Hauptimport, der alle Kernkomponenten von Qt Quick 3D
  • QtQuick3D.AssetUtils - Eine Bibliothek zum Importieren von 3D-Assets zur Laufzeit
  • QtQuick3D.Helpers - Eine Bibliothek mit zusätzlichen Komponenten, die zur Gestaltung von 3D-Szenen und zum Debuggen von 3D-Szenen verwendet werden können.

C++-Bibliotheken

  • QtQuick3D - Das einzige öffentliche C++-Modul. Enthält die Definitionen aller Typen, die dem QML-Import „ QtQuick3D “ zur Verfügung stehen, sowie einige C++-APIs
  • QtQuick3DAssetImport - Eine interne und private Bibliothek zur Unterstützung beim Importieren von Assets und beim Konvertieren von Assets in QML.
  • QtQuick3DRuntimeRender - Eine interne und private Bibliothek, die die Knoten des räumlichen Szenengraphen und den Renderer enthält.
  • QtQuick3DUtils - Eine interne und private Bibliothek, die von allen anderen C++-Modulen als gemeinsame Hilfsbibliothek genutzt wird.

AssetImporters-Plugins

Die Tools zum Importieren von Assets sind auf einer Plugin-basierten Architektur implementiert. Die mit „ Qt Quick 3D “ mitgelieferten Plugins erweitern die Funktionalität der Asset-Importer-Bibliothek und des Tools „Balsam“.

  • Assimp – Dieses Plugin nutzt die Drittanbieter-Bibliothek „libAssimp“, um 3D-Assets in 3D-Austauschformaten in QML-Komponenten von „ Qt Quick 3D “ zu konvertieren.

Wie fügt sich „ Qt Quick 3D “ in den Qt-Grafik-Stack ein?

Architekturdiagramm des <span translate=Qt Quick 3D-Grafik-Stacks" src="images/quick3d-graphics-stack.drawio.svg" title="Architekturdiagramm des Qt Quick 3D-Grafik-Stacks"/>

Das obige Diagramm veranschaulicht, wie sich „ Qt Quick 3D “ in den übergeordneten Qt-Grafik-Stack einfügt. „ Qt Quick 3D “ fungiert als Erweiterung der 2D- Qt Quick -API, und bei der Verwendung von 3D-Szenenelementen in Verbindung mit „ View3D “ wird die Szene über das Qt Rendering Hardware Interface (RHI) gerendert. Das RHI übersetzt API-Aufrufe in die für die jeweilige Plattform korrekten nativen Rendering-Hardware-API-Aufrufe. Das obige Diagramm zeigt die für jede Plattform verfügbaren Optionen. Wenn kein natives Backend explizit definiert ist, wählt Qt Quick standardmäßig ein sinnvolles natives Backend für das Rendering auf der jeweiligen Plattform aus.

Die Integration zwischen den „ Qt Quick 3D “-Komponenten des Stacks und dem „ Qt Quick “-Stack wird im Folgenden in den nächsten Abschnitten beschrieben.

3D-in-2D-Integration

Die Darstellung von 3D-Inhalten in 2D ist der Hauptzweck der „ Qt Quick 3D “-API. Die primäre Schnittstelle für die Integration von 3D-Inhalten in 2D ist die „ View3D “-Komponente.

Die „ View3D “-Komponente verhält sich wie jede andere von „ QQuickItem “ abgeleitete Klasse mit Inhalten und implementiert die virtuelle Funktion „ QQuickItem::updatePaintNode “. „ Qt Quick “ ruft während der Synchronisationsphase „updatePaintNode“ für alle „dirty“-Elemente im „ Qt Quick “-Szenengraphen auf. Dazu gehören auch die von einem „ View3D “ verwalteten 3D-Elemente, die infolge des Aufrufs von „updatePaintNode“ ebenfalls ihre Synchronisationsphase durchlaufen.

Die Methode `updatePaintNode` von ` View3D ` führt die folgenden Aktionen aus:

  • Ein Renderer und ein Renderziel werden eingerichtet, sofern noch keine vorhanden sind
  • Synchronisiert Elemente in der 3D-Szene über den SceneManager
  • Aktualisieren aller „dynamischen“ Texturen, die von Qt Quick gerendert wurden (2D im 3D-Texturpfad unten)

Das Rendern der 3D-Szene erfolgt jedoch nicht in der Methode `updatePaintNode` von ` View3D `. Stattdessen gibt `updatePaintNode` eine Unterklasse von ` QSGNode ` zurück, die den Renderer für ` Qt Quick 3D` enthält, der die 3D-Szene während der Vorverarbeitungsphase des ` Qt Quick `-Renderprozesses rendert.

Die technische Umsetzung der Darstellung von „ Qt Quick 3D “ hängt davon ab, welche „ View3D::renderMode “-Klasse verwendet wird:

Offscreen

Der Standardmodus für „ View3D “ ist „ Offscreen “. Im Offscreen-Modus fungiert „ View3D “ als Textur-Provider, indem es eine Offscreen-Oberfläche erstellt und darauf rendert. Diese Oberfläche kann in „ Qt Quick “ als Textur abgebildet und mit einem „ QSGSimpleTextureNode “ gerendert werden.

Dieses Muster ähnelt stark der Funktionsweise von QSGLayerNodes in Qt Quick.

Underlay

Bei Verwendung des Modus „ Underlay “ wird die 3D-Szene direkt auf die „ QQuickWindow “ gerendert, die den „ View3D “ enthält. Das Rendern erfolgt als Reaktion auf das Signal „ QQuickWindow::beforeRenderPassRecording()“, was bedeutet, dass alles andere in „ Qt Quick “ über den 3D-Inhalten gerendert wird.

Overlay

Im Modus „ Overlay “ wird die 3D-Szene direkt in den QQuickWindow gerendert, der das View3D enthält. Das Rendern erfolgt als Reaktion auf das Signal QQuickWindow::afterRenderPassRecording(), was bedeutet, dass der 3D-Inhalt über allen anderen Inhalten von Qt Quick gerendert wird.

Inline

Der Rendermodus „ Inline “ verwendet „ QSGRenderNode “, was das direkte Rendern auf das Renderziel von „ Qt Quick “ ohne Verwendung einer Offscreen-Oberfläche ermöglicht. Dies geschieht durch das Inline-Einfügen der Renderbefehle während des 2D-Renderings der „ Qt Quick “-Szene.

Dieser Modus kann problematisch sein, da er denselben Tiefenpuffer wie der „ Qt Quick “-Renderer verwendet und Z-Werte in „ Qt Quick “ und „ Qt Quick 3D “ völlig unterschiedliche Bedeutungen haben.

Integration von 2D in 3D

Beim Rendern einer 3D-Szene gibt es viele Szenarien, in denen 2D-Elemente in 3D eingebettet werden müssen. Es gibt zwei verschiedene Möglichkeiten, 2D-Inhalte in 3D-Szenen zu integrieren, wobei jede ihren eigenen Weg auf den Bildschirm hat.

Direkter Pfad

Der direkte Weg wird verwendet, um 2D-Inhalte vom Typ „ Qt Quick “ so zu rendern, als ob sie als flaches Element in der 3D-Szene vorhanden wären. Betrachten Sie beispielsweise die folgende Szenendefinition:

Node {
    Text {
        text: "Hello world!"
    }
}

Hier geschieht Folgendes: Wenn eine untergeordnete Komponente auf einem räumlichen Knoten vom Typ „ QQuickItem “ festgelegt wird, wird sie zunächst von einem „QQuick3DItem2D“ umschlossen – dabei handelt es sich lediglich um einen Container, der einem 2D-Element 3D-Koordinaten hinzufügt. Dadurch wird die grundlegende 3D-Transformation festgelegt, nach der alle weiteren 2D-Unterelemente gerendert werden, damit sie in der 3D-Szene korrekt dargestellt werden.

Wenn die Szene gerendert wird, werden die QSGNodes dieser 2D-Elemente an den „ Qt Quick “-Renderer übergeben, um die entsprechenden Renderbefehle zu generieren. Da die Befehle inline ausgeführt werden und die aktuelle 3D-Transformation berücksichtigen, werden sie genau wie im 2D-Renderer gerendert, erscheinen jedoch so, als wären sie in 3D gerendert worden.

Der Nachteil dieses Ansatzes besteht darin, dass keine Beleuchtungsinformationen der 3D-Szene zur Schattierung der 2D-Inhalte verwendet werden können, da der 2D-Renderer von „ Qt Quick “ kein Beleuchtungskonzept kennt.

Texturpfad

Der Texturpfad nutzt eine 2D- Qt Quick -Szene, um dynamische Texturinhalte zu erzeugen. Betrachten Sie die folgende Texturdefinition:

Texture {
    sourceItem: Item {
        width: 256
        height: 256
        Text {
            anchors.centerIn: parent
            text: "Hello World!"
        }
    }
}

Dieser Ansatz funktioniert genauso wie Layer-Elemente in „ Qt Quick “: Alles wird auf eine Offscreen-Fläche in der Größe des obersten Elements gerendert, und diese Offscreen-Fläche kann dann als Textur verwendet und an anderer Stelle wiederverwendet werden.

Diese Textur kann dann von Materialien in der Szene verwendet werden, um „ Qt Quick “-Inhalte auf Elementen zu rendern.

Szenensynchronisation

Szenenmanager

Der Szenenmanager in „ Qt Quick 3D “ ist dafür zuständig, räumliche Elemente in einer 3D-Szene zu verfolgen und sicherzustellen, dass die Elemente während der Synchronisationsphase ihre entsprechenden Szenengraph-Knoten aktualisieren. In „ Qt Quick “ wird diese Rolle im 2D-Fall von „ QQuickWindow “ übernommen. Der Szenenmanager ist die primäre Schnittstelle zwischen den Frontend-Knoten und den Backend-Szenengraph-Objekten.

Jedes „ View3D “-Element verfügt über mindestens einen Szenenmanager, da bei der Erstellung ein solcher angelegt und mit der integrierten Szenenwurzel verknüpft wird. Wenn räumliche Knoten als untergeordnete Elemente des „ View3D “ hinzugefügt werden, werden sie beim Szenenmanager des „ View3D “ registriert. Bei der Verwendung einer importierten Szene wird ein zweiter SceneManager erstellt (oder, falls bereits vorhanden, referenziert), um die Knoten zu verwalten, die keine direkten untergeordneten Elemente der „ View3D “ sind. Dies ist erforderlich, da eine importierte Szene – im Gegensatz zur „ View3D “ – erst dann auf einer „ QQuickWindow “ existiert, wenn sie referenziert wird. Der zusätzliche „SceneManager“ stellt sicher, dass Assets, die zur importierten Szene gehören, mindestens einmal pro „ QQuickWindow “ erstellt werden, in dem auf sie verwiesen wird.

Obwohl der Szenenmanager eine interne API ist, ist es wichtig zu wissen, dass er dafür verantwortlich ist, „updateSpatialNode“ für alle Objekte aufzurufen, die durch den Aufruf der Methode „update()“ als „dirty“ markiert wurden.

Frontend-/Backend-Synchronisation

Das Ziel der Synchronisation ist es, sicherzustellen, dass die im Frontend (Qt Quick) festgelegten Zustände mit denen im Backend (Qt Quick Spatial Scene Graph Renderer) übereinstimmen. Standardmäßig laufen Frontend und Backend in getrennten Threads: das Frontend im Qt-Hauptthread und das Backend im Render-Thread von Qt Quick. In der Synchronisationsphase können der Haupt- und der Render-Thread sicher Daten austauschen. Während dieser Phase ruft der Szenenmanager für jeden geänderten Knoten in der Szene die Funktion `updateSpatialNode` auf. Dadurch wird entweder ein neuer Backend-Knoten erstellt oder ein bestehender aktualisiert, damit er vom Renderer verwendet werden kann.

Qt Quick Spatial Scene Graph

Qt Quick 3D ist so konzipiert, dass es dasselbe Trennungsmuster zwischen Frontend und Backend verwendet wie „ Qt Quick “: Frontend-Objekte werden von der „ Qt Quick “-Engine gesteuert, während Backend-Objekte Zustandsdaten für das Rendern der Szene enthalten. Frontend-Objekte erben von „ QObject “ und werden der „ Qt Quick “-Engine zur Verfügung gestellt. Elemente in QML-Quelldateien werden direkt Frontend-Objekten zugeordnet.

Wenn die Eigenschaften dieser Frontend-Objekte aktualisiert werden, werden ein oder mehrere Backend-Knoten erstellt und in einen Szenengraphen eingefügt. Da das Rendern von 3D-Szenen wesentlich mehr Zustandsdaten erfordert als das Rendern von 2D-Szenen, gibt es einen separaten Satz spezialisierter Szenengraphenknoten zur Darstellung des Zustands der 3D-Szenenobjekte. Dieser Szenengraph ist als „ Qt Quick -Szenengraph“ bekannt.

Sowohl die Frontend-Objekte als auch die Backend-Knoten lassen sich in zwei Klassen einteilen. Die erste Klasse umfasst räumliche Elemente, d. h., sie existieren an einer bestimmten Stelle im 3D-Raum. In der Praxis bedeutet dies, dass jeder dieser Typen eine Transformationsmatrix enthält. Bei räumlichen Elementen ist die Eltern-Kind-Beziehung von Bedeutung, da jedes untergeordnete Element die Transformation seines übergeordneten Elements erbt.

Die andere Klasse von Elementen sind Ressourcen. Ressourcenelemente haben keine Position im 3D-Raum, sondern stellen lediglich einen Zustand dar, der von anderen Elementen genutzt wird. Zwischen diesen Elementen kann eine Eltern-Kind-Beziehung bestehen, die jedoch keine andere Bedeutung als die der Zugehörigkeit hat.

Im Gegensatz zum 2D-Szenengraphen unter Qt Quick macht der räumliche Szenengraph die Ressourcenknoten dem Benutzer direkt zugänglich. So ist beispielsweise in Qt Quick zwar QSGTexture Teil der öffentlichen API, es gibt jedoch kein QQuickItem, das dieses Objekt direkt zugänglich macht. Stattdessen muss der Benutzer entweder ein „Image“-Element verwenden, das sowohl die Herkunft der Textur als auch deren Darstellung beschreibt, oder C++-Code schreiben, um direkt mit dem „ QSGTexture “ selbst zu arbeiten. In Qt Quick 3D werden diese Ressourcen direkt in der QML-API bereitgestellt. Dies ist notwendig, da Ressourcen ein wichtiger Bestandteil des Szenenstatus sind. Auf diese Ressourcen kann von vielen Objekten in der Szene verwiesen werden: So könnten beispielsweise viele Materialien dieselbe Textur verwenden. Es ist zudem möglich, Eigenschaften einer Textur zur Laufzeit festzulegen, wodurch sich beispielsweise die Art und Weise, wie eine Textur abgetastet wird, direkt ändern würde.

Räumliche Objekte

Alle räumlichen Objekte sind Unterklassen der Node-Komponente, die die Eigenschaften enthält, welche Position, Rotation und Skalierung im 3D-Raum definieren.

Ressourcenobjekte

Ressourcenobjekte sind Unterklassen der Komponente „ Object3D “. „ Object3D “ ist lediglich eine Unterklasse von „ QObject “ mit einigen speziellen Hilfsfunktionen für die Verwendung mit dem Szenenmanager. Ressourcenobjekte verfügen zwar über Eltern-Kind-Beziehungen, diese sind jedoch hauptsächlich für die Zuordnung von Ressourcen nützlich.

View3D und Render-Ebenen

Im Hinblick auf die Trennung von Frontend und Backend stellt „ View3D “ aus Benutzersicht den Trennpunkt dar, da ein „ View3D “ definiert, welche Szeneninhalte gerendert werden sollen. Im räumlichen Szenengraphen von „ Qt Quick “ ist der Stammknoten einer zu rendernenden Szene ein Layer-Knoten. Layer-Knoten werden vom „ View3D “ mithilfe einer Kombination aus den Eigenschaften des „ View3D “ und den Eigenschaften des „ SceneEnvironment “ erstellt. Beim Rendern einer Szene für einen „ View3D “ wird dieser Layer-Knoten an den Renderer übergeben, um die Szene zu rendern.

Szenen-Rendering

Flussdiagramm zum 3D-Rendering in Qt Quick 3D

Renderziel einrichten

Der erste Schritt im Rendering-Prozess besteht darin, das Szenen-Renderziel zu bestimmen und einzurichten. Je nachdem, welche Eigenschaften im „ SceneEnvironment “ festgelegt sind, variiert das tatsächliche Renderziel. Zunächst muss entschieden werden, ob der Inhalt direkt auf eine Fensteroberfläche oder auf eine Offscreen-Textur gerendert wird. Standardmäßig rendert „ View3D “ auf eine Offscreen-Textur. Bei der Verwendung von Post-Processing-Effekten ist das Rendern auf eine Offscreen-Textur zwingend erforderlich.

Sobald ein Szenen-Renderziel festgelegt ist, werden einige globale Zustände gesetzt.

  • Fenstergröße – bei Rendering in ein Fenster
  • Viewport – die Größe des gerenderten Szenenbereichs
  • Scherrechteck – der Teilbereich eines Fensters, auf den der Ansichtsbereich beschränkt werden soll
  • Löschfarbe – mit welcher Farbe das Renderziel gegebenenfalls gelöscht werden soll.

Vorbereitung für das Rendern

Die nächste Phase des Renderings ist die Vorbereitungsphase, in der der Renderer Verwaltungsaufgaben durchführt, um zu ermitteln, was für ein bestimmtes Bild gerendert werden muss, und um sicherzustellen, dass alle erforderlichen Ressourcen verfügbar und auf dem neuesten Stand sind.

Die Vorbereitungsphase selbst besteht aus zwei Schritten: der übergeordneten Vorbereitung, bei der ermittelt wird, was gerendert werden soll und welche Ressourcen benötigt werden; und der untergeordneten Vorbereitung, bei der mithilfe von RHI die Render-Pipelines und -Puffer tatsächlich eingerichtet sowie die Render-Abhängigkeiten des Hauptszenen-Durchlaufs festgelegt werden.

Render-Vorbereitung auf hoher Ebene

Der Zweck dieser Phase besteht darin, den Zustand des räumlichen Szenengraphen in eine Form zu extrahieren, die zur Erstellung von Renderbefehlen verwendet werden kann. Im Überblick erstellt der Renderer dabei Listen von Geometrie- und Materialkombinationen, die aus der Perspektive einer einzelnen Kamera mit einer Reihe von Beleuchtungszuständen gerendert werden sollen.

Zunächst wird der globale gemeinsame Zustand für alle Inhalte ermittelt. Wenn die „ SceneEnvironment “ eine „ lightProbe “ definiert, wird geprüft, ob die mit dieser Licht-Probe-Textur verknüpfte Umgebungskarte geladen ist; ist dies nicht der Fall, wird eine neue Umgebungskarte geladen oder generiert. Die Erzeugung einer Umgebungskarte erfolgt selbst durch eine Reihe von Durchläufen, bei denen die Quelltextur in eine Cube-Map konvolviert wird. Diese Cube-Map enthält sowohl Informationen zur spiegelnden Reflexion als auch zur Bestrahlungsstärke, die für die Materialschattierung verwendet werden.

Als Nächstes muss der Renderer bestimmen, welche Kamera in der Szene verwendet werden soll. Wenn keine aktive Kamera explizit durch eine ` View3D` definiert ist, wird die erste in der Szene verfügbare Kamera verwendet. Befinden sich keine Kameras in der Szene, wird kein Inhalt gerendert und der Renderer bricht den Vorgang ab.

Sobald eine Kamera festgelegt ist, kann die Projektionsmatrix für dieses Bild berechnet werden. Die Berechnung erfolgt an dieser Stelle, da jedes renderbare Objekt wissen muss, wie es projiziert werden soll. Das bedeutet auch, dass nun berechnet werden kann, welche renderbaren Objekte gerendert werden sollen. Ausgehend von der Liste aller renderbaren Objekte entfernen wir alle Objekte, die nicht sichtbar sind, weil sie entweder deaktiviert oder vollständig transparent sind. Ist dann bei der aktiven Kamera „Frustum Culling“ aktiviert, wird jedes renderbare Element daraufhin überprüft, ob es sich vollständig außerhalb des Sichtbereichs des Kamerasichtkegels befindet; ist dies der Fall, wird es aus der Liste der renderbaren Elemente entfernt.

Zusätzlich zur Kameraprojektion wird auch die Kamerarichtung berechnet, da dies für die Beleuchtungsberechnungen im Shading-Code erforderlich ist.

Befinden sich Lichtknoten in der Szene, werden diese in einer Liste zusammengefasst, deren Länge der maximalen Anzahl verfügbarer Lichter entspricht. Sind in der Szene mehr Lichtknoten vorhanden, als der Renderer unterstützt, werden alle Lichtknoten, die über diese Grenze hinausgehen, ignoriert und tragen nicht zur Beleuchtung der Szene bei. Es ist möglich, den Geltungsbereich von Lichtknoten festzulegen; beachte jedoch, dass selbst bei Festlegung eines Geltungsbereichs der Beleuchtungszustand jedes Lichts weiterhin an jedes Material gesendet wird, das über Beleuchtung verfügt; bei Lichtern, die nicht im Geltungsbereich liegen, wird die Helligkeit jedoch auf 0 gesetzt, sodass diese Lichter in der Praxis nicht zur Beleuchtung dieser Materialien beitragen.

Mit einer hoffentlich nun kürzeren Liste von Renderables muss nun jedes dieser Elemente aktualisiert werden, um den aktuellen Zustand der Szene widerzuspiegeln. Für jedes Renderable prüfen wir, ob ein passendes Material geladen ist; ist dies nicht der Fall, wird ein neues erstellt. Ein Material ist eine Kombination aus Shadern und einer Render-Pipeline und wird für die Erstellung eines Draw-Calls benötigt. Darüber hinaus stellt der Renderer sicher, dass alle zum Rendern eines renderbaren Objekts benötigten Ressourcen geladen sind, beispielsweise die am Modell festgelegte Geometrie und die Texturen. Ressourcen, die noch nicht geladen sind, werden hier geladen.

Siehe „Festplattenbasiertes Caching von Shadern“ für eine Erläuterung zum festplattenbasierten Caching von Shadern für Materialien und Effekte.

Die Liste der renderbaren Objekte wird anschließend in drei Listen sortiert.

  • Opake Objekte: Diese werden von vorne nach hinten sortiert, d. h. von den Objekten, die der Kamera am nächsten sind, zu den Objekten, die am weitesten von der Kamera entfernt sind. Dies geschieht, um die Vorteile des Hardware-Occlusion-Culling oder der Early-Z-Detection im Fragment-Shader zu nutzen.
  • 2D-Objekte: Hierbei handelt es sich um „ QtQuick “-Objekte, die vom „ Qt Quick “-Renderer gerendert werden.
  • Transparente Objekte: Diese werden von hinten nach vorne sortiert, d. h. von den Objekten, die am weitesten von der Kamera entfernt sind, zu den Objekten, die der Kamera am nächsten liegen. Dies geschieht, da transparente Objekte mit allen dahinter liegenden Objekten überblendet werden müssen.

Vorbereitung des Low-Level-Renderings

Nachdem nun alle für diesen Frame zu berücksichtigenden Aspekte festgelegt wurden, können die grundlegenden Abläufe und Abhängigkeiten für den Hauptrenderdurchlauf behandelt werden. In dieser Phase werden zunächst alle für den Hauptrenderdurchlauf erforderlichen Vorabdurchläufe gerendert.

  • Rendering des Depth-Passes – Bestimmte Funktionen wie Screen Space Ambient Occlusion und Schattenbildung erfordern einen Depth-Pre-Pass. Bei diesem Pass werden alle undurchsichtigen Objekte in eine Tiefentextur gerendert.
  • Render SSAO-Pass – Das Ziel des Screen-Space-Ambient-Occlusion-Passes ist die Erzeugung einer Ambient-Occlusion-Textur. Diese Textur wird später von Materialien verwendet, um bestimmte Bereiche beim Shading abzudunkeln.
  • Render ShadowPasses – Jede Lichtquelle in der Szene, für die Schatten aktiviert sind, trägt zu einem zusätzlichen Schatten-Pass bei. Der Renderer verwendet zwei verschiedene Schattentechniken, sodass je nach Lichttyp unterschiedliche Pässe zum Einsatz kommen. Beim Rendern von Schatten durch ein Richtlicht wird die Szene in eine 2D-Oklusionstextur gerendert, die sich aus der Richtung des Richtlichts und der Größe des Kamerapyramidenstumpfs ergibt. Beim Rendern von Schatten durch ein Punkt- oder Spotlicht ist die Oklusionstextur des Lichts eine Cube-Map, die den Oklusionsbeitrag relativ zu jeder Flächenrichtung des Lichts darstellt.
  • Render ScreenTexture – Dieser Durchgang findet nur statt, wenn ein „ CustomMaterial “ verwendet wird, der eine Bildschirmtextur erfordert; diese kann für Rendertechniken wie Refraktion genutzt werden. Dieser Durchgang funktioniert wie ein Tiefendurchgang, rendert jedoch stattdessen alle undurchsichtigen Objekte in eine Farbtextur.

Nachdem die Abhängigkeitsrenderings abgeschlossen sind, werden die restlichen Durchläufe vorbereitet, jedoch nicht gerendert. Diese Vorbereitung umfasst die Übernahme des in der übergeordneten Vorbereitungsphase gesammelten Zustands und dessen Umsetzung in Grafikprimitive, wie das Erstellen bzw. Aktualisieren von Uniform-Buffer-Werten, das Zuordnen von Samplern zu Abhängigkeitstexturen, die Einrichtung von Shader-Ressourcenbindungen sowie alle weiteren Schritte, die zur Erstellung eines für die Ausführung eines Draw-Calls erforderlichen Pipeline-Zustands erforderlich sind.

Szenen-Rendering

Nachdem die mühsame Vorbereitungsarbeit nun abgeschlossen ist, besteht der einfache Teil darin, die Befehle auszuführen, die zum Inhalt der Hauptszene beitragen. Dieses Rendering erfolgt in folgender Reihenfolge:

  • Clear-Pass – Dies ist eigentlich kein Pass, aber je nachdem, wie „backgroundMode“ in ` SceneEnvironment` eingestellt ist, können hier verschiedene Dinge geschehen. Ist der Hintergrundmodus entweder auf „transparent“ oder „color“ gesetzt, wird der Farbpuffer entweder mit Transparenz oder mit der angegebenen Farbe gelöscht. Ist der Hintergrundmodus hingegen auf „SkyBox“ gesetzt, wird ein Durchgang ausgeführt, der die SkyBox aus der Perspektive der Kamera rendert und dabei den Puffer mit den Anfangsdaten füllt.
  • Opaque-Pass – Als Nächstes werden alle opaken Elemente gezeichnet. Dies umfasst lediglich das Setzen des Pipeline-Status und das Ausführen des Zeichnungsbefehls für jedes Element in der Reihenfolge der Liste, da diese zu diesem Zeitpunkt bereits sortiert ist.
  • 2D-Durchgang – Befinden sich 2D-Objekte in der Szene, wird der „ Qt Quick “-Renderer aufgerufen, um die zum Rendern dieser Objekte erforderlichen Renderbefehle zu generieren.
  • Transparenz-Durchlauf – Schließlich werden die transparenten Objekte in der Szene nacheinander auf dieselbe Weise wie die undurchsichtigen Objekte gerendert.

Damit ist das Rendern der Szene abgeschlossen.

Nachbearbeitung

Wenn eine Nachbearbeitungsfunktion aktiviert ist, kann davon ausgegangen werden, dass das Ergebnis des Szenen-Renderers eine Textur war, die als Eingabe für die Nachbearbeitungsphase dient. Alle Nachbearbeitungsmethoden sind zusätzliche Durchläufe, die auf dieser Szenen-Eingabetextur angewendet werden.

Alle Schritte der Nachbearbeitungsphase sind optional. Sind weder integrierte Funktionen noch benutzerdefinierte Effekte aktiviert, wird die Ausgabe des Szenen-Renders als endgültiges Renderziel verwendet. Beachten Sie jedoch, dass „ tonemapping “ standardmäßig aktiviert ist.

Nachbearbeitungs-Render-Pass-Graph

Integrierte Nachbearbeitung

ExtendedSceneEnvironment und dessen übergeordneter Typ „ SceneEnvironment “ bieten die gängigsten Effekte für 3D-Szenen sowie Tonemapping, mit dem die vom Renderer erzeugten Farbwerte mit hohem Dynamikumfang auf den LDR-Bereich von 0 bis 1 abgebildet werden. Zu den Effekten gehören Tiefenschärfe, Glühen/Bloom, Linsenreflexe, Vignettierung, Farbanpassung und -korrektur, Nebel sowie Umgebungsokklusion.

Nachbearbeitungseffekte

Anwendungen können ihre eigenen benutzerdefinierten Nachbearbeitungseffekte als geordnete Liste in der Eigenschaft „ SceneEnvironment::effects “ angeben. Ist diese Liste nicht leer, werden die darin enthaltenen Effekte vor den integrierten Effekten von „ ExtendedSceneEnvironment “ angewendet. Jeder Nachbearbeitungseffekt ist Teil einer Kette, sodass die Ausgabe des vorherigen Effekts die Eingabe für den nächsten darstellt. Der erste Effekt in dieser Kette erhält seine Eingabe direkt aus der Ausgabe des Szenen-Renderers. Außerdem können Effekte auf die Tiefentextur-Ausgabe des Szenen-Renderers zugreifen.

Jeder Effekt in diesem Prozess kann aus mehreren Teildurchläufen bestehen, was bedeutet, dass Inhalte in Zwischenpuffer gerendert werden können. Der letzte Durchlauf eines Mehrfachdurchlauf-Effekts soll eine einzelne Textur ausgeben, die die Farbdaten enthält, die von den nächsten Schritten der Nachbearbeitungsphase verwendet werden.

Zeitliches und progressives Antialiasing

Die Schritte für zeitliches und progressives Antialiasing werden optional durch die Einstellung von Eigenschaften in der „ SceneEnvironment “ aktiviert. Obwohl sie streng genommen nicht Teil der Nachbearbeitungsphase sind, werden die tatsächlichen Ergebnisse des zeitlichen und progressiven Antialiasings während der Nachbearbeitungsphase realisiert.

Temporäres Antialiasing wird durchgeführt, wenn eine Szene aktiv aktualisiert wird. Wenn diese Option aktiviert ist, nimmt die aktive Kamera beim Zeichnen der Szene für jedes Einzelbild sehr kleine Anpassungen an der Kamerarichtung vor. Das aktuelle Einzelbild wird dann mit dem zuvor gerenderten Einzelbild überblendet, um das Gerenderte zu glätten.

Progressives Antialiasing wird nur durchgeführt, wenn eine Szene nicht aktualisiert wird. Ist diese Option aktiviert, wird eine Aktualisierung erzwungen und der aktuelle Zustand der Szene wird unter sehr geringfügigen Anpassungen der Richtung der aktiven Kamera gerendert. Bis zu 8 Frames werden gesammelt und mit vordefinierten Gewichtungen miteinander überblendet. Dies bewirkt eine Glättung einer nicht animierten Szene, geht jedoch zu Lasten der Leistung, da bei jeder Aktualisierung mehrere zusätzliche Frames gerendert werden.

Super-Sampling-Antialiasing (SSAA)

Super-Sampling-Antialiasing ist eine „Brute-Force“-Methode zur Glättung einer Szene. Dabei wird zunächst in eine Textur gerendert, deren Größe ein Vielfaches der gewünschten Szenengröße beträgt, und anschließend auf die Zielgröße heruntergerechnet. Wird beispielsweise 2X-SSAA angefordert, wird die Szene auf eine Textur gerendert, die doppelt so groß ist wie die beabsichtigte Größe, und im Rahmen dieses Schritts heruntergerechnet. Dies kann erhebliche Auswirkungen auf die Leistung und den Ressourcenverbrauch haben und sollte daher nach Möglichkeit vermieden werden. Es ist auch möglich, dass die Größe von „ View3D “ zu groß ist, um diese Methode anzuwenden, da die dafür benötigte Textur größer sein könnte als die von der Rendering-Hardware unterstützte Größe.

© 2026 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.