CustomMaterial QML Type
Basiskomponente zur Erstellung von benutzerdefinierten Materialien, die zur Schattierung von Modellen verwendet werden. Mehr...
Import Statement: | import QtQuick3D |
Inherits: |
Eigenschaften
- alwaysDirty : bool
- destinationAlphaBlend : enumeration
(since 6.7)
- destinationBlend : enumeration
- fragmentShader : url
- lineWidth : real
- shadingMode : enumeration
- sourceAlphaBlend : enumeration
(since 6.7)
- sourceBlend : enumeration
- vertexShader : url
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 vonPOSITION
, der vec4-Ausgabe des Vertex-Shaders, zu setzen und optional die Werte vonVERTEX
,COLOR
,NORMAL
,UV0
,UV1
,TANGENT
,BINORMAL
,JOINTS
undWEIGHTS
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 aufVERTEX
oderNORMAL
speichern wollen, um anschließend korrekte Beleuchtungsberechnungen durchzuführen. Außerdem kann die Funktion in Variablen schreiben, die mitVARYING
definiert wurden, um interpolierte Daten an den Fragment-Shader zu übergeben. Wenn diese Funktion oder eine Neudefinition vonPOSITION
nicht vorhanden ist, wirdPOSITION
auf der Grundlage vonVERTEX
undMODELVIEWPROJECTION_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 VariablenBASE_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 undOCCLUSION_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 vonBASE_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 inMAIN
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 inMAIN
zu setzen, da diese dann bei den Standardbeleuchtungsberechnungen berücksichtigt wird. Der Standardwert istvec4(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 vonvec3 color
undfloat 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 istvec3(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 ist1.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äre1.0
und die Vorgabe ist0.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äre10.0
und der Standardwert ist0.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ärevec3(1.0, 0.0, 0.0)
und auch der Standardwert istvec3(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äre100.0
und die Vorgabe ist0.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 ist5.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 ist1.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 ist0.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 ist1.0
und der Standardwert ist0.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äre1.0
für eine vollständig unscharfe Klarlackschicht und auch die Voreinstellung ist0.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 wieVAR_WORLD_NORMAL
hat, hat nur die Änderung des Wertes vonCLEARCOAT_NORMAL
eine Auswirkung auf die Normalen der Klarlackschicht. - Float
FRESNEL_POWER
Gibt die Fresnelleistung an. Ein typischer Wert und auch der Standardwert ist5.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 ist1.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 ist0.0
, da dies der Wert ist, den PrincipledMaterial verwenden würde. - float
SPECULAR_AMOUNT
Spiegelungsanteil im Bereich 0,0 - 1,0. Der Standardwert ist0.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 ist1.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 wieVAR_WORLD_NORMAL
hat, hat nur die Änderung des Wertes vonNORMAL
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 überFRAGCOLOR
. Vielmehr sind es die in den Lichtprozessorfunktionen geschriebenen WerteDIFFUSE
undSPECULAR
, die über die endgültige Fragmentfarbe entscheiden. Wenn keine Lichtprozessorfunktion implementiert ist, werden die entsprechenden Standard-Schattierungsberechnungen wie bei PrincipledMaterial durchgeführt, wobeiBASE_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); }
- vec4
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 SpezialvariablenDIFFUSE
zu addieren. Sie kann natürlich auch einen anderen Wert berechnen oderDIFFUSE
ü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; }
- vec3
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 SpezialvariablenDIFFUSE
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))); }
- vec3
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 VariablenDIFFUSE
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))); }
- vec3
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 SpezialvariablenDIFFUSE
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))); }
- vec3
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 VariablenSPECULAR
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
vonvoid 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 FunktionMAIN
festgelegt wurde. Dieser Wert ist nützlich für die Berechnung von Fresnel-Beiträgen, wenn nicht der integrierte Fresnel-Beitrag vonFRESNEL_CONTRIB
verwendet wird
.- vec3
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 zuFRAGCOLOR
für ein nicht schattiertes Material wirdCOLOR_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 aufTonemapModeNone
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); }
- vec4
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 SpezialvariablenDIFFUSE
undSPECULAR
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
.- vec3
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 durchNORMAL_MATRIX
. - vec3
VAR_WORLD_TANGENT
- Interpolierter Tangens transformiert durchMODEL_MATRIX
. - vec3
VAR_WORLD_BINORMAL
- Interpolierte Binormale transformiert nachMODEL_MATRIX
- vec3
NORMAL
- Im Gegensatz zuVAR_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 BerechnungenNORMAL
anstelle vonVAR_WORLD_NORMAL
zu verwenden, um sich mit allen Culling-Modi korrekt zu verhalten. - vec3
TANGENT
- WieNORMAL
wird dieser Wert für Doppelseitigkeit angepasst: beim Rendern mit deaktiviertem Culling wird die Tangente bei Bedarf invertiert. - vec3
BINORMAL
- WieNORMAL
, 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 derCAMERA_POSITION - VAR_WORLD_POSITION
Vektor, normalisiert. - vec4
FRAGCOORD
- Enthält die Fenster-relativen Koordinaten des aktuellen Fragments. - float
FRAMEBUFFER_Y_UP
- Der Wert ist1
, 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 vonSCREEN_TEXTURE
mit Texturkoordinaten , die nicht aufFRAGCOORD
basieren. Da die Ausrichtung vonSCREEN_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
undDEPTH_TEXTURE
gesampelt werden, oder wennFRAGCOORD
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 ist1
, 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 bis1
reicht. Dies ist der Fall, wenn OpenGL zum Rendern verwendet wird. Bei anderen Rendering-Backends ist der Wert dieser Eigenschaft0
, was bedeutet, dass der Bereich der Clipping-Ebene von0
bis1
reicht. Dieser Wert ist bei bestimmten Techniken nützlich, bei denen dieDEPTH_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. WennNEAR_CLIP_VALUE
-1
ist, wird der Tiefenwert so skaliert, dass er zwischen-1
und1
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ürMODEL_MATRIX
, einschließlich der Instanztransformation.INSTANCE_MODELVIEWPROJECTION_MATRIX
-> mat4, Ersatz fürMODELVIEWPROJECTION_MATRIX
, einschließlich der Instanztransformation.INSTANCE_COLOR
-> vec4, die Instanzfarbe: zu kombinieren mitCOLOR
.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
odersampler2DArray
) 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 vonSCREEN_TEXTURE
. Oft wirdSCREEN_TEXTURE
in Kombination mitBASE_COLOR
inMAIN
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
einsampler2DArray
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 mitSCREEN_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 immerSCREEN_TEXTURE
, es sei denn, das benutzerdefinierte Material implementiert eine Technik, die auf die Mip-Levels der Textur angewiesen ist (z. B. die Verwendung vontextureLod
im Shader).DEPTH_TEXTURE
- Wenn vorhanden, wird eine Textur (sampler2D
odersampler2DArray
) 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
einsampler2DArray
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
odersampler2DArray
) 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
einesampler2DArray
. Verwenden SieVIEW_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 mitDEPTH_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 |
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.
Konstante | Wert |
---|---|
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
.
Konstante | Wert |
---|---|
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.
Konstante | Wert |
---|---|
CustomMaterial.Unshaded | |
CustomMaterial.Shaded |
sourceAlphaBlend : enumeration |
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.
Konstante | Wert |
---|---|
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
.
Konstante | Wert |
---|---|
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.