CustomMaterial QML Type

Basiskomponente zur Erstellung von benutzerdefinierten Materialien, die zur Schattierung von Modellen verwendet werden. Mehr...

Import Statement: import QtQuick3D
Inherits:

Material

Eigenschaften

Detaillierte Beschreibung

Das benutzerdefinierte Material ermöglicht die Verwendung von benutzerdefiniertem Shader-Code für ein Material, was die Programmierbarkeit auf Grafik-Shader-Ebene ermöglicht. Es können ein Vertex-, ein Fragment- oder beide Shader bereitgestellt werden. Die Eigenschaften vertexShader und fragmentShader sind URLs, die auf Dateien verweisen, die Shader-Snippets enthalten, und funktionieren ganz ähnlich wie ShaderEffect oder Image.source. Bei benutzerdefinierten Materialien werden nur die Schemata file und qrc unterstützt. Es ist auch möglich, das Schema file wegzulassen, um auf bequeme Weise einen relativen Pfad anzugeben. Ein solcher Pfad wird relativ zum Speicherort der Komponente (der Datei .qml ) aufgelöst.

Eine Anleitung für den Einstieg in benutzerdefinierte Materialien finden Sie auf der Seite Programmierbare Materialien, Effekte, Geometrie und Texturdaten.

Einführung

Betrachten Sie die folgenden Versionen der gleichen Szene. Auf der linken Seite verwendet der Zylinder ein eingebautes, nicht programmierbares Material. Solche Materialien sind durch eine Vielzahl von Eigenschaften konfigurierbar, aber es gibt keine weitere Kontrolle über die Shader, die unter der Haube erzeugt werden. Auf der rechten Seite ist derselbe Zylinder nun mit einem CustomMaterial verknüpft, das auf die von der Anwendung bereitgestellten Vertex- und Fragment-Shader-Snippets verweist. Dies ermöglicht das Einfügen benutzerdefinierter, anwendungsspezifischer Logik in den Vertex-Shader, um die Geometrie zu transformieren und bestimmte Farbeigenschaften auf benutzerdefinierte Weise im Fragment-Shader zu bestimmen. Da es sich um ein shaded benutzerdefiniertes Material handelt, nimmt der Zylinder weiterhin normal an der Beleuchtung der Szene teil.

View3D {
    anchors.fill: parent
    PerspectiveCamera {
        id: camera
        position: Qt.vector3d(0, 0, 600)
    }
    camera: camera
    DirectionalLight {
        position: Qt.vector3d(-500, 500, -100)
        color: Qt.rgba(0.2, 0.2, 0.2, 1.0)
        ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0)
    }
    Model {
        source: "#Cylinder"
        eulerRotation: Qt.vector3d(30, 30, 0)
        scale: Qt.vector3d(1.5, 1.5, 1.5)
        materials: [
            DefaultMaterial {
                diffuseColor: Qt.rgba(0, 1, 0, 1)
            }
        ]
    }
}
View3D {
    anchors.fill: parent
    PerspectiveCamera {
        id: camera
        position: Qt.vector3d(0, 0, 600)
    }
    camera: camera
    DirectionalLight {
        position: Qt.vector3d(-500, 500, -100)
        color: Qt.rgba(0.2, 0.2, 0.2, 1.0)
        ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0)
    }
    Model {
        source: "#Cylinder"
        eulerRotation: Qt.vector3d(30, 30, 0)
        scale: Qt.vector3d(1.5, 1.5, 1.5)
        materials: [
            CustomMaterial {
                vertexShader: "material.vert"
                fragmentShader: "material.frag"
                property real uTime
                property real uAmplitude: 50
                NumberAnimation on uTime { from: 0; to: 100; duration: 10000; loops: -1 }
            }
        ]
    }
}

Nehmen wir an, dass die Shader-Snippets in material.vert und material.frag die folgenden sind:

void MAIN()
{
    VERTEX.x += sin(uTime + VERTEX.y) * uAmplitude;
}
void MAIN()
{
    BASE_COLOR = vec4(0.0, 1.0, 0.0, 1.0);
}

Beachten Sie, dass uTime und uAmplitude Eigenschaften des CustomMaterial-Elements sind. Sie können Werte ändern und normal animiert werden. Die Werte werden den Shadern automatisch und ohne weiteres Zutun des Entwicklers zur Verfügung gestellt.

Das Ergebnis ist ein Zylinder, der seine Scheitelpunkte animiert:

Zwei Arten von benutzerdefinierten Materialien

Es gibt zwei Haupttypen von benutzerdefinierten Materialien. Dies wird durch die Eigenschaft shadingMode festgelegt. Bei unshaded benutzerdefinierten Materialien gibt der Fragment-Shader eine einzelne vec4 Farbe aus und ignoriert Lichter, Lichtsonden und Schatten in der Szene. Bei shaded materials wird vom Shader erwartet, dass er bestimmte Funktionen implementiert und mit eingebauten Variablen arbeitet, um Licht- und Schattenbeiträge zu berücksichtigen.

Die Standardwahl ist normalerweise ein schattiertes Material, was sich im Standardwert der Eigenschaft shadingMode widerspiegelt. Dies passt zu Materialien, die Scheitelpunkte oder andere eingehende Daten aus der Geometrie transformieren oder Werte wie BASE_COLOR oder EMISSIVE_COLOR auf eine benutzerdefinierte Weise bestimmen müssen, vielleicht durch Abtasten von SCREEN_TEXTURE oder DEPTH_TEXTURE, während sie weiterhin Licht- und Schattenbeiträge aus der Szene erhalten. Darüber hinaus können solche Materialien auch die Gleichungen außer Kraft setzen und neu implementieren, die zur Berechnung der Beiträge von gerichteten, punktförmigen und anderen Lichtern verwendet werden. Die von der Anwendung bereitgestellten Shader-Snippets werden von der Qt Quick 3D -Engine unter der Haube stark abgeändert, um die Funktionen, wie z. B. die Beleuchtung, der Standardmaterialien bereitzustellen.

Nicht schattierte Materialien sind nützlich, wenn das Aussehen des Objekts vollständig durch den benutzerdefinierten Shader-Code bestimmt wird. Die Shader für solche Materialien erhalten nur minimale Ergänzungen durch die Engine, so dass es vollständig dem Shader überlassen bleibt, die endgültige Fragmentfarbe zu bestimmen. Dies bietet mehr Freiheit, schränkt aber auch die Möglichkeiten zur Integration mit anderen Elementen der Szene, wie z. B. Lichtern, ein.

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 vom Material bereitgestellt wird, ist kein vollständiger GLSL-Shader für sich. Vielmehr stellen sie eine Reihe von Funktionen bereit, die dann von der Engine mit weiterem Shader-Code ergänzt werden.

Freigabe von Daten an die Shader

Die dynamischen Eigenschaften des CustomMaterials können mit Hilfe von QML- und Qt Quick -Funktionen geändert und animiert werden, und die Werte werden automatisch an die Shader weitergegeben. In der Praxis ist dies ShaderEffect sehr ähnlich. Die folgende Liste zeigt, wie die Eigenschaften abgebildet werden:

  • bool, int, real -> bool, int, float
  • QColor, color -> vec4, und die Farbe wird in den linearen, angenommenen sRGB-Raum für den in QML angegebenen Farbwert konvertiert. 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 CustomMaterial mit diesen übereinstimmt. Im Gegensatz zu Qt Quick ist die Linearisierung für Qt Quick 3D unerlässlich, da in der Regel ein Tonemapping in der 3D-Szene durchgeführt wird.
  • QRect, QRectF, rect -> vec4
  • QPoint, QPointF, point, QSize, QSizeF, size -> vec2
  • QVector2D, vector2d -> vec2
  • 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, nimmt aber eine Textur mit undurchsichtigem schwarzem Bildinhalt auf. 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 bei benutzerdefinierten Materialien implizit berücksichtigt werden, während der Rest (z. B. UV-Transformationen) von den benutzerdefinierten Shadern nach eigenem Ermessen implementiert werden kann.

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 Materials 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 CustomMaterial-Objekt deklariert haben müssen.

Unschattierte benutzerdefinierte Materialien

Im Folgenden finden Sie ein Beispiel für ein benutzerdefiniertes Material von unshaded.

CustomMaterial {
    // These properties are automatically exposed to the shaders
    property real time: 0.0
    property real amplitude: 5.0
    property real alpha: 1.0
    property TextureInput tex: TextureInput {
        enabled: true
        texture: Texture { source: "image.png" }
    }

    shadingMode: CustomMaterial.Unshaded
    sourceBlend: alpha < 1.0 ? CustomMaterial.SrcAlpha : CustomMaterial.NoBlend
    destinationBlend: alpha < 1.0 ? CustomMaterial.OneMinusSrcAlpha : CustomMaterial.NoBlend
    cullMode: CustomMaterial.BackFaceCulling

    vertexShader: "customshader.vert"
    fragmentShader: "customshader.frag"
}

Mit dem obigen Beispiel könnten die unshaded Vertex- und Fragment-Shader-Schnipsel wie folgt aussehen. Beachten Sie, dass die Shader keine Uniformen oder Vertex-Eingänge deklarieren müssen, da dies von Qt beim Zusammensetzen des endgültigen Shader-Codes erledigt wird.

