Effect QML Type
Grundkomponente zur Erstellung eines Nachbearbeitungseffekts. Mehr...
| Import Statement: | import QtQuick3D |
| Inherits: |
Eigenschaften
- passes : list
Ausführliche Beschreibung
Der Typ „Effekt“ ermöglicht es dem Benutzer, eigene Nachbearbeitungseffekte für QtQuick3D zu implementieren.
Nachbearbeitungseffekte
Ein Nachbearbeitungseffekt ähnelt konzeptionell stark dem Element „ ShaderEffect “ in „ Qt Quick “. Wenn ein Effekt vorhanden ist, wird die Szene zunächst in eine separate Textur gerendert. Der Effekt wird dann durch das Zeichnen eines texturierten Quadrats auf das Hauptrenderziel angewendet, abhängig von der „ render mode “ des „ View3D “. Der Effekt kann einen Vertex-Shader, einen Fragment-Shader oder beides bereitstellen. Effekte werden gemäß „ View3D “ immer auf die gesamte Szene angewendet.
Effekte werden über die Eigenschaft „ SceneEnvironment::effects “ mit dem „ SceneEnvironment “ verknüpft. Die Eigenschaft ist eine Liste: Effekte können miteinander verkettet werden; sie werden in der Reihenfolge ihrer Auflistung angewendet, wobei die Ausgabe des vorherigen Schritts als Eingabe für den nächsten dient und die Ausgabe des letzten Effekts den Inhalt des „ View3D “ definiert.
Hinweis: „ SceneEnvironment “ und„ ExtendedSceneEnvironment “ bieten eine Reihe integrierter Effekte, wie beispielsweise Tiefenschärfe, Leuchten/Bloom, Linsenreflexe, Farbkorrektur und Vignettierung. Prüfen Sie stets zunächst, ob diese für die Anforderungen der Anwendung ausreichen, und ziehen Sie die Verwendung der integrierten Funktionen der Implementierung eines benutzerdefinierten Nachbearbeitungseffekts vor.
Effekte ähneln in vielerlei Hinsicht den „ custom materials “. Ein benutzerdefiniertes Material ist jedoch mit einem Modell verknüpft und für die Schattierung des jeweiligen Meshes verantwortlich. Während der Vertex-Shader eines Effekts immer ein Quad (zum Beispiel zwei Dreiecke) als Eingabe erhält, nimmt der Fragment-Shader des Effekts die Textur mit dem Inhalt der Szene ab.
Im Gegensatz zu benutzerdefinierten Materialien unterstützen Effekte mehrere Durchläufe (Passes). Für viele Effekte ist dies nicht erforderlich, und wenn mehrere Effekte angewendet werden müssen, lassen sich identische Ergebnisse oft durch die Verkettung mehrerer Effekte in „ the SceneEnvironment “ erzielen. Dies wird auch im Beispiel „Custom Effect“ veranschaulicht. Pässe bieten jedoch die Möglichkeit, zusätzliche Farbpuffer (Texturen) anzufordern und festzulegen, in welche dieser zusätzlichen Puffer sie ausgeben. Dies ermöglicht die Implementierung komplexerer Bildverarbeitungstechniken, da nachfolgende Pässe dann einen oder mehrere dieser zusätzlichen Puffer sowie den ursprünglichen Inhalt der Szene als Eingabe verwenden können. Bei Bedarf können diese zusätzlichen Puffer eine verlängerte Lebensdauer haben, was bedeutet, dass ihr Inhalt zwischen den Einzelbildern erhalten bleibt. Dies ermöglicht die Implementierung von Effekten, die auf der Akkumulation von Inhalten aus mehreren Einzelbildern beruhen, wie beispielsweise Bewegungsunschärfe.
Im Vergleich zu den 2D- ShaderEffect n von „ Qt Quick “ haben die 3D-Nachbearbeitungseffekte den Vorteil, dass sie mit Tiefenpufferdaten arbeiten können und die Möglichkeit bieten, mehrere Durchläufe mit Zwischenpuffern zu implementieren. Zudem wurden die texturbezogenen Funktionen erweitert: „ Qt Quick 3D “ ermöglicht eine feinere Steuerung der Filtermodi und erlaubt die Verwendung von Effekten mit anderen Texturformaten als RGBA8, beispielsweise mit Gleitkommaformaten.
Hinweis: Nachbearbeitungseffekte sind derzeit verfügbar, wenn für das „ View3D “ die Option „ renderMode “ auf „ Offscreen “, „ Underlay “ oder „ Overlay “ gesetzt ist. Im Modus „ Inline “ werden die Effekte nicht gerendert.
Hinweis: Bei der Verwendung von Nachbearbeitungseffekten sollten die von der Anwendung bereitgestellten Shader lineare Farbdaten ohne Tonemapping erwarten. Das Tonemapping, das während des Hauptrenderdurchgangs (oder während des Skybox-Renderings, falls eine Skybox vorhanden ist) durchgeführt wird, wenn „ tonemapMode “ auf einen anderen Wert als „ SceneEnvironment.TonemapModeNone “ gesetzt ist, wird automatisch deaktiviert, sobald mindestens ein Nachbearbeitungseffekt in der „ SceneEnvironment “ angegeben ist. Der Fragment-Shader des letzten Effekts in der Kette (genauer gesagt, des letzten Durchgangs des letzten Effekts in der Kette) wird automatisch so angepasst, dass er dasselbe Tonemapping durchführt wie der Hauptrenderdurchgang.
Hinweis: Effekte , die ihr eigenes Tonemapping durchführen, sollten in einem „ SceneEnvironment “ verwendet werden, bei dem das integrierte Tonemapping deaktiviert ist, indem „ tonemapMode “ auf „ SceneEnvironment.TonemapModeNone “ gesetzt wird.
Hinweis: Standardmäßig wird die als Eingabe für die Effekte verwendete Textur mit einem Gleitkomma-Texturformat erstellt, beispielsweise 16-Bit-Gleitkomma-RGBA. Das Format der Ausgabetextur ist identisch, da es standardmäßig dem Eingabeformat folgt. Dies kann mithilfe von „ Buffer “ und einem leeren Namen überschrieben werden. Der Standardwert „RGBA16F“ ist nützlich, da er die Arbeit mit linearen Daten ohne Tonemapping ermöglicht, ohne dass Farbwerte außerhalb des Bereichs von 0 bis 1 begrenzt werden.
Daten für die Shader bereitstellen
Wie bei ` CustomMaterial ` oder ` ShaderEffect` können die dynamischen Eigenschaften eines `Effect`-Objekts mithilfe der üblichen QML- und ` Qt Quick `-Funktionen geändert und animiert werden, wobei die Werte automatisch den Shadern zur Verfügung gestellt werden. Die folgende Liste zeigt, wie die Eigenschaften zugeordnet werden:
- bool, int, real -> bool, int, float
- QColor, ` color ` -> `vec4`, und die Farbe wird in den linearen Farbraum konvertiert, wobei für den in QML angegebenen Farbwert der sRGB-Farbraum vorausgesetzt wird. Die in Qt integrierten Farben, wie beispielsweise `
"green"`, liegen ebenfalls im sRGB-Farbraum, und die gleiche Konvertierung wird für alle Farbeigenschaften von `DefaultMaterial` und ` PrincipledMaterial` durchgeführt, sodass dieses Verhalten von `Effect` mit diesen übereinstimmt. - QRect, QRectF, rect -> vec4
- QPoint, QPointF, point, QSize, QSizeF, size -> vec2
- QVector2D, vector2d -> vec3
- QVector3D, vector3d -> vec3
- QVector4D, vector4d -> vec4
- QMatrix4x4, matrix4x4 -> mat4
- QQuaternion, quaternion -> vec4, der Skalarwert ist
w - TextureInput -> „sampler2D“ oder „samplerCube“, je nachdem, ob „ Texture “ oder „ CubeMapTexture “ in der Textur-Eigenschaft von „ TextureInput “ verwendet wird. Das Setzen der Eigenschaft „ enabled “ auf „false“ führt dazu, dass dem Shader eine Dummy-Textur zur Verfügung gestellt wird, was bedeutet, dass die Shader weiterhin funktionsfähig sind, jedoch eine Textur mit undurchsichtigem schwarzem Bildinhalt abtasten. Beachten Sie, dass Eigenschaften für Sampler immer auf ein „ TextureInput “-Objekt verweisen müssen und nicht direkt auf ein „ Texture “. Was die Eigenschaften von „ Texture “ betrifft, werden bei Effekten nur die Eigenschaften in Bezug auf Quelle, Kachelung und Filterung implizit berücksichtigt, während die übrigen (wie z. B. UV-Transformationen) von den benutzerdefinierten Shadern nach eigenem Ermessen implementiert werden müssen.
Hinweis: Wenn ein im Shader-Code referenziertes Uniform keine entsprechende Eigenschaft hat, führt dies bei der Verarbeitung des Effekts zur Laufzeit zu einem Shader-Kompilierungsfehler. Es gibt einige Ausnahmen, wie z. B. Sampler-Uniforms, denen eine Dummy-Textur zugewiesen wird, wenn keine entsprechende QML-Eigenschaft vorhanden ist. Generell müssen jedoch alle Uniforms und Sampler über eine entsprechende, im Effect-Objekt deklarierte Eigenschaft verfügen.
Erste Schritte mit benutzerdefinierten Effekten
Ein benutzerdefinierter Nachbearbeitungseffekt umfasst mindestens ein `Effect`-Objekt und einen Fragment-Shader-Ausschnitt. Für manche Effekte ist zudem ein angepasster Vertex-Shader erforderlich.
Als einfaches Beispiel erstellen wir einen Effekt, der den Inhalt der Szene mit einem Bild kombiniert und dabei den Wert des Rotkanals auf animierte Weise weiter verändert:
| |
Hier wird die Textur mit dem Bild „ image.png “ dem Shader unter dem Namen „ tex “ zur Verfügung gestellt. Der Wert von „redLevel“ steht im Shader in einer gleichnamigen Uniform „ float “ zur Verfügung.
Der Fragment-Shader muss eine Funktion namens „ MAIN “ enthalten. Die endgültige Fragmentfarbe wird durch „ FRAGCOLOR “ bestimmt. Auf die Haupt-Input-Textur mit dem Inhalt der Szene von „ View3D “ kann über ein „ sampler2D “ mit dem Namen „ INPUT “ zugegriffen werden. Die UV-Koordinaten des Quadrats befinden sich in INPUT_UV. Diese UV-Werte eignen sich stets zum Abtasten von INPUT, unabhängig von der zugrunde liegenden Grafik-API zur Laufzeit (und somit unabhängig von der Richtung der Y-Achse in Bildern, da die erforderlichen Anpassungen automatisch durch Qt Quick 3D vorgenommen werden). Das Abtasten der Textur mit unserem externen Bild erfolgt über TEXTURE_UV. INPUT_UV ist in plattformübergreifenden Anwendungen nicht geeignet, da V gespiegelt werden muss, um die zuvor erwähnten Unterschiede im Koordinatensystem auszugleichen – wobei für Texturen, die auf Bildern basieren, und für Texturen, die als Renderziele verwendet werden, unterschiedliche Logik zum Einsatz kommt. Glücklicherweise wird dies alles von der Engine übernommen, sodass der Shader hierfür keine weitere Logik benötigt.
Sobald „simpleEffect“ verfügbar ist, kann es der Effektsliste des „ View3D “ unter „ SceneEnvironment “ zugeordnet werden:
environment: SceneEnvironment {
effects: [ simpleEffect ]
}Das Ergebnis würde in etwa wie folgt aussehen, wobei links die ursprüngliche Szene und rechts die Szene mit dem angewendeten Effekt zu sehen ist:
|
|
Hinweis: Der Wert der Eigenschaft „ shader “ im Shader ist eine URL, wie es in QML und „ Qt Quick “ üblich ist, die auf die Datei verweist, die das Shader-Snippet enthält, und funktioniert sehr ähnlich wie „ ShaderEffect “ oder „ Image.source “. Es werden nur die Schemata „ file “ und „ qrc “ unterstützt. Es ist auch möglich, das Schema „ file “ wegzulassen, wodurch sich auf bequeme Weise ein relativer Pfad angeben lässt. Ein solcher Pfad wird relativ zum Speicherort der Komponente (der Datei „ .qml “) aufgelöst.
Hinweis: Der Shader -Code wird immer im Vulkan-GLSL-Stil bereitgestellt, unabhängig von der von Qt zur Laufzeit verwendeten Grafik-API.
Hinweis: Der vom Effekt bereitgestellte Vertex- und Fragment-Shader-Code stellt für sich genommen keine vollständigen GLSL-Shader dar. Vielmehr enthalten sie eine „ MAIN “-Funktion und optional eine Reihe von „ VARYING “-Deklarationen, die anschließend von der Engine durch weiteren Shader-Code ergänzt werden.
Hinweis: Das obige Beispiel ist nicht kompatibel mit dem optionalen Multiview-Rendering-Modus, der in einigen VR/AR-Anwendungen verwendet wird. Damit es sowohl mit als auch ohne Multiview-Modus funktioniert, ändern Sie MAIN() wie folgt:
void MAIN()
{
vec4 c = texture(tex, TEXTURE_UV);
c.r *= redLevel;
#if QSHADER_VIEW_COUNT >= 2
FRAGCOLOR = c * texture(INPUT, vec3(INPUT_UV, VIEW_INDEX));
#else
FRAGCOLOR = c * texture(INPUT, INPUT_UV);
#endif
}Effekte mit Vertex-Shadern
Ein Vertex-Shader muss, sofern vorhanden, eine Funktion namens „ MAIN “ bereitstellen. In den allermeisten Fällen wird der benutzerdefinierte Vertex-Shader keine eigene Berechnung der homogenen Vertex-Position vornehmen wollen, doch ist dies mithilfe von „ POSITION “, „ VERTEX “ und „ MODELVIEWPROJECTION_MATRIX “ möglich. Wenn „ POSITION “ im benutzerdefinierten Shader-Code nicht vorhanden ist, wird automatisch eine Anweisung, die „ POSITION = MODELVIEWPROJECTION_MATRIX * vec4(VERTEX, 1.0); “ entspricht, von „ Qt Quick 3D “ eingefügt.
Um Daten zwischen dem Vertex- und dem Fragment-Shader zu übergeben, verwenden Sie das Schlüsselwort VARYING. Intern wird dies dann in die entsprechende Deklaration für einen Vertex-Ausgang oder einen Fragment-Eingang umgewandelt. Der Fragment-Shader kann dieselbe Deklaration verwenden, wodurch es möglich ist, den interpolierten Wert für das aktuelle Fragment auszulesen.
Schauen wir uns ein Beispiel an, das im Grunde dem integrierten „DistortionSpiral“-Effekt sehr ähnlich ist:
| |
Die Liste „ passes “ des Effect-Objekts sollte nun sowohl die Vertex- als auch die Fragment-Snippets enthalten:
passes: Pass {
shaders: [
Shader {
stage: Shader.Vertex
shader: "effect.vert"
},
Shader {
stage: Shader.Fragment
shader: "effect.frag"
}
]
}Das Endergebnis sieht wie folgt aus:
|
|
Spezielle Schlüsselwörter in Effekt-Shadern
VARYING- Deklariert je nach Typ des aktuellen Shaders einen Vertex-Ausgang oder einen Fragment-Eingang.MAIN- Diese Funktion muss in einem Effekt-Shader immer vorhanden sein.FRAGCOLOR-vec4– Die endgültige Fragmentfarbe; die Ausgabe des Fragment-Shaders. (nur Fragment-Shader)POSITION-vec4– Die im Vertex-Shader berechnete homogene Position. (nur Vertex-Shader)MODELVIEWPROJECTION_MATRIX-mat4– Die Transformationsmatrix für das Bildschirmquad.VERTEX-vec3– Die Scheitelpunkte des Quadrats; die Eingabe für den Vertex-Shader. (nur Vertex-Shader)INPUT-sampler2Dodersampler2DArray– Der Sampler für die Eingabetextur, in die die Szene gerendert wird, es sei denn, ein Pass leitet seine Eingabe über ein „ BufferInput “-Objekt um; in diesem Fall bezieht sichINPUTauf die Textur des zusätzlichen Farbpuffers, auf die von BufferInput verwiesen wird. Bei aktiviertem Multiview-Rendering, was für VR/AR-Anwendungen relevant sein kann, handelt es sich hierbei um ein `sampler2DArray`, während die Eingabetextur zu einem 2D-Textur-Array wird.INPUT_UV-vec2– UV-Koordinaten zum Abtasten vonINPUT.TEXTURE_UV-vec2– UV-Koordinaten, die zum Abtasten einer Textur geeignet sind, deren Inhalt aus einer Bilddatei geladen wurde.INPUT_SIZE-vec2– Die Größe der Textur „INPUT“ in Pixeln.OUTPUT_SIZE-vec2– Die Größe des Ausgabepuffers in Pixeln. Entspricht oft der Größe von „INPUT_SIZE“, es sei denn, der Pass gibt die Daten an einen zusätzlichen Puffer mit einem Größenmultiplikator aus.FRAME- `float` – Ein Frame-Zähler, der nach jedem Frame in der ` View3D` erhöht wird.DEPTH_TEXTURE-sampler2Dodersampler2DArray– Eine Tiefentextur mit dem Inhalt des Tiefenpuffers, der die undurchsichtigen Objekte in der Szene enthält. Wie bei CustomMaterial löst das Vorhandensein dieses Schlüsselworts im Shader die automatische Erzeugung der Tiefentextur aus.NORMAL_ROUGHNESS_TEXTURE-sampler2D– Eine Textur mit den Welt-Raum-Normalen und der Materialrauheit der undurchsichtigen Objekte im aktuell sichtbaren Teil der Szene. Wie bei CustomMaterial bedeutet das Vorhandensein dieses Schlüsselworts im Shader einen zusätzlichen Render-Durchlauf zur Erzeugung der Normaltextur.VIEW_INDEX-uint– Bei aktiviertem Multiview-Rendering ist dies der aktuelle Ansichtsindex, der sowohl im Vertex- als auch im Fragment-Shader verfügbar ist. Immer 0, wenn kein Multiview-Rendering verwendet wird.PROJECTION_MATRIX- `mat4`: Die Projektionsmatrix. Beachten Sie, dass es sich beim Multiview-Rendering um ein Array von Matrizen handelt.INVERSE_PROJECTION_MATRIX-mat4, die inverse Projektionsmatrix. Beachten Sie, dass es sich hierbei bei aktivem Multiview-Rendering um ein Array von Matrizen handelt.VIEW_MATRIX->mat4, die Ansichts- (Kamera-)Matrix. Beachten Sie, dass es sich hierbei beim Multiview-Rendering um ein Array von Matrizen handelt.- float
NDC_Y_UP– Der Wert beträgt1, wenn die Y-Achse im normalisierten Gerätekordinatensystem nach oben zeigt, und-1, wenn die Y-Achse nach unten zeigt. Die Y-Achse zeigt bei der Darstellung mit Vulkan nach unten. - float
FRAMEBUFFER_Y_UP– Der Wert ist „1“, wenn die Y-Achse im Koordinatensystem für Framebuffer (Texturen) nach oben zeigt, was bedeutet, dass „(0, 0)“ die linke untere Ecke ist. Der Wert ist „-1“, wenn die Y-Achse nach unten zeigt, wobei „(0, 0)“ die linke obere Ecke ist. - float
NEAR_CLIP_VALUE– Der Wert beträgt-1, wenn der Bereich der Clipping-Ebenen bei-1beginnt und bis1reicht. Dies gilt bei der Verwendung von OpenGL für das Rendering. Bei anderen Rendering-Backends beträgt der Wert dieser Eigenschaft0, was bedeutet, dass der Bereich der Clipping-Ebenen von0bis1reicht.
Erstellen von Multi-Pass-Effekten
Ein Multi-Pass-Effekt verwendet oft mehr als einen Satz von Shadern und nutzt die Eigenschaften „ output “ und „ commands “. Jeder Eintrag in der Pass-Liste entspricht einem Render-Pass, der ein Viereck in die Ausgabetextur des Passes zeichnet, während er gleichzeitig die Eingabetextur des Effekts und optional auch andere Texturen abtastet.
Der typische Aufbau eines Multi-Pass-Effekts kann wie folgt aussehen:
passes: [
Pass {
shaders: [
Shader {
stage: Shader.Vertex
shader: "pass1.vert"
},
Shader {
stage: Shader.Fragment
shader: "pass1.frag"
}
// This pass outputs to the intermediate texture described
// by the Buffer object.
output: intermediateColorBuffer
],
},
Pass {
shaders: [
Shader {
stage: Shader.Vertex
shader: "pass2.vert"
},
Shader {
stage: Shader.Fragment
shader: "pass2.frag"
}
// The output of the last pass needs no redirection, it is
// the final result of the effect.
],
commands: [
// This pass reads from the intermediate texture, meaning
// INPUT in the shader will refer to the texture associated
// with the Buffer.
BufferInput {
buffer: intermediateColorBuffer
}
]
}
]Was ist „ intermediateColorBuffer “?
Buffer {
id: intermediateColorBuffer
name: "tempBuffer"
// format: Buffer.RGBA8
// textureFilterOperation: Buffer.Linear
// textureCoordOperation: Buffer.ClampToEdge
}Die auskommentierten Eigenschaften sind nicht erforderlich, wenn die gewünschten Werte mit den Standardwerten übereinstimmen.
Intern führt das Vorhandensein dieses Buffer-Objekts und dessen Referenzierung über die Eigenschaft „ output “ eines Passes zur Erstellung einer Textur, deren Größe der „ View3D “ entspricht – und damit auch der Größe der impliziten Eingabe- und Ausgabetexturen. Ist dies nicht gewünscht, kann die Eigenschaft „ sizeMultiplier “ verwendet werden, um eine Zwischentextur mit einer anderen Größe zu erhalten. Dies kann dazu führen, dass die Uniforms „ INPUT_SIZE “ und „ OUTPUT_SIZE “ im Shader unterschiedliche Werte aufweisen.
Standardmäßig kann der Effekt nicht davon ausgehen, dass Texturen ihren Inhalt zwischen den Frames beibehalten. Wenn eine neue Zwischentextur erstellt wird, wird sie auf „ vec4(0.0) “ zurückgesetzt. Danach kann dieselbe Textur für einen anderen Zweck wiederverwendet werden. Daher sollten Effekt-Pässe immer in die gesamte Textur schreiben, ohne zu Beginn des Passes Annahmen über deren Inhalt zu treffen. Es gibt eine Ausnahme: Buffer-Objekte, bei denen „ bufferFlags “ auf „Buffer.SceneLifetime“ gesetzt ist. Dies bedeutet, dass die Textur dauerhaft mit einem Pass des Effekts verknüpft ist und nicht für andere Zwecke wiederverwendet wird. Der Inhalt solcher Farbpuffer bleibt zwischen den Einzelbildern erhalten. Dies wird typischerweise in Effekten wie Bewegungsunschärfe im Ping-Pong-Verfahren verwendet: Der erste Durchgang nimmt den persistenten Puffer zusätzlich zur Haupteingabetextur des Effekts als Eingabe und gibt in einen anderen Zwischenpuffer aus, während der zweite Durchgang in den persistenten Puffer ausgibt. Auf diese Weise nimmt der erste Durchgang im ersten Frame eine leere (transparente) Textur ab, während er in den nachfolgenden Frames die Ausgabe des zweiten Durchgangs aus dem vorherigen Frame abtastet. Ein dritter Durchgang kann dann die Eingabe des Effekts und die Ausgabe des zweiten Durchgangs miteinander überblenden.
Der Befehlstyp „ BufferInput “ wird verwendet, um benutzerdefinierte Texturpuffer für den Render-Durchgang verfügbar zu machen.
Um beispielsweise im Render-Pass-Shader unter dem Namen „ mySampler “ auf „ someBuffer “ zuzugreifen, kann Folgendes zur Befehlsliste hinzugefügt werden:
BufferInput { buffer: someBuffer; sampler: "mySampler" }Wenn der Name „ sampler “ nicht angegeben wird, wird standardmäßig „ INPUT “ verwendet.
Puffer können nützlich sein, um Zwischenergebnisse zwischen Render-Pässen auszutauschen.
Um vorgeladene Texturen für den Effekt verfügbar zu machen, sollte stattdessen „ TextureInput “ verwendet werden. Diese können als Eigenschaften des Effekts selbst definiert werden und stehen den Shadern automatisch über ihre Eigenschaftsnamen zur Verfügung.
property TextureInput tex: TextureInput {
texture: Texture { source: "image.png" }
}Hier ist „ tex “ ein gültiger Sampler in allen Shadern aller Durchläufe des Effekts.
Bei Uniform-Werten aus Eigenschaften lesen alle Durchläufe des Effekts in ihren Shadern dieselben Werte ein. Bei Bedarf ist es möglich, den Wert eines Uniforms nur für einen bestimmten Durchlauf zu überschreiben. Dies wird durch Hinzufügen des Befehls „ SetUniformValue “ zur Befehlsliste des Durchlaufs erreicht.
Hinweis: Die „ target “ des pass-spezifischen Uniform-Wert-Setzers darf sich nur auf einen Namen beziehen, der dem Namen einer Eigenschaft des Effekts entspricht. Sie kann den Wert für die entsprechende Uniform einer Eigenschaft überschreiben, darf jedoch keine neuen Uniforms einführen.
Überlegungen zur Leistung
Beachten Sie den erhöhten Ressourcenverbrauch und die möglicherweise verminderte Leistung bei der Verwendung von Nachbearbeitungseffekten. Genau wie bei „ Qt Quick “-Ebenen und „ ShaderEffect “ ist das Rendern der Szene in eine Textur und die anschließende Verwendung dieser Textur zur Texturierung eines Quads kein ressourcenschonender Vorgang, insbesondere auf Low-End-Hardware mit begrenzter Fragmentverarbeitungsleistung. Der Bedarf an zusätzlichem Grafikspeicher sowie die erhöhte GPU-Auslastung hängen beide von der Größe der „ View3D “ ab (die auf eingebetteten Geräten ohne Fenstersystem oft so groß wie die Bildschirmauflösung sein kann). Multi-Pass-Effekte sowie die Anwendung mehrerer Effekte erhöhen die Ressourcen- und Leistungsanforderungen zusätzlich.
Daher ist es äußerst ratsam, bereits früh im Entwicklungszyklus sicherzustellen, dass das Zielgerät und der Grafikstack in der Lage sind, die im Entwurf der 3D-Szene enthaltenen Effekte bei der Bildschirmauflösung des Endprodukts zu bewältigen.
DEPTH_TEXTURE ist zwar bei bestimmten Techniken unvermeidbar, erfordert jedoch einen zusätzlichen Rendering-Durchgang zur Erzeugung des Texturinhalts, was bei weniger leistungsfähiger Hardware ebenfalls zu Einbußen führen kann. Verwenden Sie daher „ DEPTH_TEXTURE “ in den Shadern des Effekts nur, wenn dies unbedingt erforderlich ist.
Auch die Komplexität der Operationen in den Shadern spielt eine wichtige Rolle. Genau wie bei „ CustomMaterial “ kann ein suboptimaler Fragment-Shader leicht zu einer verminderten Rendering-Leistung führen.
Seien Sie vorsichtig mit „ sizeMultiplier in Buffer “, wenn Werte größer als 1 zum Einsatz kommen. Ein Multiplikator von 4 bedeutet beispielsweise, dass eine Textur erstellt und anschließend gerendert wird, die viermal so groß ist wie die „ View3D “. Genau wie bei Schattenkarten und Multi- oder Supersampling können die erhöhten Ressourcen- und Leistungskosten auf Systemen mit begrenzter GPU-Leistung schnell die Vorteile einer besseren Qualität überwiegen.
Überlegungen zu VR/AR
Bei der Entwicklung von Anwendungen für virtuelle oder erweiterte Realität unter Verwendung von Qt Quick 3D XR sind Postprocessing-Effekte funktionsfähig und einsetzbar. Designer und Entwickler sollten jedoch besonders darauf achten, zu verstehen, welche und welche Art von Effekten in einer Virtual-Reality-Umgebung sinnvoll sind. Einige Effekte, darunter auch einige der in „ ExtendedSceneEnvironment “ integrierten oder des veralteten „Effects“-Moduls, führen in einer VR-Umgebung nicht zu einem guten visuellen Erlebnis und können den Nutzer möglicherweise sogar körperlich beeinträchtigen (z. B. durch Auslösen von Reisekrankheit oder Schwindel).
Wenn der effizientere Multiview-Rendering-Modus in einer VR/AR-Anwendung aktiviert ist, gibt es keinen separaten Render-Durchlauf für die Inhalte des linken und rechten Auges. Stattdessen erfolgt alles in einem einzigen Durchgang unter Verwendung eines 2D-Textur-Arrays mit zwei Ebenen anstelle von zwei unabhängigen 2D-Texturen. Dies bedeutet auch, dass viele Zwischenpuffer – also Farb- oder Tiefentexturen – in diesem Modus zu Textur-Arrays umgewandelt werden müssen. Dies hat wiederum Auswirkungen auf benutzerdefinierte Materialien und Nachbearbeitungseffekte. Texturen wie die Eingabetextur (INPUT) und die Tiefentextur (DEPTH_TEXTURE) werden zu 2D-Textur-Arrays, die im Shader als „ sampler2DArray “ anstelle von „ sampler2D “ bereitgestellt werden. Dies hat Auswirkungen auf GLSL-Funktionen wie „texture()“, „textureLod()“ oder „textureSize()“. Die UV-Koordinate ist dann ein `vec3` und kein `vec2`. Die Funktion `textureSize()` gibt hingegen ein `vec3` und kein `vec2` zurück. Effekte, die unabhängig vom Rendering-Modus funktionieren sollen, können mit einem entsprechenden `ifdef` geschrieben werden:
#if QSHADER_VIEW_COUNT >= 2
vec4 c = texture(INPUT, vec3(INPUT_UV, VIEW_INDEX));
#else
vec4 c = texture(INPUT, INPUT_UV);
#endifEs kann auch sinnvoll sein, Makros zu definieren, die beide Fälle abdecken. Zum Beispiel:
#if QSHADER_VIEW_COUNT >= 2
#define SAMPLE_INPUT(uv) texture(INPUT, vec3(uv, VIEW_INDEX))
#define SAMPLE_DEPTH(uv) texture(DEPTH_TEXTURE, vec3(uv, VIEW_INDEX)).r
#define PROJECTION PROJECTION_MATRIX[VIEW_INDEX]
#define INVERSE_PROJECTION INVERSE_PROJECTION_MATRIX[VIEW_INDEX]
#else
#define SAMPLE_INPUT(uv) texture(INPUT, uv)
#define SAMPLE_DEPTH(uv) texture(DEPTH_TEXTURE, uv).r
#define PROJECTION PROJECTION_MATRIX
#define INVERSE_PROJECTION INVERSE_PROJECTION_MATRIX
#endifDies gilt nicht für ` NORMAL_ROUGHNESS_TEXTURE `, das immer eine 2D-Textur ist, selbst wenn das Multiview-Rendering aktiv ist:
#define SAMPLE_NORMAL(uv) normalize(texture(NORMAL_ROUGHNESS_TEXTURE, uv).rgb)Hinweis: Das Vorhandensein von Schlüsselwörtern wie „ DEPTH_TEXTURE “ löst zusätzliche Render-Durchläufe aus, und Uniforms wie „ INVERSE_PROJECTION_MATRIX “ werden berechnet und gesetzt, sobald das Schlüsselwort an beliebiger Stelle im Shader-Schnipsel vorkommt. Dies ist sowohl hinsichtlich der Leistung als auch des Ressourcenverbrauchs aufwändiger. Daher wird empfohlen, solche #defines nur dann hinzuzufügen, wenn die Texturen und Matrizen im Effekt tatsächlich verwendet werden.
Siehe auch Shader, Pass, Buffer, BufferInput und Qt Quick 3D – Beispiel für einen benutzerdefinierten Effekt.
Dokumentation zu den Eigenschaften
passes : list [read-only]
Enthält eine Liste der vom Effekt implementierten Render passes.
© 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.


