Qt Quick 3D - Beispiel für benutzerdefinierte Effekte

Demonstriert das Schreiben von benutzerdefinierten Nachbearbeitungseffekten.

Das Beispiel implementiert seine eigenen benutzerdefinierten Post-Processing-Effekte, die dann über SceneEnvironment::effects auf die Szene angewendet werden. Es demonstriert sowohl die einfachste Art von Effekten, die nur über einen Fragment-Shader verfügen, als auch den fortgeschritteneren Fall, bei dem sowohl ein Vertex- als auch ein Fragment-Shader vorhanden sind, wobei die Daten zwischen den beiden weitergegeben werden.

Der einfache Effekt verwendet nur einen einzelnen Fragment-Shader und fügt eine Textureingabe aus einer Bilddatei hinzu:

Effect {
    id: eff1
    property TextureInput tex: TextureInput {
        id: qtLogo
        texture: Texture { source: "qt_logo_rect.png" }
    }
    passes: Pass {
        shaders: Shader {
            id: fs1
            stage: Shader.Fragment
            shader: "effect.frag"
        }
    }
}

Dieser Effekt verwendet einen sehr einfachen Fragment-Shader, der lediglich die Eingabetextur mit der Szene nimmt und sie mit der Bildtextur multipliziert:

void MAIN()
{
    vec4 c = texture(tex, TEXTURE_UV);
    FRAGCOLOR = c * texture(INPUT, INPUT_UV);
}

Die Shader-Schnipsel in den Dateien .vert und .frag werden unter Verwendung der eingebauten Schlüsselwörter geschrieben, wie in der Dokumentation Effect beschrieben. Benutzerdefinierte Eigenschaften mit Basistypen sowie Eigenschaften mit dem Typ TextureInput werden den Shadern automatisch als Uniformen und Sampler zur Verfügung gestellt.

Der zweite Effekt ist etwas komplexer. Er spezifiziert sowohl einen Vertex- als auch einen Fragment-Shader, sowie zwei Eigenschaften: uRed und uGreen, mit einer Animation auf uRed:

Effect {
    id: eff2
    property real uRed: 0.0
    SequentialAnimation {
        running: radioEff2.checked || radioEff3.checked
        loops: Animation.Infinite
        NumberAnimation { target: eff2; property: "uRed"; from: 0; to: 1; duration: 2000 }
        NumberAnimation { target: eff2; property: "uRed"; from: 1; to: 0; duration: 2000 }
    }
    property real uGreen: 1.0
    Shader {
        id: vs2
        stage: Shader.Vertex
        shader: "effect2.vert"
    }
    Shader {
        id: fs2
        stage: Shader.Fragment
        shader: "effect2.frag"
    }
    passes: Pass {
        shaders: [ vs2, fs2 ]
    }
}

Der Fragment-Shader für diesen Effekt erzeugt eine Verzerrung durch Änderung der Abtastkoordinaten. Für die Berechnung wird center_vec verwendet, das aus dem Fragment-Shader stammt. Schließlich passt der Shader die Farbe mithilfe der Uniformen uRed und uGreen an. Beachten Sie, dass diese Uniformen nicht im Shader deklariert werden müssen:

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;
        float cos_r = cos(r);
        float sin_r = sin(r);
        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));
    }
    vec4 c = texture(INPUT, texcoord);
    c.r *= uRed;
    c.g *= uGreen;
    FRAGCOLOR = c;
}

Beispielprojekt @ code.qt.io

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