Effect QML Type

Basiskomponente zur Erstellung eines Nachbearbeitungseffekts. Mehr...

Import Statement: import QtQuick3D
Inherits:

Object3D

Eigenschaften

Detaillierte Beschreibung

Der Effekttyp ermöglicht es dem Benutzer, seine eigenen Nachbearbeitungseffekte für QtQuick3D zu implementieren.

Nachbearbeitungseffekte

Ein Nachbearbeitungseffekt ist konzeptionell sehr ähnlich zu Qt Quick's ShaderEffect Element. Wenn ein Effekt vorhanden ist, wird die Szene zunächst in eine separate Textur gerendert. Der Effekt wird dann durch Zeichnen eines texturierten Vierecks auf das Haupt-Rendering-Ziel angewendet, je nach render mode der View3D. Der Effekt kann einen Vertex-Shader, einen Fragment-Shader oder beides bereitstellen. Effekte werden immer auf die gesamte Szene angewendet, je View3D.

Effekte sind mit der SceneEnvironment in der SceneEnvironment::effects Eigenschaft verbunden. Die Eigenschaft ist eine Liste: Effekte können aneinandergereiht werden; sie werden in der Reihenfolge angewandt, in der sie in der Liste stehen, wobei die Ausgabe des vorherigen Schritts als Eingabe für den nächsten verwendet wird, wobei die Ausgabe des letzten Effekts den Inhalt von View3D definiert.

Hinweis: SceneEnvironment und ExtendedSceneEnvironment bieten eine Reihe von integrierten Effekten, wie z. B. Tiefenschärfe, Glühen/Blühen, Linsenreflexion, Farbabstufung und Vignette. Überlegen Sie immer zuerst, ob diese für die Anforderungen der Anwendung ausreichen, und verwenden Sie lieber die integrierten Funktionen, anstatt einen benutzerdefinierten Nachbearbeitungseffekt zu implementieren.

Effekte sind in vielerlei Hinsicht mit custom materials vergleichbar. Ein benutzerdefiniertes Material ist jedoch mit einem Modell verknüpft und für die Schattierung dieses Meshs verantwortlich. Der Vertex-Shader eines Effekts hingegen erhält immer ein Quad (z. B. zwei Dreiecke) als Eingabe, während sein Fragment-Shader die Textur mit dem Inhalt der Szene abtastet.

Im Gegensatz zu benutzerdefinierten Materialien unterstützen Effekte mehrere Durchläufe. Bei vielen Effekten ist dies nicht notwendig, und wenn es notwendig ist, mehrere Effekte anzuwenden, können identische Ergebnisse oft durch die Verkettung mehrerer Effekte in the SceneEnvironment erzielt werden. Dies wird auch am Beispiel des benutzerdefinierten Effekts gezeigt. Allerdings haben Pässe die Möglichkeit, zusätzliche Farbpuffer (Textur) anzufordern und anzugeben, in welchen dieser zusätzlichen Puffer sie ausgegeben werden. Dies ermöglicht die Implementierung komplexerer Bildverarbeitungstechniken, da nachfolgende Durchläufe einen oder mehrere dieser zusätzlichen Puffer sowie den Inhalt der Originalszene als Eingabe verwenden können. Falls erforderlich, können diese zusätzlichen Puffer eine verlängerte Lebensdauer haben, d. h. ihr Inhalt bleibt zwischen den Einzelbildern erhalten, was die Implementierung von Effekten ermöglicht, die auf der Akkumulation von Inhalten aus mehreren Einzelbildern beruhen, wie z. B. Bewegungsunschärfe.

Im Vergleich zu den 2D-Effekten von Qt Quick ShaderEffect haben die 3D-Nachbearbeitungseffekte den Vorteil, dass sie mit Tiefenpufferdaten arbeiten können und mehrere Durchläufe mit Zwischenpuffern möglich sind. Darüber hinaus wurden die texturbezogenen Fähigkeiten erweitert: Qt Quick 3D ermöglicht eine feinere Steuerung der Filtermodi und erlaubt es den Effekten, mit anderen Texturformaten als RGBA8 zu arbeiten, zum Beispiel mit Fließkommaformaten.

