Instanzielles Rendering
Einführung
Qt Quick 3D unterstützt die Instanzierung von Model Objekten. Instanzierung bezieht sich auf eine Technik, bei der ein Objekt mit einem einzigen Zeichenaufruf mehrfach gerendert wird. (Zum Beispiel die OpenGL-Funktion glDrawElementsInstanced
.)
Die Instanzierung ermöglicht die Vervielfältigung eines Modells mit Variationen. Im Gegensatz zur Verwendung einer Repeater3D werden das Modell und seine Grafikressourcen nur einmal zugewiesen. Das Rendering der duplizierten Instanzen wird auf niedriger Ebene von der GPU durchgeführt. Je nach Komplexität des Modells kann dies zu einer Leistungsverbesserung um mehrere Größenordnungen führen.
In der Praxis erfolgt die Instanzierung durch die Definition einer Tabelle, die angibt, wie jede Instanz im Vergleich zum Basismodell geändert wird.
Instanzierungs-API
Das Hauptprinzip der Instanzierungs-API ist, dass sie explizit ist: Es wird nicht versucht, Gelegenheiten zur Instanzierung innerhalb der bestehenden API automatisch zu erkennen. Stattdessen wird jedes Modell einzeln markiert, indem seine instancing Eigenschaft auf ein Instancing Objekt verweist. Das gleiche Instancing-Objekt kann für mehrere Modelle gleichzeitig verwendet werden.
Das Instancing-Objekt gibt eine Tabelle an, die definiert, wie jede Kopie gerendert wird. Die verfügbaren Modifikationen sind:
- Transformation: Position, Drehung und Skalierung
- Farbe: eine Farbe, die mit dem Material des Modells gemischt wird
- benutzerdefinierte Daten: Daten, die von benutzerdefinierten Materialien verwendet werden können
Qt bietet drei QML-Typen, die von Instancing erben:
- InstanceList listet alle Instanzen auf und ermöglicht die Bindung an die Eigenschaften der einzelnen Instanzen.
- RandomInstancing bietet eine Möglichkeit, schnell zu testen und Prototypen zu erstellen, indem zufällige Instanzen innerhalb definierter Grenzen erzeugt werden.
- FileInstancing liest eine Instanztabelle aus einer externen Datei.
Das Instanzierungsbeispiel zeigt, wie man eine Szene mit Hilfe der QML-API erstellt.
Andere Arten von Instanztabellen können in C++ durch Unterklassen von QQuick3DInstancing definiert werden. Zum Beispiel verwendet particle system intern seine eigene Instanztabelle. Sie ist als ModelParticle3D.instanceTable verfügbar.
Durch das Schreiben von benutzerdefiniertem Shader-Code ist es möglich, Instanzierung zu verwenden, um zusätzliche Eigenschaften zu steuern, wie z. B. Variablen für physikalisch basiertes Rendering, Skelettanimationsgewichte, Verzerrung oder alles andere, was mit benutzerdefinierten Materialien ausgedrückt werden kann. Die benutzerdefinierten Daten in der Instanzierungstabelle bestehen aus vier Fließkommazahlen.
Das Beispiel für die benutzerdefinierte Instanzierung zeigt, wie man benutzerdefinierte Materialien und eine in C++ implementierte Instanztabelle kombiniert.
Alpha-Blending und Instanzierung
Korrektes Alpha-Blending erfordert, dass halbtransparente Objekte von hinten nach vorne gerendert werden. Aus diesem Grund sortiert QtQuick3D undurchsichtige und halbtransparente Objekte getrennt und rendert sie in der richtigen Reihenfolge. Bei der Instanzierung rendert die GPU die Instanzen jedoch in der durch die Instanzierungstabelle festgelegten Reihenfolge, wenn depth-sorting nicht aktiviert ist. Aus Leistungsgründen sortiert QtQuick3D die Tabelle standardmäßig nicht, da dies bei einer großen Anzahl von Instanzen viel Zeit in Anspruch nehmen kann. Dies bedeutet, dass die Ergebnisse falsch aussehen können, wenn sich halbtransparente Instanzen untereinander oder mit anderen halbtransparenten Objekten überlappen. Im Allgemeinen ist der Fehler weniger sichtbar, wenn die Deckkraft niedrig ist.
Vollständig undurchsichtige Objekte zusammen mit nicht überlappenden halbtransparenten Objekten werden immer korrekt gerendert, da Qt Tiefenpuffer-Tests verwendet, um das Zeichnen hinter undurchsichtigen Objekten zu vermeiden. Das Fehlen einer Sortierung hat jedoch potenzielle Auswirkungen auf die Leistung von undurchsichtigen Objekten: Sie werden möglicherweise nicht in der optimalen Reihenfolge gerendert, was bedeutet, dass derselbe Pixel mehrfach geschrieben werden kann, was mehr Arbeit für den Fragment-Shader bedeutet.
Der Renderer überprüft den Inhalt der Instanztabelle nicht, daher muss sie explizit angegeben werden, wenn eine Instanztabelle halbtransparente Alphawerte enthält: Setzen Sie die Eigenschaft hasTransparency auf true
, um sicherzustellen, dass der Renderer das Alpha-Blending aktiviert. Dies gilt für alle Instanzen: Auch vollständig opake Instanzen werden ohne Tiefenprüfung gerendert, was zu sichtbaren Fehlern führen kann.
Die Rendering-Reihenfolge relativ zum Rest der Szene kann durch Einstellen der depth bias des Modells angepasst werden.
Transformationen und Instanzierung
Jede Instanz hat ihre eigene Transformation in der Instanztabelle. Diese wird mit den Transformationen des instanzierten Modells kombiniert. Dies ist etwas komplex, da es mehrere Anwendungsfälle gibt:
- Eine Transformation auf dem Modell durchführen, die auf jede einzelne Instanz angewendet wird. Dies ermöglicht billige Animationen, zum Beispiel durch Drehen aller Instanzen auf einmal, ohne die Instanztabelle ändern zu müssen.
- Transformieren der gesamten Gruppe von Instanzen auf einmal.
- Die Instanzierung einer Modellhierarchie.
Um alle diese Fälle zu unterstützen, wird die Transformation des Modells in zwei Teile aufgeteilt: die lokale Instanztransformation und die globale Instanztransformation. Konzeptionell wird die Instanzierung wie folgt durchgeführt:
- Zunächst wird das Modell gemäß der lokalen Instanztransformation transformiert.
- Dann wird jede Instanz durch Anwendung der Instanztabellentransformation berechnet.
- Schließlich wird die gesamte Gruppe der instanzierten Objekte gemäß der globalen Instanztransformation transformiert.
Standardmäßig besteht die lokale Instanztransformation eines Modells aus der Skalierung und Drehung des Modells, während der Rest in die globale Instanztransformation eingeht.
Dies kann durch die Einstellung der Eigenschaft instanceRoot des Modells gesteuert werden. Damit wird der Ursprung des Koordinatensystems der Instanz definiert. Die häufigste Anwendung ist die Instanzierung einer Hierarchie von Modellen. Zum Beispiel, eine Kugel, die um einen Würfel kreist:
Model { id: cube instancing: someInstanceTable source: "#Cube" materials: DefaultMaterial { diffuseColor: "lightgray" } Node { Model { source: "#Sphere" instanceRoot: cube instancing: cube.instancing x: 150 materials: DefaultMaterial { diffuseColor: "gray" } } NumberAnimation on eulerRotation.y { from: 0 to: 360 duration: 4000 loops: Animation.Infinite } } }
Die instanceRoot
ist notwendig, um festzulegen, dass die Kugelinstanz so positioniert werden soll, als wäre sie ein Element des Würfels. Jedes Modell in einer Hierarchie muss immer noch die Eigenschaft instancing
angeben: in normalen Fällen sollten sie alle auf das gleiche Instancing
Objekt gesetzt werden.
instanceRoot
kann auch bei der Instanzierung eines einzelnen Modells verwendet werden. Zum Beispiel ein Zylinder, der sich um einen exzentrischen Punkt dreht:
Node { id: parentNode Model { source: "#Cylinder" instanceRoot: parentNode instancing: anotherInstanceTable x: 25 materials: DefaultMaterial { diffuseColor: "white" } } NumberAnimation on eulerRotation.y { from: 0 to: 360 duration: 1000 loops: Animation.Infinite } }
Auswählen und Instanzieren
Picking ist ein Mechanismus, der die Auswahl eines Modells über eine Benutzerschnittstelleninteraktion ermöglicht. Beim instanzierten Rendering gibt es mehrere Darstellungen desselben Modells, so dass das Pick-Ergebnis eine instance index enthält. Das instanzierte Picking wird durch die Einstellung der Eigenschaft pickable auf dem Basismodell aktiviert.
© 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.