VARYING vec3 pos;
VARYING vec2 texcoord;

void MAIN()
{
    pos = VERTEX;
    pos.x += sin(time * 4.0 + pos.y) * amplitude;
    texcoord = UV0;
    POSITION = MODELVIEWPROJECTION_MATRIX * vec4(pos, 1.0);
}
VARYING vec3 pos;
VARYING vec2 texcoord;

void MAIN()
{
    vec4 c = texture(tex, texcoord);
    FRAGCOLOR = vec4(pos.x * 0.02, pos.y * 0.02, pos.z * 0.02, alpha) * c;
}

Die folgenden speziellen, in Großbuchstaben geschriebenen Schlüsselwörter sind verfügbar:

  • MAIN -> der Name des Einstiegspunktes im Vertex- oder Fragment-Shader-Snippet muss immer MAIN lauten. Die Bereitstellung dieser Funktion ist in Shader-Snippets für nicht schattierte benutzerdefinierte Materialien obligatorisch.
  • VARYING -> deklariert eine Ausgabe des Vertex-Shaders oder eine Eingabe für den Fragment-Shader
  • POSITION -> vec4, die Ausgabe des Vertex-Shaders
  • FRAGCOLOR -> vec4, die Ausgabe des Fragment-Shaders. Nur für nicht schattierte benutzerdefinierte Materialien verfügbar.
  • VERTEX -> vec3, die Vertex-Position im Vertex-Shader.
  • NORMAL -> vec3, die Vertexnormale im Vertexshader. Wenn das Mesh für das zugehörige Modell keine Normalen bereitstellt, ist der Wert vec3(0.0).
  • UV0 -> vec2, der erste Satz von Texturkoordinaten im Vertex-Shader. Wenn das Netz des zugehörigen Modells keine Texturkoordinaten bereitstellt, ist der Wert vec2(0.0).
  • UV1 -> vec2, der zweite Satz von Texturkoordinaten im Vertex-Shader. Wenn das Netz des zugehörigen Modells keinen zweiten Satz von Texturkoordinaten bereitstellt, ist der Wert vec2(0.0).
  • COLOR -> vec4, die Scheitelfarbe im Vertex-Shader. Wenn das Netz für das verknüpfte Modell keine Farben pro Scheitelpunkt bereitstellt, ist der Wert vec4(1.0).
  • TANGENT -> vec3, die Tangente im Vertex-Shader. Wenn das Mesh für das verknüpfte Modell keine Tangentialdaten bereitstellt, ist der Wert vec3(0.0).
  • BINORMAL -> vec3, binormal im Vertex-Shader. Wenn das Netz für das zugehörige Modell keine binormalen Daten bereitstellt, ist der Wert vec3(0.0).
  • JOINTS -> ivec4, Gelenkindizes im Vertex-Shader. Wenn das Netz für das verknüpfte Modell keine Joint-Indexdaten bereitstellt, ist der Wert ivec4(0).
  • WEIGHTS -> vec4, Gelenkgewichte im Vertex-Shader. Wenn das Mesh für das zugehörige Modell keine Joint-Weights-Daten bereitstellt, ist der Wert vec4(0.0).
  • MORPH_POSITION(n) -> vec3, die n+1teMorph-Zielposition im Vertex-Shader. Das zugehörige Modell sollte die richtigen Daten liefern.
  • MORPH_NORMAL(n) -> vec3, die n+1-teMorph-Zielnormale im Vertex-Shader. Das zugehörige Modell sollte die richtigen Daten liefern.
  • MORPH_TANGENT(n) -> vec3, die n+1-teMorph-Ziel-Tangente im Vertex-Shader. Das zugehörige Modell sollte die richtigen Daten liefern.
  • MORPH_BINORMAL(n) -> vec3, das n+1-teMorph-Ziel binormal im Vertex-Shader. Das zugehörige Modell sollte die richtigen Daten liefern.
  • MODELVIEWPROJECTION_MATRIX -> mat4, die Model-View-Projektionsmatrix. Projektionsmatrizen folgen immer den OpenGL-Konventionen, mit einer eingebrannten Transformation für die Y-Achsenrichtung und die Cliptiefe, abhängig von der zur Laufzeit verwendeten Grafik-API.
  • VIEWPROJECTION_MATRIX -> mat4, die Ansichtsprojektionsmatrix
  • PROJECTION_MATRIX -> mat4, die Projektionsmatrix
  • INVERSE_PROJECTION_MATRIX -> mat4, die inverse Projektionsmatrix
  • VIEW_MATRIX -> mat4, die Ansichtsmatrix (Kamera)
  • MODEL_MATRIX -> mat4, die Modellmatrix (Welt)
  • NORMAL_MATRIX -> mat3, die normale Matrix (die Transponierung der Inverse des oberen linken 3x3 Teil des Modells Matrix)
  • BONE_TRANSFORMS -> mat4[], das Array der Knochenmatrixen des Modells
  • BONE_NORMAL_TRANSFORMS -> mat3[], das Array des Modells Knochen normale Matrizen (die Transponierung der Inverse des oberen linken 3x3 Teil der einzelnen Knochenmatrizen)
  • MORPH_WEIGHTS -> float[], das Array der Morph-Gewichte. Das zugehörige Modell sollte die richtigen Daten liefern. Zur Sicherheit wird QT_MORPH_MAX_COUNT auf die Größe dieses Arrays festgelegt.
  • CAMERA_POSITION -> vec3, die Kameraposition im Weltraum
  • CAMERA_DIRECTION -> vec3, der Richtungsvektor der Kamera
  • CAMERA_PROPERTIES -> vec2, die Nah- und Fern-Clipwerte für die Kamera
  • POINT_SIZE -> Float, nur im Vertex-Shader beschreibbar. Beim Rendern von Geometrie mit einer Topologie aus Punkten muss der benutzerdefinierte Vertex-Shader diesen Wert entweder auf 1,0 oder einen anderen Wert setzen, sowohl in schattierten als auch in nicht schattierten benutzerdefinierten Materialien. Siehe PrincipledMaterial::pointSize für weitere Hinweise zur Unterstützung von anderen Größen als 1.

Schattierte benutzerdefinierte Materialien

Ein shaded Material augments den Shader-Code, der von einem PrincipledMaterial generiert werden würde. Im Gegensatz zu nicht schattierten Materialien, die fast die gesamte Logik für die Vertex- und Fragment-Shader-Hauptfunktionen selbst bereitstellen, verhindern sie das Hinzufügen von generiertem Code für Beleuchtung, Schattenwurf, globale Beleuchtung usw., lassen schattierte Materialien die Shader-Generierung ganz normal ablaufen, so als wäre das CustomMaterial ein PrincipledMaterial. Von den Vertex- und Fragment-Shader-Snippets wird erwartet, dass sie optionale Funktionen bereitstellen, die dann an bestimmten Punkten aufgerufen werden und ihnen die Möglichkeit geben, die Farben und andere Werte anzupassen, die dann für die Berechnung der Beleuchtung und der endgültigen Fragmentfarbe verwendet werden.

Anstatt nur eine MAIN Funktion zu implementieren, kann der Fragment-Shader für ein schattiertes benutzerdefiniertes Material mehrere Funktionen implementieren. Alle Funktionen, einschließlich MAIN, sind optional in schattierten benutzerdefinierten Materialien zu implementieren. Ein leeres Shader-Snippet oder sogar das Fehlen der Eigenschaften vertexShader oder fragmentShader kann ebenfalls vollkommen gültig sein.

Vertex-Shader-Snippets in einem schattierten benutzerdefinierten Material