Hinweis: Nachbearbeitungseffekte sind derzeit verfügbar, wenn die renderMode von View3D auf Offscreen, Underlay oder Overlay eingestellt ist. Im Modus Inline werden keine Effekte gerendert.

Hinweis: Bei der Verwendung von Nachbearbeitungseffekten sollten die von der Anwendung bereitgestellten Shader lineare Farbdaten ohne angewandtes Tonemapping erwarten. Das Tonemapping, das während des Haupt-Rendering-Durchgangs (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, wenn mindestens ein Nachbearbeitungseffekt in SceneEnvironment angegeben ist. Der letzte Effekt in der Kette (genauer gesagt, der letzte Durchgang des letzten Effekts in der Kette) erhält automatisch seinen Fragment-Shader geändert, um das gleiche Tonemapping durchzuführen, das auch der Haupt-Rendering-Durchgang durchführen würde.

Hinweis: Effekte, die ihr eigenes Tonemapping durchführen, sollten in einem SceneEnvironment verwendet werden, in dem das integrierte Tonemapping durch die Einstellung tonemapMode auf SceneEnvironment.TonemapModeNone deaktiviert ist.

Hinweis: Standardmäßig wird die Textur, die als Eingabe für die Effekte verwendet wird, mit einem Fließkomma-Texturformat erstellt, z. B. 16-Bit-Fließkomma-RGBA. Das Format der Ausgabetextur ist dasselbe, da es standardmäßig dem Eingabeformat folgt. Dies kann mit Buffer und einem leeren Namen außer Kraft gesetzt werden. Die Voreinstellung RGBA16F ist nützlich, weil sie die Arbeit mit nicht tonemapierten linearen Daten ermöglicht, ohne dass die Farbwerte außerhalb des Bereichs 0-1 geklammert werden.

Daten für die Shader freigeben

Wie bei CustomMaterial oder ShaderEffect können die dynamischen Eigenschaften eines Effektobjekts mit den üblichen QML- und Qt Quick -Funktionen geändert und animiert werden, und die Werte werden automatisch an die Shader weitergegeben. Die folgende Liste zeigt, wie Eigenschaften abgebildet werden:

  • bool, int, real -> bool, int, float
  • QColor, color -> vec4, und die Farbe wird in einen linearen Wert umgewandelt, wobei der sRGB-Raum für den in QML angegebenen Farbwert angenommen wird. Die eingebauten Qt-Farben, wie "green", sind ebenfalls im sRGB-Farbraum, und die gleiche Konvertierung wird für alle Farbeigenschaften von DefaultMaterial und PrincipledMaterial durchgeführt, so dass 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, skalarer Wert ist w
  • TextureInput -> sampler2D oder samplerCube, je nachdem, ob Texture oder CubeMapTexture in der Textur-Eigenschaft von TextureInput verwendet wird. Wenn Sie die Eigenschaft enabled auf false setzen, wird dem Shader eine Dummy-Textur präsentiert, d.h. der Shader funktioniert zwar noch, tastet aber eine Textur mit undurchsichtigem schwarzen Bildinhalt ab. Achten Sie darauf, dass Eigenschaften für Sampler immer auf ein TextureInput Objekt verweisen müssen, nicht direkt auf ein Texture. Was die Texture Eigenschaften betrifft, so sind die Quelle, die Kacheln und die Filterung die einzigen, die implizit bei den Effekten berücksichtigt werden, während der Rest (z. B. UV-Transformationen) von den benutzerdefinierten Shadern nach eigenem Ermessen implementiert werden muss.

Hinweis: Wenn eine Uniform, auf die im Shader-Code verwiesen wird, keine entsprechende Eigenschaft hat, führt dies zu einem Shader-Kompilierungsfehler bei der Verarbeitung des Effekts zur Laufzeit. Es gibt einige Ausnahmen, wie z. B. Sampler-Uniformen, die eine Dummy-Textur gebunden bekommen, wenn keine entsprechende QML-Eigenschaft vorhanden ist, aber als allgemeine Regel gilt, dass alle Uniformen und Sampler eine entsprechende Eigenschaft im Effektobjekt haben müssen.

Erste Schritte mit benutzerdefinierten Effekten

Zu einem benutzerdefinierten Nachbearbeitungseffekt gehören mindestens ein Effektobjekt und ein Fragment-Shader-Snippet. Einige Effekte benötigen auch einen angepassten Vertex-Shader.

Als einfaches Beispiel wollen wir einen Effekt erstellen, der den Inhalt der Szene mit einem Bild kombiniert und gleichzeitig den Wert des roten Kanals auf animierte Weise verändert:

Effect {
    id: simpleEffect
    property TextureInput tex: TextureInput {
        texture: Texture { source: "image.png" }
    }
    property real redLevel
    NumberAnimation on redLevel { from: 0; to: 1; duration: 5000; loops: -1 }
    passes: Pass {
       shaders: Shader {
           stage: Shader.Fragment
           shader: "effect.frag"
       }
    }
}
void MAIN()
{
    vec4 c = texture(tex, TEXTURE_UV);
    c.r *= redLevel;
    FRAGCOLOR = c * texture(INPUT, INPUT_UV);
}

Hier ist die Textur mit dem Bild image.png dem Shader unter dem Namen tex ausgesetzt. Der Wert von redLevel ist im Shader in einer float uniform mit dem gleichen Namen verfügbar.

Der Fragment-Shader muss eine Funktion namens MAIN enthalten. Die endgültige Fragmentfarbe wird durch FRAGCOLOR bestimmt. Die Haupteingabetextur mit dem Inhalt der Szene von View3D ist unter einem sampler2D mit dem Namen INPUT zugänglich. Die UV-Koordinaten aus dem Quad stehen in INPUT_UV. Diese UV-Werte sind immer für das Sampling von INPUT geeignet, unabhängig von der zugrunde liegenden Grafik-API zur Laufzeit (und damit unabhängig von der Y-Achsenrichtung in Bildern, da die notwendigen Anpassungen automatisch von Qt Quick 3D vorgenommen werden). Die Abtastung der Textur mit unserem externen Bild erfolgt mit TEXTURE_UV. INPUT_UV ist für plattformübergreifende Anwendungen nicht geeignet, da V gespiegelt werden muss, um die zuvor erwähnten Unterschiede im Koordinatensystem auszugleichen, wobei eine Logik verwendet wird, die für Texturen auf der Grundlage von Bildern und Texturen, die als Renderziele verwendet werden, unterschiedlich ist. Glücklicherweise wird dies alles von der Engine übernommen, so dass der Shader dafür keine weitere Logik benötigt.

Sobald simpleEffect verfügbar ist, kann es mit der Effektliste des View3D's SceneEnvironment verbunden werden:

environment: SceneEnvironment {
    effects: [ simpleEffect ]
}

Das Ergebnis würde in etwa wie folgt aussehen, mit der Originalszene auf der linken Seite und mit dem angewandten Effekt auf der rechten Seite:

Hinweis: Der Eigenschaftswert shader in Shader ist eine URL, wie es in QML und Qt Quick üblich ist, und verweist auf die Datei, die das Shader-Snippet enthält, und funktioniert ganz ähnlich wie ShaderEffect oder Image.source. Es werden nur die Schemata file und qrc unterstützt. Es ist auch möglich, das file Schema wegzulassen, was es erlaubt, einen relativen Pfad auf bequeme Art und Weise anzugeben. Ein solcher Pfad wird relativ zum Speicherort der Komponente (der Datei .qml ) aufgelöst.

Hinweis: Shader-Code wird immer mit GLSL im Vulkan-Stil bereitgestellt, unabhängig von der Grafik-API, die von Qt zur Laufzeit verwendet wird.

Hinweis: Der Vertex- und Fragment-Shader-Code, der durch den Effekt bereitgestellt wird, ist kein vollständiger GLSL-Shader für sich. Vielmehr stellen sie eine MAIN Funktion und optional einen Satz von VARYING Deklarationen zur Verfügung, die dann von der Engine mit weiterem Shader-Code ergänzt werden.

Hinweis: Das obige Beispiel ist nicht mit dem optionalen Multiview-Rendering-Modus kompatibel, 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, sofern vorhanden, muss eine Funktion namens MAIN bereitstellen. In den meisten Fällen wird der benutzerdefinierte Vertex-Shader keine eigene Berechnung der homogenen Scheitelpunktposition bereitstellen wollen, aber es ist möglich, POSITION, VERTEX und MODELVIEWPROJECTION_MATRIX zu verwenden. Wenn POSITION im Code des benutzerdefinierten Shaders nicht vorhanden ist, wird eine Anweisung, die POSITION = MODELVIEWPROJECTION_MATRIX * vec4(VERTEX, 1.0); entspricht, automatisch durch 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 Vertex-Ausgabe- oder Fragment-Eingabe-Deklaration umgewandelt. Der Fragment-Shader kann die gleiche Deklaration verwenden, die es dann ermöglicht, den interpolierten Wert für das aktuelle Fragment zu lesen.

Schauen wir uns ein Beispiel an, das dem eingebauten Effekt DistortionSpiral sehr ähnlich ist:

VARYING vec2 center_vec;
void MAIN()
{
    center_vec = INPUT_UV - vec2(0.5, 0.5);
    center_vec.y *= INPUT_SIZE.y / INPUT_SIZE.x;
}
VARYING vec2 center_vec;
void MAIN()
{
    float radius = 0.25;
    float dist_to_center = length(center_vec) / radius;
    vec2 texcoord = INPUT_UV;
    if (dist_to_center <= 1.0) {
        float rotation_amount = (1.0 - dist_to_center) * (1.0 - dist_to_center);
        float r = radians(360.0) * rotation_amount / 4.0;
        mat2 rotation = mat2(cos(r), sin(r), -sin(r), cos(r));
        texcoord = vec2(0.5, 0.5) + rotation * (INPUT_UV - vec2(0.5, 0.5));
    }
    FRAGCOLOR = texture(INPUT, texcoord);
}

Die Liste passes des Effektobjekts sollte nun sowohl die Vertex- als auch die Fragment-Snippets angeben:

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 einen Vertex-Ausgang oder einen Fragment-Eingang, abhängig vom Typ des aktuellen Shaders.
  • MAIN - Diese Funktion muss immer in einem Effekt-Shader 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 Quads; die Eingabe für den Vertex-Shader. (nur Vertex-Shader)
  • INPUT - sampler2D oder sampler2DArray - Der Sampler für die Eingabetextur mit der darin gerenderten Szene, es sei denn, ein Pass leitet seine Eingabe über ein BufferInput -Objekt um; in diesem Fall bezieht sich INPUT auf die Textur des zusätzlichen Farbpuffers, auf die BufferInput verweist. Bei aktiviertem Multiview-Rendering, das für VR/AR-Anwendungen relevant sein kann, ist dies ein sampler2DArray, während die Eingabetextur zu einem 2D-Textur-Array wird.
  • INPUT_UV - vec2 - UV-Koordinaten für das Sampling INPUT.
  • TEXTURE_UV - vec2 - UV-Koordinaten für das Sampling einer Textur, deren Inhalt aus einer Bilddatei geladen wurde.
  • INPUT_SIZE - vec2 - Die Größe der INPUT Textur, in Pixeln.
  • OUTPUT_SIZE - vec2 - Die Größe des Ausgabepuffers, in Pixeln. Oftmals dasselbe wie INPUT_SIZE, es sei denn, der Pass gibt an einen zusätzlichen Puffer mit einem Größenmultiplikator aus.
  • FRAME - float - Ein Bildzähler, der nach jedem Bild in View3D inkrementiert wird.
  • DEPTH_TEXTURE - sampler2D - Eine Tiefentextur mit dem Inhalt des Tiefenpuffers mit den undurchsichtigen Objekten in der Szene. Wie bei CustomMaterial löst das Vorhandensein dieses Schlüsselworts im Shader die automatische Erzeugung der Tiefentextur aus.
  • VIEW_INDEX - uint - Bei aktiviertem Multiview-Rendering ist dies der aktuelle View-Index, der sowohl in Vertex- als auch in Fragment-Shadern verfügbar ist. Immer 0, wenn Multiview-Rendering nicht verwendet wird.

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 Rendering-Pass, der ein Quad in die Ausgabetextur des Passes zeichnet, während er 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 kommentierten Eigenschaften sind nicht erforderlich, wenn die gewünschten Werte mit den Standardwerten übereinstimmen.

Intern führt das Vorhandensein dieses Buffer-Objekts und seine Referenzierung durch die output -Eigenschaft eines Passes dazu, dass eine Textur mit einer Größe erzeugt wird, die der View3D entspricht, und damit der Größe der impliziten Eingangs- und Ausgangstexturen. Wenn dies nicht erwünscht ist, kann die Eigenschaft sizeMultiplier verwendet werden, um eine Zwischentextur mit einer anderen Größe zu erhalten. Dies kann dazu führen, dass die Uniformen INPUT_SIZE und OUTPUT_SIZE im Shader unterschiedliche Werte haben.

Standardmäßig kann sich der Effekt nicht darauf verlassen, dass Texturen ihren Inhalt zwischen Frames beibehalten. Wenn eine neue Zwischentextur erstellt wird, wird sie auf vec4(0.0) zurückgesetzt. Danach kann die gleiche Textur für einen anderen Zweck wiederverwendet werden. Daher sollten Effektdurchläufe immer in die gesamte Textur schreiben, ohne zu Beginn des Durchlaufs Annahmen über deren Inhalt zu treffen. Hiervon gibt es eine Ausnahme: Pufferobjekte mit bufferFlags, die auf Buffer.SceneLifetime gesetzt sind. Dies bedeutet, dass die Textur dauerhaft mit einem Durchlauf des Effekts verbunden ist und nicht für andere Zwecke wiederverwendet wird. Der Inhalt eines solchen Farbpuffers bleibt zwischen den Frames erhalten. Dies wird typischerweise in einem Ping-Pong-Verfahren in Effekten wie der Bewegungsunschärfe verwendet: Der erste Durchlauf nimmt den dauerhaften Puffer als Eingabe, zusätzlich zur Haupteingabetextur des Effekts, und gibt ihn in einen anderen Zwischenpuffer aus, während der zweite Durchlauf in den dauerhaften Puffer ausgibt. Auf diese Weise tastet der erste Durchlauf im ersten Bild eine leere (transparente) Textur ab, während er in den nachfolgenden Bildern die Ausgabe des zweiten Durchlaufs aus dem vorherigen Bild abtastet. Ein dritter Durchlauf kann dann die Eingabe des Effekts und die Ausgabe des zweiten Durchlaufs zusammenmischen.

Der Befehlstyp BufferInput wird verwendet, um benutzerdefinierte Texturpuffer für den Rendering-Durchgang freizugeben.

Um z. B. auf someBuffer in den Renderpass-Shadern unter dem Namen mySampler zuzugreifen, kann der Befehlsliste Folgendes hinzugefügt werden:

BufferInput { buffer: someBuffer; sampler: "mySampler" }

Wenn der Name sampler nicht angegeben wird, wird INPUT als Standard verwendet.

Puffer können nützlich sein, um Zwischenergebnisse zwischen Render-Passes zu teilen.

Um vorgeladene Texturen für den Effekt freizugeben, sollte stattdessen TextureInput verwendet werden. Diese können als Eigenschaften des Effekts selbst definiert werden und sind dann automatisch für die Shader über ihre Eigenschaftsnamen zugänglich.

property TextureInput tex: TextureInput {
    texture: Texture { source: "image.png" }
}

Hier ist tex ein gültiger Sampler in allen Shadern aller Durchläufe des Effekts.

Wenn es um einheitliche Werte von Eigenschaften geht, lesen alle Pässe des Effekts die gleichen Werte in ihren Shadern. Bei Bedarf ist es möglich, den Wert einer Uniform nur für einen bestimmten Pass zu überschreiben. Dies geschieht durch Hinzufügen des Befehls SetUniformValue zur Liste der Befehle für den Pass.

Hinweis: Der target des passspezifischen Uniformwert-Setzers kann sich nur auf einen Namen beziehen, der der Name einer Eigenschaft des Effekts ist. Er kann den Wert für die entsprechende Uniform einer Eigenschaft außer Kraft setzen, aber er kann keine neuen Uniformen einführen.

Überlegungen zur Leistung

Seien Sie sich des erhöhten Ressourcenverbrauchs und der möglicherweise verringerten Leistung bei der Verwendung von Nachbearbeitungseffekten bewusst. Genau wie bei Qt Quick layers und ShaderEffect ist das Rendern der Szene in eine Textur und die anschließende Verwendung dieser Textur zum Texturieren eines Vierecks keine billige Angelegenheit, insbesondere auf Low-End-Hardware mit begrenzter Fragmentverarbeitungsleistung. Die Menge des zusätzlich benötigten Grafikspeichers und die Erhöhung der GPU-Last hängen beide von der Größe der View3D ab (die auf eingebetteten Geräten ohne Fenstersystem oft so groß wie die Bildschirmauflösung ist). Multi-Pass-Effekte sowie die Anwendung mehrerer Effekte erhöhen die Ressourcen- und Leistungsanforderungen weiter.

Daher ist es sehr ratsam, bereits zu einem frühen Zeitpunkt im Entwicklungszyklus sicherzustellen, dass das Zielgerät und der Grafik-Stack in der Lage sind, die im Design der 3D-Szene enthaltenen Effekte bei der Bildschirmauflösung des Endprodukts zu bewältigen.

Bei Techniken, die dies erfordern, ist es zwar unvermeidlich, aber DEPTH_TEXTURE impliziert einen zusätzlichen Rendering-Durchgang, um den Inhalt dieser Textur zu generieren, was auf weniger leistungsfähiger Hardware ebenfalls ein Problem darstellen kann. Verwenden Sie daher DEPTH_TEXTURE in den Shadern des Effekts nur, wenn es unbedingt erforderlich ist.

Die Komplexität der Operationen in den Shadern ist ebenfalls wichtig. 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 im Spiel sind. Ein Multiplikator von 4 bedeutet beispielsweise, dass eine Textur erstellt und dann gerendert wird, die viermal so groß ist wie die View3D. Genau wie bei Shadow Maps 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 aufwiegen.

VR/AR-Überlegungen

Bei der Entwicklung von Anwendungen für virtuelle oder erweiterte Realität unter Verwendung von Qt Quick 3D XR sind Nachbearbeitungseffekte funktionsfähig und können verwendet werden. Designer und Entwickler sollten jedoch besonders darauf achten, welche Effekte in einer Virtual-Reality-Umgebung sinnvoll sind und welche nicht. Einige Effekte, einschließlich einiger der in ExtendedSceneEnvironment integrierten Effekte oder des veralteten Effektmoduls, führen in einer VR-Umgebung nicht zu einem guten visuellen Erlebnis und können den Benutzer sogar physisch beeinträchtigen (z. B. durch Bewegungskrankheit oder Schwindel).

Wenn der effizientere Multiview-Rendering-Modus in einer VR/AR-Anwendung aktiviert ist, gibt es keinen separaten Render-Durchgang für die Inhalte des linken und rechten Auges. Stattdessen wird alles in einem Durchgang gerendert, wobei ein 2D-Textur-Array mit zwei Ebenen anstelle von zwei unabhängigen 2D-Texturen verwendet wird. Das bedeutet auch, dass viele Zwischenpuffer, d. h. Farb- oder Tiefentexturen, in diesem Modus zu Texturanordnungen werden müssen. Dies hat wiederum Auswirkungen auf benutzerdefinierte Materialien und Nachbearbeitungseffekte. Texturen wie die Eingabetextur (INPUT), die Tiefentextur (DEPTH_TEXTURE), die Bildschirmtextur (SCREEN_TEXTURE) und einige andere werden zu 2D-Texturarrays, die im Shader als sampler2DArray statt sampler2D dargestellt werden. Dies hat Auswirkungen auf GLSL-Funktionen wie texture(), textureLod() oder textureSize(). Die UV-Koordinate ist dann ein vec3, nicht ein vec2. TextureSize() hingegen gibt einen vec3 zurück, nicht einen vec2. Effekte, die unabhängig vom Rendering-Modus funktionieren sollen, können mit einer 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);
#endif

Siehe auch Shader, Pass, Buffer, BufferInput und Qt Quick 3D - Beispiel für benutzerdefinierte Effekte.

Dokumentation der Eigenschaften

passes : list [read-only]

Enthält eine Liste der vom Effekt implementierten Renderer passes.


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