Die folgenden Funktionen können in einem Vertex-Shader-Snippet implementiert werden:

  • void MAIN() Wenn vorhanden, wird diese Funktion aufgerufen, um den Wert von POSITION, der vec4-Ausgabe des Vertex-Shaders, zu setzen und optional die Werte von VERTEX, COLOR, NORMAL, UV0, UV1, TANGENT, BINORMAL, JOINTS und WEIGHTS zu ändern. Anders als bei nicht schattierten Materialien ist das Schreiben in diese sinnvoll, da die geänderten Werte dann im restlichen generierten Shader-Code berücksichtigt werden (während bei nicht schattierten Materialien kein zusätzlicher Shader-Code generiert wird). Wenn der benutzerdefinierte Scheitelpunkt-Shader beispielsweise die Scheitelpunkte oder die Normalen verschiebt, wird er die geänderten Werte auf VERTEX oder NORMAL speichern wollen, um anschließend korrekte Beleuchtungsberechnungen durchzuführen. Außerdem kann die Funktion in Variablen schreiben, die mit VARYING definiert wurden, um interpolierte Daten an den Fragment-Shader zu übergeben. Wenn diese Funktion oder eine Neudefinition von POSITION nicht vorhanden ist, wird POSITION auf der Grundlage von VERTEX und MODELVIEWPROJECTION_MATRIX berechnet, genau wie es ein PrincipledMaterial tun würde.

    Beispiel, bei dem sowohl auf QML-Eigenschaften, die als Uniformen dargestellt werden, als auch auf die Übergabe von Daten an den Fragment-Shader zurückgegriffen wird:

    VARYING vec3 vNormal;
    VARYING vec3 vViewVec;
    
    void MAIN()
    {
        VERTEX.x += sin(uTime * 4.0 + VERTEX.y) * uAmplitude;
        vNormal = normalize(NORMAL_MATRIX * NORMAL);
        vViewVec = CAMERA_POSITION - (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
        POSITION = MODELVIEWPROJECTION_MATRIX * vec4(VERTEX, 1.0);
    }

    Hinweis: Im obigen Beispiel ist die Zuweisung eines Wertes an POSITION optional, da die Verwendung in diesem Fall mit dem Standardverhalten identisch ist.

Hinweis: Um Daten ohne Interpolation vom Scheitelpunkt an die Fragmentstufe zu übergeben, fügen Sie das Schlüsselwort flat vor dem Typ in den VARYING -Deklarationen hinzu.

Fragment-Shader-Snippets in einem schattierten benutzerdefinierten Material

Die folgenden Funktionen können in einem Fragment-Shader-Snippet implementiert werden:

  • void MAIN() Wenn vorhanden, wird diese Funktion aufgerufen, um die Werte der speziellen beschreibbaren Variablen BASE_COLOR, METALNESS, ROUGHNESS, SPECULAR_AMOUNT, NORMAL, CLEARCOAT_FRESNEL_POWER, CLEARCOAT_FRESNEL_SCALE, CLEARCOAT_FRESNEL_BIAS zu setzen, CLEARCOAT_AMOUNT, CLEARCOAT_ROUGHNESS, CLEARCOAT_NORMAL, FRESNEL_BIAS, FRESNEL_SCALE, FRESNEL_POWER, IOR, TRANSMISSION_FACTOR, THICKNESS_FACTOR, ATTENUATION_COLOR, ATTENUATION_DISTANCE und OCCLUSION_AMOUNT.

    Ein häufiger Anwendungsfall ist die Festlegung des Wertes von BASE_COLOR auf der Grundlage der Abtastung einer Textur, sei es eine Basisfarbkarte, SCREEN_TEXTURE oder eine andere Art von Quelle. Dies kann insbesondere dann relevant und praktisch sein, wenn keine eigenen Lichtprozessorfunktionen implementiert sind. Die Einstellung von BASE_COLOR.a auf einen anderen Wert als den Standardwert 1.0 ermöglicht es, den endgültigen Alphawert des Fragments zu beeinflussen. (Beachten Sie, dass dies oft auch die Aktivierung von Alpha-Blending in sourceBlend und destinationBlend erfordert)

    Ein weiteres Szenario ist, wenn keine benutzerdefinierte SPECULAR_LIGHT Funktion zur Verfügung steht oder wenn eine Lichtsonde in SceneEnvironment eingestellt ist. Die Metallizität, Rauheit und andere Werte, die die Berechnung des Spiegelungsbeitrags beeinflussen, können in MAIN auf die gewünschten benutzerdefinierten Werte eingestellt werden.

    Die Funktion kann in die folgenden speziellen Variablen schreiben. Die Werte, die in diese Variablen geschrieben werden, sind normalerweise entweder fest kodiert oder werden auf der Grundlage von QML-Eigenschaften berechnet, die auf Uniformen abgebildet werden. Die Semantik ist identisch mit PrincipledMaterial.

    • vec4 BASE_COLOR - Der Basisfarb- und Materialalphawert. Entspricht built-in materials' color property. Wenn keine Lichtprozessorfunktionen implementiert sind, kann es praktisch sein, eine benutzerdefinierte Grundfarbe in MAIN zu setzen, da diese dann bei den Standardbeleuchtungsberechnungen berücksichtigt wird. Der Standardwert ist vec4(1.0), d. h. Weiß mit einem Alpha-Wert von 1,0. Der Alphawert wirkt sich auf den endgültigen Alphawert des Fragments aus. Der endgültige Alphawert ist die Deckkraft des Objekts (Modells) multipliziert mit der Grundfarbe Alpha. Wenn Sie den Wert direkt im Shader-Code angeben und sich nicht auf einheitliche Werte verlassen, die aus den Farbeigenschaften in QML hervorgehen, sollten Sie sich darüber im Klaren sein, dass es dem Shader obliegt, die Konvertierung von sRGB in linear vorzunehmen, falls erforderlich. Unter der Annahme von vec3 color und float alpha kann dies zum Beispiel wie folgt erreicht werden:
      float C1 = 0.305306011;
      vec3 C2 = vec3(0.682171111, 0.682171111, 0.682171111);
      vec3 C3 = vec3(0.012522878, 0.012522878, 0.012522878);
      BASE_COLOR = vec4(rgb * (rgb * (rgb * C1 + C2) + C3), alpha);
    • vec3 EMISSIVE_COLOR - Die Farbe der Selbstbeleuchtung. Entspricht der Emissionsfarbe der eingebauten Materialien, die durch built-in materials's emissiveFactor property und built-in materials's emissiveMap property kombiniert wird. Der Standardwert ist vec3(0.0). Wenn Sie den Wert direkt im Shader-Code angeben und sich nicht auf einheitliche Werte verlassen, die aus den Farbeigenschaften in QML hervorgehen, sollten Sie sich darüber im Klaren sein, dass es dem Shader obliegt, die Konvertierung von sRGB in linear vorzunehmen, falls erforderlich.
    • float IOR Gibt den Brechungsindex des Materials an. Ein typischer Wert und auch der Standardwert ist 1.5, da dies der Wert ist, den ein PrincipledMaterial verwenden würde.
    • float TRANSMISSION_FACTOR Legt den Betrag der Lichtdurchlässigkeit fest. Ein typischer Wert wäre 1.0 und die Vorgabe ist 0.0, da dies der Wert ist, den PrincipledMaterial verwenden würde.
    • float THICKNESS_FACTOR Legt die Stärke des durchscheinenden Materials fest. Ein typischer Wert wäre 10.0 und der Standardwert ist 0.0, da dies der Wert ist, den PrincipledMaterial verwenden würde.
    • vec3 ATTENUATION_COLOR Legt die Farbverschiebung des durchscheinenden Materials um die Entfernung fest. Ein typischer Wert wäre vec3(1.0, 0.0, 0.0) und auch der Standardwert ist vec3(1.0), da dies der Wert ist, den PrincipledMaterial verwenden würde.
    • float ATTENUATION_DISTANCE Legt die Abschwächung der Farbverschiebung des lichtdurchlässigen Materials in der Entfernung fest. Ein typischer Wert wäre 100.0 und die Vorgabe ist 0.0, da dies der Wert ist, den PrincipledMaterial verwenden würde.
    • float METALNESS Metalness-Wert im Bereich 0.0 - 1.0. Der Standardwert ist 0. Muss auf einen Wert ungleich Null gesetzt werden, um Wirkung zu zeigen.
    • float ROUGHNESS Rauhigkeitswert im Bereich 0.0 - 1.0. Der Standardwert ist 0.
    • float CLEARCOAT_FRESNEL_POWER Gibt die Fresnelkraft der Klarlackschicht an. Ein typischer Wert und auch der Standardwert ist 5.0, da dies der Wert ist, den PrincipledMaterial verwenden würde.
    • float CLEARCOAT_FRESNEL_SCALE Legt die Fresnel-Skala der Klarlackschicht fest. Ein typischer Wert und auch der Standardwert ist 1.0, da dies der Wert ist, den PrincipledMaterial verwenden würde.
    • float CLEARCOAT_FRESNEL_BIAS Legt die Fresnel-Bias der Klarlackschicht fest. Ein typischer Wert und auch der Standardwert ist 0.0, da dies der Wert ist, den PrincipledMaterial verwenden würde.
    • float CLEARCOAT_AMOUNT Legt die Menge der Klarlackschicht auf dem Material fest. Ein typischer Wert ist 1.0 und der Standardwert ist 0.0, da dies der Wert ist, der für PrincipledMaterial verwendet wird.
    • float CLEARCOAT_ROUGHNESS Legt die Rauheit der Klarlackschicht fest. Ein typischer Wert wäre 1.0 für eine vollständig unscharfe Klarlackschicht und auch die Voreinstellung ist 0.0, da dies der Wert ist, der für PrincipledMaterial verwendet würde.
    • vec3 CLEARCOAT_NORMAL - Die Normalen der Klarlackschicht, die aus dem Vertex-Shader im Weltraum stammen. Während diese Eigenschaft den gleichen Anfangswert wie VAR_WORLD_NORMAL hat, hat nur die Änderung des Wertes von CLEARCOAT_NORMAL eine Auswirkung auf die Normalen der Klarlackschicht.
    • Float FRESNEL_POWER Gibt die Fresnelleistung an. Ein typischer Wert und auch der Standardwert ist 5.0, da dies der Wert ist, den PrincipledMaterial verwenden würde.
    • float FRESNEL_SCALE Legt die Fresnel-Skala fest. Ein typischer Wert und auch der Standardwert ist 1.0, da dies der Wert ist, den PrincipledMaterial verwenden würde.
    • float FRESNEL_BIAS Legt den Fresnel-Bias fest. Ein typischer Wert und auch der Standardwert ist 0.0, da dies der Wert ist, den PrincipledMaterial verwenden würde.
    • float SPECULAR_AMOUNT Spiegelungsanteil im Bereich 0,0 - 1,0. Der Standardwert ist 0.5 und entspricht PrincipledMaterial::specularAmount. Muss auf einen Wert ungleich Null gesetzt werden, um Wirkung zu zeigen.
    • float OCCLUSION_AMOUNT Legt den AO-Faktor fest. Ein typischer Wert und auch der Standardwert ist 1.0, da dies der Wert ist, den PrincipledMaterial verwenden würde.
    • vec3 NORMAL - Die Normale, die vom Vertex-Shader im Weltraum kommt. Während diese Eigenschaft den gleichen Anfangswert wie VAR_WORLD_NORMAL hat, hat nur die Änderung des Wertes von NORMAL eine Auswirkung auf die Beleuchtung.
    • vec3 TANGENT - Die Tangente, die vom Vertex-Shader im Weltraum kommt. Dieser Wert wird möglicherweise für Doppelseitigkeit angepasst.
    • vec3 BINORMAL - Die Binormale, die vom Vertex-Shader im Weltraum kommt. Dieser Wert wird potenziell für Doppelseitigkeit angepasst.
    • vec2 UV0 - Der erste Satz von Texturkoordinaten aus dem Vertex-Shader. Diese Eigenschaft ist im Fragment-Shader schreibgeschützt.
    • vec2 UV1 - Der zweite Satz von Texturkoordinaten aus dem Vertex-Shader. Diese Eigenschaft ist im Fragment-Shader schreibgeschützt.

    Hinweis: Anders als bei nicht schattierten Materialien hat das Fragment MAIN für ein schattiertes Material keine direkte Kontrolle über FRAGCOLOR. Vielmehr sind es die in den Lichtprozessorfunktionen geschriebenen Werte DIFFUSE und SPECULAR, die über die endgültige Fragmentfarbe entscheiden. Wenn keine Lichtprozessorfunktion implementiert ist, werden die entsprechenden Standard-Schattierungsberechnungen wie bei PrincipledMaterial durchgeführt, wobei BASE_COLOR und andere Werte aus der obigen Liste berücksichtigt werden.

    Ein Beispiel für einen einfachen, metallischen benutzerdefinierten Material-Shader könnte folgendermaßen aussehen:

    void MAIN()
    {
        METALNESS = 1.0;
        ROUGHNESS = 0.5;
        FRESNEL_POWER = 5.0;
    }

    Ein weiteres Beispiel, bei dem die Grundfarbe und Alpha durch Sampling einer Textur festgelegt werden:

    VARYING vec2 texcoord;
    void MAIN()
    {
        BASE_COLOR = texture(uColorMap, texcoord);
    }
  • void AMBIENT_LIGHT() Wenn vorhanden, wird diese Funktion einmal für jedes Fragment aufgerufen. Die Aufgabe der Funktion ist es, den gesamten Umgebungsbeitrag zu einer beschreibbaren Spezialvariablen DIFFUSE zu addieren. Sie kann natürlich auch einen anderen Wert berechnen oder DIFFUSE überhaupt nicht berühren (um die Umgebungsbeleuchtung vollständig zu ignorieren). Wenn diese Funktion nicht vorhanden ist, wird der Umgebungslichtanteil normal berechnet, wie es eine PrincipledMaterial tun würde.

    Die Funktion kann in die folgenden speziellen Variablen schreiben:

    • vec3 DIFFUSE Addiert die diffusen Lichtanteile pro Fragment. Die Lichtprozessorfunktionen werden typischerweise (+=) dazu addieren, da durch das Überschreiben des Wertes der Beitrag anderer Lichter verloren gehen würde.

    Die Funktion kann die folgenden speziellen Variablen lesen, zusätzlich zu den Matrix- (z.B. MODEL_MATRIX) und Vektor- (z.B. CAMERA_POSITION) Uniformen aus der obigen Tabelle:

    • vec3 TOTAL_AMBIENT_COLOR Der gesamte Umgebungsbeitrag in der Szene.

    Beispiel:

    void AMBIENT_LIGHT()
    {
        DIFFUSE += TOTAL_AMBIENT_COLOR;
    }
  • void DIRECTIONAL_LIGHT() Wenn vorhanden, wird diese Funktion für jedes aktive Richtungslicht in der Szene für jedes Fragment aufgerufen. Die Aufgabe der Funktion ist es, den diffusen Beitrag zu einer beschreibbaren Spezialvariablen DIFFUSE hinzuzufügen. Die Funktion kann sich auch dafür entscheiden, nichts zu tun, in diesem Fall werden die diffusen Beiträge der Richtungslichter ignoriert. Wenn die Funktion überhaupt nicht vorhanden ist, werden die diffusen Beiträge von gerichteten Lichtern normal akkumuliert, wie es eine PrincipledMaterial tun würde.

    Die Funktion kann in die folgenden speziellen Variablen schreiben:

    • vec3 DIFFUSE Akkumuliert die diffusen Lichtbeiträge pro Fragment.
    • Die Lichtprozessorfunktionen addieren typischerweise (+=
    )
    • dazu, da durch das Überschreiben des Wertes die Beiträge anderer Lichter verloren gehen würden.

    Die Funktion kann die folgenden speziellen Variablen lesen, zusätzlich zu den Matrix- (z.B. MODEL_MATRIX

    )

    und Vektor- (z.B. CAMERA_POSITION) Uniformen aus der obigen Tabelle:

    • vec3 LIGHT_COLOR Diffuse Lichtfarbe.
    • float SHADOW_CONTRIB Schattenbeitrag, oder 1.0, wenn überhaupt kein Schatten vorhanden ist oder kein Schatten empfangen wird.
    • vec3 TO_LIGHT_DIR Vektor, der auf die Lichtquelle zeigt.
    • vec3 NORMAL Der Normalenvektor im Weltraum.
    • vec4 BASE_COLOR Die Grundfarbe und der Materialalphawert.
    • float METALNESS Der Metallanteil.
    • float ROUGHNESS Der Rauhigkeitsanteil.

    Beispiel:

    void DIRECTIONAL_LIGHT()
    {
        DIFFUSE += LIGHT_COLOR * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(VAR_WORLD_NORMAL), TO_LIGHT_DIR)));
    }
  • void POINT_LIGHT() Wenn vorhanden, wird diese Funktion für jedes aktive Punktlicht in der Szene für jedes Fragment aufgerufen. Die Aufgabe der Funktion ist es, den diffusen Beitrag zu einer beschreibbaren speziellen Variablen DIFFUSE hinzuzufügen. Die Funktion kann auch nichts tun, in diesem Fall werden die diffusen Beiträge der Punktlichter ignoriert. Wenn die Funktion nicht vorhanden ist, werden die diffusen Beiträge von Punktlichtern normal akkumuliert, wie es eine PrincipledMaterial tun würde.

    Die Funktion kann in die folgenden speziellen Variablen schreiben:

    • vec3 DIFFUSE Akkumuliert die diffusen Lichtbeiträge, pro Fragment.

    Die Funktion kann die folgenden speziellen Variablen lesen, zusätzlich zu den Matrix- (wie MODEL_MATRIX

    )

    und Vektor- (wie CAMERA_POSITION

    )

    Uniformen aus der obigen Tabelle:

    • vec3 LIGHT_COLOR Diffuse Lichtfarbe.
    • float LIGHT_ATTENUATION Lichtabschwächung.
    • float SHADOW_CONTRIB Schattenbeitrag oder 1.0, wenn überhaupt kein Schatten vorhanden ist oder kein Schatten empfangen wird.
    • vec3 TO_LIGHT_DIR Vektor, der in Richtung der Lichtquelle zeigt.
    • vec3 NORMAL Der Normalenvektor im Weltraum.
    • vec4 BASE_COLOR Die Grundfarbe und der Materialalphawert.
    • float METALNESS Der Metallanteil.
    • float ROUGHNESS Der Rauhigkeitsanteil.

    Beispiel:

    void POINT_LIGHT()
    {
        DIFFUSE += LIGHT_COLOR * LIGHT_ATTENUATION * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(VAR_WORLD_NORMAL), TO_LIGHT_DIR)));
    }
  • void SPOT_LIGHT() Wenn vorhanden, wird diese Funktion für jedes aktive Spotlicht in der Szene für jedes Fragment aufgerufen. Die Aufgabe der Funktion ist es, den diffusen Beitrag zu einer beschreibbaren Spezialvariablen DIFFUSE hinzuzufügen. Die Funktion kann auch nichts tun, in diesem Fall werden die diffusen Beiträge der Scheinwerfer ignoriert. Wenn die Funktion nicht vorhanden ist, werden die diffusen Beiträge von Scheinwerfern normal akkumuliert, wie es eine PrincipledMaterial tun würde.

    Die Funktion kann in die folgenden speziellen Variablen schreiben:

    • vec3 DIFFUSE Akkumuliert die diffusen Lichtbeiträge pro Fragment.

    Die Funktion kann die folgenden speziellen Variablen lesen, zusätzlich zu den Matrix- (wie MODEL_MATRIX

    )

    und Vektor-Uniformen (wie CAMERA_POSITION) aus der obigen Tabelle:

    • vec3 LIGHT_COLOR Diffuse Lichtfarbe.
    • float LIGHT_ATTENUATION Lichtabschwächung.
    • float SHADOW_CONTRIB Schattenbeitrag oder 1.0, wenn überhaupt kein Schatten vorhanden ist oder kein Schatten empfangen wird.
    • vec3 TO_LIGHT_DIR Vektor, der auf die Lichtquelle zeigt.
    • float SPOT_FACTOR Punktlichtfaktor.
    • vec3 NORMAL Der Normalenvektor im Weltraum.
    • vec4 BASE_COLOR Die Grundfarbe und der Alphawert des Materials.
    • float METALNESS Der Metallanteil.
    • float ROUGHNESS Der Rauhigkeitsanteil.

    Beispiel:

    void SPOT_LIGHT()
    {
        DIFFUSE += LIGHT_COLOR * LIGHT_ATTENUATION * SPOT_FACTOR * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(VAR_WORLD_NORMAL), TO_LIGHT_DIR)));
    }
  • void SPECULAR_LIGHT() Wenn vorhanden, wird diese Funktion für jedes aktive Licht in der Szene für jedes Fragment aufgerufen. Die Aufgabe der Funktion ist es, den Spiegelungsbeitrag zu einer beschreibbaren speziellen Variablen SPECULAR hinzuzufügen. Die Funktion kann auch nichts tun, in diesem Fall werden die spiegelnden Beiträge der Lichter ignoriert. Wenn die Funktion nicht vorhanden ist, werden die spiegelnden Beiträge von Lichtern normal akkumuliert, wie es eine PrincipledMaterial tun würde.

    Die Funktion kann in die folgenden speziellen Variablen schreiben:

    • vec3 SPECULAR Akkumuliert die spiegelnden Lichtbeiträge, pro Fragment.
    • Die Lichtprozessorfunktionen addieren typischerweise (+=
    )
    • dazu, da durch das Überschreiben des Wertes die Beiträge anderer Lichter verloren gehen würden.

    Die Funktion kann zusätzlich zu den Matrix- (z.B. MODEL_MATRIX

    )

    und Vektor- (z.B. CAMERA_POSITION) Uniformen aus der obigen Tabelle die folgenden speziellen Variablen lesen:

    • vec3 LIGHT_COLOR Specular light color.
    • float LIGHT_ATTENUATION Light attenuation. Für gerichtete Lichter ist der Wert 1,0.
    • Für Punktlichter ist der Wert derselbe wie LIGHT_ATTENUATION * SPOT_FACTOR von void SPOT_LIGHT()
    • .
    • float SHADOW_CONTRIB Schattenbeitrag oder 1.0, wenn überhaupt kein Schatten vorhanden ist oder kein Schatten empfangen wird.
    • vec3 FRESNEL_CONTRIB Fresnel-Beitrag aus der eingebauten Fresnel-Berechnung.
    • vec3 TO_LIGHT_DIR Vektor, der auf die Lichtquelle zeigt.
    • vec3 NORMAL Der Normalenvektor im Weltraum.
    • vec4 BASE_COLOR Die Grundfarbe und der Material-Alpha-Wert.
    • float METALNESS Der Metallanteil.
    • float ROUGHNESS Der Rauheitsanteil.
    • float SPECULAR_AMOUNT Der Spiegelanteil. Dieser Wert liegt zwischen 0,0 und 1,0 und ist derselbe Wert, der in der benutzerdefinierten Funktion MAIN festgelegt wurde. Dieser Wert ist nützlich für die Berechnung von Fresnel-Beiträgen, wenn nicht der integrierte Fresnel-Beitrag von FRESNEL_CONTRIB verwendet wird
  • .
  • void SPECULAR_LIGHT()
    {
        vec3 H = normalize(VIEW_VECTOR + TO_LIGHT_DIR);
        float cosAlpha = max(0.0, dot(H, normalize(NORMAL)));
        float shine = pow(cosAlpha, exp2(15.0 * (1.0 - ROUGHNESS) + 1.0) * 0.25);
        SPECULAR += shine * LIGHT_COLOR * FRESNEL_CONTRIB * SHADOW_CONTRIB * LIGHT_ATTENUATION;
    }
  • void POST_PROCESS() Wenn vorhanden, wird diese Funktion am Ende der Fragment-Pipeline aufgerufen. Die Aufgabe der Funktion ist es, COLOR_SUM mit den endgültigen diffusen, spiegelnden und emittierenden Termen abzuschließen. Im Gegensatz zu FRAGCOLOR für ein nicht schattiertes Material wird COLOR_SUM automatisch tongemappt, bevor es in den Framebuffer geschrieben wird. Zu Debugging-Zwecken ist es manchmal nützlich, einen Wert auszugeben, der nicht als Farbe behandelt werden soll. Um zu vermeiden, dass das Tonemapping diesen Wert verzerrt, kann es deaktiviert werden, indem die Eigenschaft tonemapMode auf TonemapModeNone gesetzt wird

    . Die Funktion kann in die folgenden speziellen Variablen schreiben:

    • vec4 COLOR_SUM die Ausgabe des Fragment-Shaders.
    • Der Standardwert ist vec4(DIFFUSE.rgb + SPECULAR + EMISSIVE, DIFFUSE.a)

    Die Funktion kann die folgenden speziellen Variablen lesen.

    • vec4 DIFFUSE Der endgültige diffuse Term der Fragment-Pipeline.
    • vec3 SPECULAR Der endgültige specular Term der Fragment-Pipeline.
    • vec3 EMISSIVE Der letzte emissive Term der Fragment-Pipeline.
    • vec2 UV0 - Der erste Satz von Texturkoordinaten aus dem Vertex-Shader.
    • vec2 UV1 - Der zweite Satz von Texturkoordinaten aus dem Vertex-Shader.
    void POST_PROCESS()
    {
        float center_x = textureSize(SCREEN_TEXTURE, 0).x * 0.5;
        if (gl_FragCoord.x > center_x)
            COLOR_SUM = DIFFUSE;
        else
            COLOR_SUM = vec4(EMISSIVE, DIFFUSE.a);
    }
  • void IBL_PROBE() Wenn vorhanden, wird diese Funktion für IBL (Image-Based Lighting) aufgerufen. Die Aufgabe der Funktion ist es, sowohl die diffusen als auch die spiegelnden Beiträge von IBL zu den beschreibbaren Spezialvariablen DIFFUSE und SPECULAR zu addieren

    . Die Funktion kann in die folgenden Spezialvariablen schreiben:

    • vec3 DIFFUSE Akkumuliert die diffusen Lichtbeiträge, pro Fragment.
    • vec3 SPECULAR Akkumuliert die spiegelnden Lichtbeiträge, pro Fragment.

    Die Funktion kann die folgenden Spezialvariablen lesen.

    • vec4 BASE_COLOR Die Grundfarbe und der Material-Alpha-Wert.
    • float AO_FACTOR Der Bildschirmraum-Verdeckungsfaktor.
    • float SPECULAR_AMOUNT Der spiegelnde Anteil.
    • float ROUGHNESS Der abschließende Emissionsterm der Fragment-Pipeline.
    • vec3 NORMAL Der Normalenvektor im Weltraum.
    • vec3 VIEW_VECTOR Zeigt in Richtung der Kamera.
    • mat3 IBL_ORIENTATION Die Ausrichtung der Lichtsonde. Sie ergibt sich aus SceneEnvironment::probeOrientation
  • .
  • void IBL_PROBE()
    {
        vec3 smpDir = IBL_ORIENTATION * NORMAL;
        DIFFUSE += AO_FACTOR * BASE_COLOR.rgb * textureLod(IBL_TEXTURE, smpDir, IBL_MAXMIPMAP).rgb;
    }

Benutzerdefinierte Variablen zwischen Funktionen

Zusätzliche Variablen können von der MAIN-Funktion an die anderen Funktionen übergeben werden. Das Schlüsselwort SHARED_VARS kann zur Definition neuer benutzerdefinierter Variablen verwendet werden. Auf diese benutzerdefinierten Variablen kann mit SHARED.<Variablenname> zugegriffen werden.

Ein schattiertes benutzerdefiniertes Material kann zum Beispiel einen gemeinsamen Wert in der Funktion MAIN abrufen und in anderen Funktionen verwenden.

SHARED_VARS {
    vec3 colorThreshold;
};
void MAIN()
{
    BASE_COLOR = texture(baseColorMap, UV0);
    SHARED.colorThreshold = texture(thresholdMap, UV0).rgb;
}
void DIRECTIONAL_LIGHT()
{
    if (DIFFUSE >= SHARED.colorThreshold) {
        DIFFUSE = SHARED.colorThreshold;
        return;
    }
    DIFFUSE += LIGHT_COLOR * SHADOW_CONTRIB;
}

Hinweis: SHARED kann in alle Funktionen ohne POST_PROCESS geschrieben werden, aber es ist sicher, es in MAIN zu schreiben und in den anderen Funktionen zu lesen.

Hinweis: Ein empfohlener Anwendungsfall, um SHARED in LIGHT-Funktionen zu schreiben, ist, es zuerst in MAIN zurückzusetzen und es dann in jeder LIGHT-Funktion zu akkumulieren.

SHARED_VARS {
    float sheenIntensity;
    float sheenRoughness;
    vec3 sheenColor;
    vec3 outSheenColor;
};
void MAIN()
{
    ...
    vec4 tex = texture(uSheenMap, UV0);
    SHARED.sheenColor = tex.rgb;
    SHARED.sheenIntensity = tex.a;
    SHARED.sheenRoughness = uSheenRoughness;
    SHARED.outSheenColor = vec3(0.0);
}
void SPECULAR_LIGHT()
{
    SHARED.outSheenColor += ...;
}
void POST_PROCESS()
{
    COLOR_SUM = DIFFUSE + SPECULAR + EMISSIVE + SHARED.outSheenColor;
}

Hinweis: MAIN wird vor den anderen Funktionen und POST_PROCESS nach allen anderen Funktionen aufgerufen, aber es gibt keine Garantie für eine andere Reihenfolge bei Light-Prozessoren.

Zusätzliche spezielle Schlüsselwörter

Der benutzerdefinierte Fragment-Shader-Code kann frei auf Uniformen (wie CAMERA_DIRECTION oder CAMERA_POSITION) und Variationen zugreifen, die vom benutzerdefinierten Vertex-Shader weitergegeben werden. Zusätzlich gibt es eine Reihe von eingebauten Variationen, die als spezielle Schlüsselwörter verfügbar sind. Einige davon sind optional in dem Sinne, dass ein Vertex-Shader MAIN diese selbst berechnen und weitergeben könnte, aber um doppelte Daten zu reduzieren, können sich Fragment-Shader stattdessen auch auf diese Built-ins verlassen. Diese Built-Ins sind in den Lichtprozessorfunktionen und im Fragment MAIN verfügbar.

  • vec3 VAR_WORLD_NORMAL - Interpolierte Normale, transformiert durch NORMAL_MATRIX.
  • vec3 VAR_WORLD_TANGENT - Interpolierter Tangens transformiert durch MODEL_MATRIX.
  • vec3 VAR_WORLD_BINORMAL - Interpolierte Binormale transformiert nach MODEL_MATRIX
  • vec3 NORMAL - Im Gegensatz zu VAR_WORLD_NORMAL, der die interpolierte Normale im Ist-Zustand darstellt, wird dieser Wert potenziell für Doppelseitigkeit angepasst: Beim Rendern mit deaktiviertem Culling wird die Normale bei Bedarf invertiert. Daher wird empfohlen, für Beleuchtungs- und andere Berechnungen NORMAL anstelle von VAR_WORLD_NORMAL zu verwenden, um sich mit allen Culling-Modi korrekt zu verhalten.
  • vec3 TANGENT - Wie NORMAL wird dieser Wert für Doppelseitigkeit angepasst: beim Rendern mit deaktiviertem Culling wird die Tangente bei Bedarf invertiert.
  • vec3 BINORMAL - Wie NORMAL, wird dieser Wert potenziell für Doppelseitigkeit angepasst: Beim Rendern mit deaktiviertem Culling wird die Binormale bei Bedarf invertiert.
  • vec3 VAR_WORLD_POSITION - Interpolierte Weltraum-Eckpunktposition ((MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz)
  • vec4 VAR_COLOR - Die interpolierte Scheitelfarbe, wenn im Netz Farben angegeben sind. vec4(1.0) ansonsten.
  • vec3 VIEW_VECTOR - Zeigt in Richtung der Kamera. Dies ist effektiv der CAMERA_POSITION - VAR_WORLD_POSITION Vektor, normalisiert.
  • vec4 FRAGCOORD - Enthält die Fenster-relativen Koordinaten des aktuellen Fragments.
  • 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 untere linke Ecke ist. Der Wert ist -1, wenn die Y-Achse nach unten zeigt; (0, 0) ist dann die linke obere Ecke. Solche Unterschiede in den zugrunde liegenden Grafik-APIs betreffen die meisten benutzerdefinierten Materialien nicht. Eine bemerkenswerte Ausnahme ist das Sampling von SCREEN_TEXTURE mit Texturkoordinaten , die nicht auf FRAGCOORD basieren. Da die Ausrichtung von SCREEN_TEXTURE von Natur aus an die zugrundeliegende Grafik-API gebunden ist, sind bei der Verwendung von Texturkoordinaten aus einem Mesh möglicherweise entsprechende Anpassungen der Y-Koordinate erforderlich.

    Der folgende Fragment-Shader, der für Rechteck- oder Würfel-Meshes geeignet ist, zeigt beispielsweise die opaken Objekte der Szene auf dem Modell an:

    VARYING vec2 texcoord;
    void MAIN()
    {
        vec2 screencoord = texcoord;
        if (FRAMEBUFFER_Y_UP < 0.0) // effectively: if not OpenGL
            screencoord.y = 1.0 - screencoord.y;
        BASE_COLOR = texture(SCREEN_TEXTURE, screencoord);
    }

    Wenn andere Texturen als SCREEN_TEXTURE und DEPTH_TEXTURE gesampelt werden, oder wenn FRAGCOORD zur Berechnung der Texturkoordinate verwendet wird (was der typische Anwendungsfall für den Zugriff auf die Bildschirm- und Tiefentexturen wäre), ist eine solche Anpassung nicht erforderlich.

  • float NDC_Y_UP - Der Wert ist 1, wenn die Y-Achse im normalisierten Gerätekoordinatenraum nach oben zeigt, und -1, wenn die Y-Achse nach unten zeigt. Wenn Y nach unten zeigt, ist dies der Fall, wenn das Rendering mit Vulkan erfolgt. Die meisten Materialien müssen sich nicht darum kümmern, aber die Möglichkeit, basierend auf diesem Wert zu verzweigen, kann in bestimmten fortgeschrittenen Anwendungsfällen nützlich werden.
  • float NEAR_CLIP_VALUE - Der Wert ist -1 für den Fall, dass der Bereich der Clipping-Ebene bei -1 beginnt und bis 1 reicht. Dies ist der Fall, wenn OpenGL zum Rendern verwendet wird. Bei anderen Rendering-Backends ist der Wert dieser Eigenschaft 0, was bedeutet, dass der Bereich der Clipping-Ebene von 0 bis 1 reicht. Dieser Wert ist bei bestimmten Techniken nützlich, bei denen die DEPTH_TEXTURE

    Der folgende Fragment-Shader demonstriert beispielsweise eine Technik zur Rekonstruktion der Position eines Wertes aus dem Tiefenpuffer, um die Entfernung von der aktuellen gerenderten Position zu bestimmen. Bei Verwendung in Kombination mit INVERSE_PROJECTION_MATRIX muss der Tiefenwert in normalisierten Gerätekoordinaten angegeben werden, daher ist es wichtig, dass der Tiefenwertbereich dies widerspiegelt. Wenn NEAR_CLIP_VALUE -1 ist, wird der Tiefenwert so skaliert, dass er zwischen -1 und 1 liegt.

    void MAIN() {
        vec2 screen_uv = FRAGCOORD.xy / vec2(textureSize(SCREEN_TEXTURE, 0));
        float depth = texture(DEPTH_TEXTURE, screen_uv).r;
    
        if (NEAR_CLIP_VALUE < 0.0) // effectively: if opengl
            depth = depth * 2.0 - 1.0;
    
        vec4 unproject = INVERSE_PROJECTION_MATRIX * vec4(screen_uv, depth, 1.0);
        depth = (unproject.xyz / unproject.w).z;
        float viewVectorZ = (VIEW_MATRIX * vec4(VAR_WORLD_POSITION, 1.0)).z;
        depth = viewVectorZ - depth;
    
        BASE_COLOR = vec4(depth, depth, depth, 1.0);
    }
  • float IBL_EXPOSE - Die von der Lichtsonde abgegebene Lichtmenge. Sie stammt von SceneEnvironment::probeExposure.
    DIFFUSE += AO_FACTOR * IBL_EXPOSE * BASE_COLOR.rgb * textureLod(IBL_TEXTURE, NORMAL, IBL_MAXMIPMAP).rgb;
  • float IBL_HORIZON - Der horizontale Cut-Off-Wert der Reflexionen aus der unteren Hälfte der Umgebung. Dieser Wert stammt von Horizon Cut-Off, wird aber auf [-1, 0) umgerechnet.
    vec3 diffuse += AO_FACTOR * IBL_EXPOSE * BASE_COLOR.rgb * textureLod(IBL_TEXTURE, NORMAL, IBL_MAXMIPMAP).rgb;
    if (IBL_HORIZON > -1.0) {
        float ctr = 0.5 + 0.5 * IBL_HORIZON;
        float vertWt = smoothstep(ctr * 0.25, ctr + 0.25, NORMAL.y);
        float wtScaled = mix(1.0, vertWt, IBL_HORIZON + 1.0);
        diffuse *= wtScaled;
    }
  • float IBL_MAXMIPMAP - Der maximale Mipmap-Pegel von IBL_TEXTURE.

Instanzierung

Beim instanzierten Rendering sind einige der oben genannten Schlüsselwörter nicht anwendbar. Die folgenden Schlüsselwörter sind nur bei Instanzierung verfügbar:

  • INSTANCE_MODEL_MATRIX -> mat4, Ersatz für MODEL_MATRIX, einschließlich der Instanztransformation.
  • INSTANCE_MODELVIEWPROJECTION_MATRIX -> mat4, Ersatz für MODELVIEWPROJECTION_MATRIX, einschließlich der Instanztransformation.
  • INSTANCE_COLOR -> vec4, die Instanzfarbe: zu kombinieren mit COLOR.
  • INSTANCE_DATA -> vec4, Instanz benutzerdefinierte Daten.
  • INSTANCE_INDEX -> int, die Instanznummer und der Index in der Instanztabelle.

Bildschirm, Tiefe und andere Texturen

Die Rendering-Pipeline kann den benutzerdefinierten Material-Shadern eine Reihe von Texturen mit Inhalten aus speziellen Render-Passes zur Verfügung stellen. Dies gilt sowohl für schattierte als auch für nicht schattierte benutzerdefinierte Materialien.

Beispielsweise kann ein Shader auf eine Tiefentextur zugreifen wollen, die den Inhalt des Tiefenpuffers für die undurchsichtigen Objekte in der Szene enthält. Dies wird durch Sampling DEPTH_TEXTURE erreicht. Eine solche Textur wird normalerweise nicht erzeugt, es sei denn, es besteht ein echter Bedarf dafür. Daher dient das Vorhandensein der folgenden Schlüsselwörter im Vertex- oder Fragment-Shader auch als Umschalter, um die - potenziell teuren - Durchläufe zur Erzeugung der betreffenden Textur zu aktivieren. (Natürlich kann es sein, dass einige davon aufgrund anderer Einstellungen bereits aktiviert sind, wie z. B. die Ambient-Occlusion-Parameter in SceneEnvironment oder aufgrund eines Post-Processing-Effekts, der sich auf die Tiefen-Textur stützt; in diesem Fall werden die fraglichen Texturen unabhängig vom benutzerdefinierten Material generiert, so dass das Sampling dieser speziellen Texturen im Material keine zusätzlichen Kosten verursacht, abgesehen vom Texturzugriff selbst)

  • SCREEN_TEXTURE - Wenn vorhanden, wird eine Textur (sampler2D oder sampler2DArray) mit dem Farbpuffer aus einem Rendering-Durchgang, der den Inhalt der Szene enthält, mit Ausnahme aller transparenten Materialien oder aller Materialien, die ebenfalls SCREEN_TEXTURE verwenden, dem Shader unter diesem Namen zur Verfügung gestellt. Die Textur kann für Techniken verwendet werden, die den Inhalt des Framebuffers benötigen, in den sie gerendert werden. Die SCREEN_TEXTURE-Textur verwendet denselben Clear-Modus wie die View3D. Die Größe dieser Texturen entspricht der Größe der View3D in Pixeln. Ein Fragment-Shader könnte zum Beispiel Folgendes enthalten:
    vec2 uv = FRAGCOORD.xy / vec2(textureSize(SCREEN_TEXTURE, 0));
    vec2 displace = vec2(0.1);
    vec4 c = texture(SCREEN_TEXTURE, uv + displace);

    Beachten Sie, dass die Verwendung von SCREEN_TEXTURE eine angemessene, bewusste Gestaltung der Szene erfordert. Objekte, die solche Materialien verwenden, müssen sorgfältig positioniert werden, normalerweise über allen anderen Objekten, die in der Textur sichtbar sein sollen. Objekte, die in irgendeiner Form Semitransparenz verwenden, sind nie Teil von SCREEN_TEXTURE. Oft wird SCREEN_TEXTURE in Kombination mit BASE_COLOR in MAIN verwendet. Der folgende benutzerdefinierte Fragment-Shader wendet zum Beispiel einen Prägeeffekt an, wobei Fragmente, die nicht von undurchsichtigen Objekten berührt werden, transparent bleiben.

    Dabei wird davon ausgegangen, dass das Objekt mit dem Material im Vordergrund platziert ist und die Überblendung aktiviert ist.

    void MAIN()
    {
        vec2 size = vec2(textureSize(SCREEN_TEXTURE, 0));
        vec2 uv = FRAGCOORD.xy / size;
    
        // basic emboss effect
        vec2 d = vec2(1.0 / size.x, 1.0 / size.y);
        vec4 diff = texture(SCREEN_TEXTURE, uv + d) - texture(SCREEN_TEXTURE, uv - d);
        float c = (diff.x + diff.y + diff.z) + 0.5;
    
        float alpha = texture(SCREEN_TEXTURE, uv).a;
        BASE_COLOR = vec4(vec3(c), alpha);
    }

    Beim Multiview-Rendering ist SCREEN_TEXTURE ein sampler2DArray

    .

    Verwenden Sie VIEW_INDEX, um die zu verwendende Ebene auszuwählen. Für VR/AR-Anwendungen, die beide Arten des Renderings unterstützen möchten, ist der portable Ansatz der folgende:

    #if QSHADER_VIEW_COUNT >= 2
        vec4 c = texture(SCREEN_TEXTURE, vec3(uv, VIEW_INDEX));
    #else
        vec4 c = texture(SCREEN_TEXTURE, uv);
    #endif
  • SCREEN_MIP_TEXTURE - Identisch mit SCREEN_TEXTURE in den meisten Punkten, mit dem Unterschied, dass diese Textur Mipmaps generiert hat. Dies kann je nach Bildschirmgröße und aufgrund der Tatsache, dass die Mipmaps jedes Mal, wenn die Szene gerendert wird, generiert werden müssen, ein teures Leistungsmerkmal sein. Verwenden Sie daher lieber immer SCREEN_TEXTURE, es sei denn, das benutzerdefinierte Material implementiert eine Technik, die auf die Mip-Levels der Textur angewiesen ist (z. B. die Verwendung von textureLod im Shader).
  • DEPTH_TEXTURE - Wenn vorhanden, wird eine Textur (sampler2D oder sampler2DArray) mit dem (nicht linearisierten) Tiefenpufferinhalt dem Shader unter diesem Namen angezeigt. Es werden nur undurchsichtige Objekte einbezogen. Ein Fragment-Shader könnte z. B. Folgendes enthalten:
    ivec2 dtSize = textureSize(DEPTH_TEXTURE, 0);
    vec2 dtUV = (FRAGCOORD.xy) / vec2(dtSize);
    vec4 depthSample = texture(DEPTH_TEXTURE, dtUV);
    float zNear = CAMERA_PROPERTIES.x;
    float zFar = CAMERA_PROPERTIES.y;
    float zRange = zFar - zNear;
    float z_n = 2.0 * depthSample.r - 1.0;
    float d = 2.0 * zNear * zFar / (zFar + zNear - z_n * zRange);
    d /= zFar;

    Beim Multiview-Rendering ist DEPTH_TEXTURE ein sampler2DArray

    .

    Verwenden Sie VIEW_INDEX, um die zu verwendende Ebene auszuwählen. Für VR/AR-Anwendungen, die beide Arten von Rendering unterstützen möchten, ist der portable Ansatz der folgende:

    #if QSHADER_VIEW_COUNT >= 2
        vec4 depthSample = texture(DEPTH_TEXTURE, vec3(uv, VIEW_INDEX));
    #else
        vec4 depthSample = texture(DEPTH_TEXTURE, uv);
    #endif
  • AO_TEXTURE - Wenn vorhanden und Screen Space Ambient Occlusion aktiviert ist (d.h. wenn die AO-Stärke und der Abstand beide ungleich Null sind) in SceneEnvironment, wird die SSAO-Textur (sampler2D oder sampler2DArray) dem Shader unter diesem Namen ausgesetzt. Die Abtastung dieser Textur kann bei nicht schattierten Materialien nützlich sein. Bei schattierten Materialien ist die Unterstützung von Ambient Occlusion eingebaut. Dies bedeutet, dass der Faktor der Umgebungsokklusion automatisch berücksichtigt wird. In einem Fragment-Shader für ein nicht schattiertes Material könnte man Folgendes schreiben, um das Gleiche zu erreichen:
    ivec2 aoSize = textureSize(AO_TEXTURE, 0);
    vec2 aoUV = (FRAGCOORD.xy) / vec2(aoSize);
    float aoFactor = texture(AO_TEXTURE, aoUV).x;

    Beim Multiview-Rendering ist AO_TEXTURE eine sampler2DArray. Verwenden Sie VIEW_INDEX, um die zu verwendende Ebene auszuwählen. Für VR/AR-Anwendungen, die beide Arten von Rendering unterstützen wollen, ist der portable Ansatz der folgende:

    #if QSHADER_VIEW_COUNT >= 2
        ivec2 aoSize = textureSize(AO_TEXTURE, 0).xy;
        vec2 aoUV = (FRAGCOORD.xy) / vec2(aoSize);
        float aoFactor = texture(AO_TEXTURE, vec3(aoUV, VIEW_INDEX)).x;
    #else
        ivec2 aoSize = textureSize(AO_TEXTURE, 0);
        vec2 aoUV = (FRAGCOORD.xy) / vec2(aoSize);
        float aoFactor = texture(AO_TEXTURE, aoUV).x;
    #endif
  • IBL_TEXTURE - Sie ermöglicht keinen speziellen Rendering-Pass, kann aber verwendet werden, wenn das Material Material::lightProbe hat oder das Modell im Bereich von SceneEnvironment::lightProbe liegt.
    void IBL_PROBE()
    {
        DIFFUSE += AO_FACTOR * BASE_COLOR.rgb * textureLod(IBL_TEXTURE, NORMAL, IBL_MAXMIPMAP).rgb;
    }
  • VIEW_INDEX - Wenn sie im benutzerdefinierten Shader-Code verwendet wird, ist dies eine (nicht interpolierte) uint-Variable. Wenn Multiview-Rendering nicht verwendet wird, ist der Wert immer 0. Bei Multiview-Rendering ist der Wert der aktuelle View-Index (z. B. gl_ViewIndex). Nützlich vor allem in Kombination mit DEPTH_TEXTURE und ähnlichem, wenn Multiview-Rendering aktiviert ist.

Siehe auch SceneEnvironment::tonemapMode, Verwendung von bildbasierter Beleuchtung, Qt Quick 3D - Beispiel für benutzerdefinierte Shader, Qt Quick 3D - Beispiel für benutzerdefinierte Materialien, und Programmierbare Materialien, Effekte, Geometrie und Texturdaten.

Eigenschaft Dokumentation

alwaysDirty : bool

Gibt an, dass der Materialstatus immer schmutzig ist, was bedeutet, dass das Material jedes Mal, wenn es von QtQuick3D verwendet wird, aktualisiert werden muss.


destinationAlphaBlend : enumeration [since 6.7]

Gibt den Ziel-Alphaüberblendungsfaktor an. Der Standardwert ist CustomMaterial.NoBlend. Dieser Wert wird nur aktiv verwendet, wenn sourceBlend und destinationBlend auf einen anderen Wert als den Standardwert gesetzt sind.

KonstanteWert
CustomMaterial.NoBlend
CustomMaterial.Zero
CustomMaterial.One
CustomMaterial.SrcColor
CustomMaterial.OneMinusSrcColor
CustomMaterial.DstColor
CustomMaterial.OneMinusDstColor
CustomMaterial.SrcAlpha
CustomMaterial.OneMinusSrcAlpha
CustomMaterial.DstAlpha
CustomMaterial.OneMinusDstAlpha
CustomMaterial.ConstantColor
CustomMaterial.OneMinusConstantColor
CustomMaterial.ConstantAlpha
CustomMaterial.OneMinusConstantAlpha
CustomMaterial.SrcAlphaSaturate

Hinweis: Aus Gründen der Abwärtskompatibilität wird, wenn der Standardwert beibehalten wird, der gleiche Wert wie destinationBlend zugewiesen, wenn sourceBlend und destinationBlend auf Nicht-Standardwerte gesetzt sind.

Diese Eigenschaft wurde in Qt 6.7 eingeführt.

Siehe auch destinationBlend.


destinationBlend : enumeration

Gibt den Zielüberblendungsfaktor an. Der Standardwert ist CustomMaterial.NoBlend.

KonstanteWert
CustomMaterial.NoBlend
CustomMaterial.Zero
CustomMaterial.One
CustomMaterial.SrcColor
CustomMaterial.OneMinusSrcColor
CustomMaterial.DstColor
CustomMaterial.OneMinusDstColor
CustomMaterial.SrcAlpha
CustomMaterial.OneMinusSrcAlpha
CustomMaterial.DstAlpha
CustomMaterial.OneMinusDstAlpha
CustomMaterial.ConstantColor
CustomMaterial.OneMinusConstantColor
CustomMaterial.ConstantAlpha
CustomMaterial.OneMinusConstantAlpha
CustomMaterial.SrcAlphaSaturate

Hinweis: Sowohl sourceBlend als auch destinationBlend müssen auf einen anderen Wert als den Standardwert gesetzt werden, bevor die Überblendung aktiviert wird.

Siehe auch sourceBlend.


fragmentShader : url

Gibt die Datei mit dem Ausschnitt des benutzerdefinierten Fragment-Shader-Codes an.

Der Wert ist eine URL und muss entweder eine lokale Datei sein oder das qrc-Schema verwenden, um auf Dateien zuzugreifen, die über das Qt-Ressourcensystem eingebettet sind. Relative Dateipfade (ohne Schema) werden ebenfalls akzeptiert, in diesem Fall wird die Datei als relativ zur Komponente (der .qml Datei) behandelt.

Siehe auch vertexShader.


lineWidth : real

Diese Eigenschaft bestimmt die Breite der gerenderten Linien, wenn die Geometrie einen primitiven Typ von Linien oder Linienstreifen verwendet. Der Standardwert ist 1.0. Diese Eigenschaft ist nicht relevant, wenn andere Geometrietypen gerendert werden, z. B. Dreiecksnetze.

Warnung: Andere Linienbreiten als 1 werden je nach der zugrunde liegenden Grafik-API zur Laufzeit möglicherweise nicht unterstützt. Wenn dies der Fall ist, wird die Anforderung, die Breite zu ändern, ignoriert. Es ist zum Beispiel nicht zu erwarten, dass breite Linien unterstützt werden: Direct3D, Metal, OpenGL mit Kernprofilkontexten.

Hinweis: Im Gegensatz zur Linienbreite, deren Wert Teil des Grafikpipeline-Objekts ist, wird die Punktgröße für Geometrien mit einer Topologie aus Punkten durch den Vertex-Shader gesteuert (sofern unterstützt) und hat daher keine entsprechende QML-Eigenschaft.


shadingMode : enumeration

Gibt den Typ des Materials an. Der Standardwert ist Shaded.

KonstanteWert
CustomMaterial.Unshaded
CustomMaterial.Shaded

sourceAlphaBlend : enumeration [since 6.7]

Gibt den Quell-Alpha-Überblendfaktor an. Der Standardwert ist CustomMaterial.NoBlend. Dieser Wert wird nur aktiv verwendet, wenn sourceBlend und destinationBlend auf einen anderen Wert als den Standardwert eingestellt sind.

KonstanteWert
CustomMaterial.NoBlend
CustomMaterial.Zero
CustomMaterial.One
CustomMaterial.SrcColor
CustomMaterial.OneMinusSrcColor
CustomMaterial.DstColor
CustomMaterial.OneMinusDstColor
CustomMaterial.SrcAlpha
CustomMaterial.OneMinusSrcAlpha
CustomMaterial.DstAlpha
CustomMaterial.OneMinusDstAlpha
CustomMaterial.ConstantColor
CustomMaterial.OneMinusConstantColor
CustomMaterial.ConstantAlpha
CustomMaterial.OneMinusConstantAlpha
CustomMaterial.SrcAlphaSaturate

Hinweis: Aus Gründen der Abwärtskompatibilität wird diesem Wert, wenn er auf seinem Standardwert belassen wird, der gleiche Wert wie sourceBlend zugewiesen, wenn sourceBlend und destinationBlend auf Nicht-Standardwerte gesetzt sind.

Diese Eigenschaft wurde in Qt 6.7 eingeführt.

Siehe auch sourceBlend.


sourceBlend : enumeration

Legt den Überblendfaktor der Quelle fest. Der Standardwert ist CustomMaterial.NoBlend.

KonstanteWert
CustomMaterial.NoBlend
CustomMaterial.Zero
CustomMaterial.One
CustomMaterial.SrcColor
CustomMaterial.OneMinusSrcColor
CustomMaterial.DstColor
CustomMaterial.OneMinusDstColor
CustomMaterial.SrcAlpha
CustomMaterial.OneMinusSrcAlpha
CustomMaterial.DstAlpha
CustomMaterial.OneMinusDstAlpha
CustomMaterial.ConstantColor
CustomMaterial.OneMinusConstantColor
CustomMaterial.ConstantAlpha
CustomMaterial.OneMinusConstantAlpha
CustomMaterial.SrcAlphaSaturate

Hinweis: Sowohl sourceBlend als auch destinationBlend müssen auf einen anderen Wert als den Standardwert gesetzt werden, bevor die Überblendung aktiviert wird.

Siehe auch destinationBlend.


vertexShader : url

Gibt die Datei mit dem Ausschnitt des benutzerdefinierten Vertex-Shader-Codes an.

Der Wert ist eine URL und muss entweder eine lokale Datei sein oder das qrc-Schema verwenden, um auf Dateien zuzugreifen, die über das Qt-Ressourcensystem eingebettet sind. Relative Dateipfade (ohne Schema) werden ebenfalls akzeptiert, in diesem Fall wird die Datei als relativ zur Komponente (die .qml Datei) behandelt.

Siehe auch fragmentShader.


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