Sur cette page

CustomMaterial QML Type

Composant de base permettant de créer des matériaux personnalisés utilisés pour l'ombrage des modèles. En savoir plus...

Import Statement: import QtQuick3D
Inherits:

Material

Propriétés

Description détaillée

Le matériau personnalisé permet d'utiliser un code de shader personnalisé pour un matériau, ce qui offre une programmabilité au niveau du shader graphique. Il est possible de fournir un shader de sommet, un shader de fragment, ou les deux. Les propriétés vertexShader et fragmentShader sont des URL faisant référence à des fichiers contenant des extraits de shaders ; elles fonctionnent de manière très similaire à ShaderEffect ou Image.source. Seuls les schémas file et qrc sont pris en charge avec les matériaux personnalisés. Il est également possible d’omettre le schéma file, ce qui permet de spécifier un chemin relatif de manière pratique. Ce chemin est résolu par rapport à l’emplacement du composant (le fichier .qml ).

Pour un guide de prise en main des matériaux personnalisés, consultez la page « Matériaux, effets, géométrie et données de texture programmables ».

Introduction

Considérons les versions suivantes d’une même scène. À gauche, le cylindre utilise un matériau intégré non programmable. Ces matériaux sont configurables via un large éventail de propriétés, mais ne permettent aucun contrôle supplémentaire sur les shaders générés en arrière-plan. À droite, le même cylindre est désormais associé à un CustomMaterial faisant référence à des extraits de shaders de sommets et de fragments fournis par l’application. Cela permet d’insérer une logique personnalisée, spécifique à l’application, dans le shader de sommets afin de transformer la géométrie, et de déterminer certaines propriétés de couleur de manière personnalisée dans le shader de fragments. Comme il s’agit d’un matériau personnalisé de type « shaded », le cylindre participe toujours normalement à l’éclairage de la scène.

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 }
            }
        ]
    }
}

Supposons que les extraits de shaders dans material.vert et material.frag soient les suivants :

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

Remarquez que uTime et uAmplitude sont des propriétés de l’élément CustomMaterial. Leurs valeurs peuvent être modifiées et animées normalement ; elles seront automatiquement mises à la disposition des shaders sans aucune intervention supplémentaire de la part du développeur.

Le résultat est un cylindre dont les sommets s’animent :

Cylindre courbé avec shader de sommet personnalisé

Deux types de matériaux personnalisés

Il existe deux types principaux de matériaux personnalisés. Ceux-ci sont spécifiés par la propriété ` shadingMode `. Dans les matériaux de type « unshaded », le shader de fragment génère une seule couleur d’ vec4, en ignorant les lumières, les sondes d’éclairage et les ombres de la scène. Dans les matériaux de type « shaded », le shader doit implémenter certaines fonctions et utiliser des variables intégrées pour prendre en compte l’éclairage et les ombres.

Le choix par défaut est généralement un matériau ombré, ce qui se reflète dans la valeur par défaut de la propriété shadingMode. Cela convient aux matériaux qui doivent transformer les sommets ou d’autres données provenant de la géométrie, ou déterminer des valeurs telles que BASE_COLOR ou EMISSIVE_COLOR de manière personnalisée, par exemple en échantillonnant SCREEN_TEXTURE ou DEPTH_TEXTURE, tout en continuant à recevoir les contributions de l’éclairage et des ombres de la scène. De plus, ces matériaux peuvent également remplacer et réimplémenter les équations utilisées pour calculer les contributions des lumières directionnelles, ponctuelles et autres. Les extraits de shaders fournis par l’application sont largement modifiés en arrière-plan par le moteur 3D d’ Qt Quick, afin d’offrir les fonctionnalités, telles que l’éclairage, dont disposent les matériaux standard.

Les matériaux non ombrés sont utiles lorsque l’apparence de l’objet est entièrement déterminée par le code de shader personnalisé. Les shaders de ces matériaux ne subissent que des modifications minimes de la part du moteur ; c’est donc entièrement au shader qu’il revient de déterminer la couleur finale du fragment. Cela offre davantage de liberté, mais limite également les possibilités d’intégration avec d’autres éléments de la scène, tels que les lumières.

Remarque : le codede shader est toujours fourni au format GLSL de type Vulkan, quelle que soit l’API graphique utilisée par Qt lors de l’exécution.

Remarque : le code des shaders de sommets et de fragments fourni par le matériau ne constitue pas en soi des shaders GLSL complets. Il fournit plutôt un ensemble de fonctions, qui sont ensuite complétées par du code de shader supplémentaire ajouté par le moteur.

Mise à disposition des données pour les shaders

Les propriétés dynamiques du CustomMaterial peuvent être modifiées et animées à l'aide de QML et des fonctionnalités d'Qt Quick, et leurs valeurs sont automatiquement mises à la disposition des shaders. En pratique, cela fonctionne de manière très similaire à ShaderEffect. La liste suivante indique comment les propriétés sont mappées :

  • bool, int, real → bool, int, float
  • QColor, color → vec4, et la couleur est convertie en espace linéaire, en supposant un espace sRGB pour la valeur de couleur spécifiée dans QML. Les couleurs intégrées de Qt, telles que "green", sont également dans l’espace de couleurs sRGB, et la même conversion est effectuée pour toutes les propriétés de couleur de DefaultMaterial et PrincipledMaterial; ce comportement de CustomMaterial correspond donc à celui-ci. Contrairement à Qt Quick, pour Qt Quick, la linéarisation 3D est essentielle car un mappage de tons est généralement appliqué à la scène 3D.
  • 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, la valeur scalaire est w
  • TextureInput -> sampler2D ou samplerCube, selon que Texture ou CubeMapTexture est utilisé dans la propriété texture de l’ TextureInput. Définir la propriété enabled sur false expose une texture factice au shader, ce qui signifie que les shaders restent fonctionnels mais échantillonneront une texture dont le contenu est une image noire opaque. Il est important de noter que les propriétés des échantillonneurs doivent toujours faire référence à un objet ` TextureInput `, et non directement à un ` Texture `. En ce qui concerne les propriétés Texture, seules celles liées à la source, au mosaïquage et au filtrage sont prises en compte implicitement avec les matériaux personnalisés, les autres (telles que les transformations UV) devant être implémentées par les shaders personnalisés comme bon leur semble.

Remarque : lorsqu’un uniforme référencé dans le code du shader ne dispose pas d’une propriété correspondante, cela provoque une erreur de compilation du shader lors du traitement du matériau à l’exécution. Il existe quelques exceptions à cette règle, comme les uniformes d’échantillonneur, auxquels une texture factice est associée en l’absence de propriété QML correspondante, mais en règle générale, tous les uniformes et échantillonneurs doivent avoir une propriété correspondante déclarée dans l’objet CustomMaterial.

Matériaux personnalisés sans ombrage

Voici un exemple de matériau personnalisé de type « 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"
}

Dans l'exemple ci-dessus, les extraits de code des shaders de sommets et de fragments « unshaded » pourraient ressembler à ce qui suit. Notez que les shaders ne déclarent pas, et ne doivent pas déclarer, d’uniformes ni d’entrées de sommets, car Qt s’en charge lors de l’assemblage du code final du shader.

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;
}

Les mots-clés spéciaux suivants, en majuscules, sont disponibles :

  • MAIN -> le nom du point d'entrée dans l'extrait de shader de sommet ou de fragment doit toujours être MAIN. La définition de cette fonction est obligatoire dans les extraits de shader pour les matériaux personnalisés non ombrés.
  • VARYING -> déclare une sortie du shader de sommet ou une entrée du shader de fragment
  • POSITION -> vec4, la sortie du shader de sommet
  • FRAGCOLOR -> vec4, la sortie du shader de fragment. Disponible uniquement pour les matériaux personnalisés non ombrés.
  • VERTEX -> vec3, la position du sommet dans le shader de sommets.
  • NORMAL -> vec3, la normale du sommet dans le shader de sommet. Lorsque le maillage du modèle associé ne fournit pas de normales, la valeur est vec3(0,0).
  • UV0 -> vec2, le premier jeu de coordonnées de texture dans le shader de sommets. Lorsque le maillage du modèle associé ne fournit pas de coordonnées de texture, la valeur est vec2(0,0).
  • UV1 -> vec2, le deuxième jeu de coordonnées de texture dans le shader de sommet. Lorsque le maillage du modèle associé ne fournit pas de deuxième jeu de coordonnées de texture, la valeur est vec2(0,0).
  • COLOR -> vec4 : la couleur de sommet dans le shader de sommets. Lorsque le maillage du modèle associé ne fournit pas de couleurs par sommet, la valeur est vec4(1,0).
  • TANGENT -> vec3, la tangente dans le shader de sommets. Lorsque le maillage du modèle associé ne fournit pas de données de tangente, la valeur est vec3(0,0).
  • BINORMALE -> vec3, la binormale dans le shader de sommet. Lorsque le maillage du modèle associé ne fournit pas de données de binormale, la valeur est vec3(0,0).
  • JOINTS -> ivec4, indices d’articulation dans le shader de sommets. Lorsque le maillage du modèle associé ne fournit pas de données d’indices d’articulation, la valeur est ivec4(0).
  • WEIGHTS -> vec4, poids des articulations dans le shader de sommets. Lorsque le maillage du modèle associé ne fournit pas de données de poids d'articulations, la valeur est vec4(0,0).
  • MORPH_POSITION(n) -> vec3, la n+1eposition de cible de morph dans le shader de sommets. Le modèle associé doit fournir les données appropriées.
  • MORPH_NORMAL(n) -> vec3, la normale de la n+1ecible de morph dans le shader de sommets. Le modèle associé doit fournir les données appropriées.
  • MORPH_TANGENT(n) -> vec3, la tangente de la n+1ecible de morph dans le shader de sommets. Le modèle associé doit fournir les données appropriées.
  • MORPH_BINORMAL(n) -> vec3, la binormale de la n+1ecible de morphing dans le shader de sommets. Le modèle associé doit fournir les données appropriées.
  • MODELVIEWPROJECTION_MATRIX -> mat4, la matrice modèle-vue-projection. Les matrices de projection respectent toujours les conventions OpenGL, avec une transformation intégrée pour la direction de l’axe Y et la profondeur de découpe, en fonction de l’API graphique utilisée lors de l’exécution.
  • VIEWPROJECTION_MATRIX -> mat4, la matrice vue-projection
  • PROJECTION_MATRIX -> mat4, la matrice de projection
  • INVERSE_PROJECTION_MATRIX -> mat4, la matrice de projection inverse
  • VIEW_MATRIX -> mat4, la matrice de vue (caméra)
  • MODEL_MATRIX -> mat4, la matrice du modèle (monde)
  • NORMAL_MATRIX -> mat3, la matrice des normales (la transposée de l'inverse de la partie 3x3 située en haut à gauche de la matrice du modèle)
  • BONE_TRANSFORMS -> mat4[], le tableau des matrices d'os du modèle
  • BONE_NORMAL_TRANSFORMS -> mat3[], le tableau des matrices normales des os du modèle (la transposée de l'inverse de la partie 3x3 située en haut à gauche de chaque matrice d'os)
  • MORPH_WEIGHTS -> float[], le tableau des poids de morphes. Le modèle associé doit fournir les données appropriées. Par mesure de sécurité, QT_MORPH_MAX_COUNT est défini à la taille de ce tableau.
  • CAMERA_POSITION -> vec3, la position de la caméra dans l'espace mondial
  • CAMERA_DIRECTION -> vec3, le vecteur de direction de la caméra
  • CAMERA_PROPERTIES -> vec2, les valeurs de clip proche et lointain pour la caméra
  • POINT_SIZE -> float, modifiable uniquement dans le shader de sommets. Lors du rendu d’une géométrie présentant une topologie de points, le shader de sommets personnalisé doit définir cette valeur soit à 1,0, soit à une autre valeur, tant pour les matériaux personnalisés ombrés que non ombrés. Consultez PrincipledMaterial::pointSize pour plus d’informations sur la prise en charge de tailles autres que 1.

Matériaux personnalisés ombrés

Un matériau de type ` shaded ` augments le code de shader qui serait généré par un ` PrincipledMaterial`. Contrairement aux matériaux non ombrés, qui fournissent eux-mêmes la quasi-totalité de la logique pour les fonctions principales des shaders de sommets et de fragments, empêchant ainsi l’ajout de code généré pour l’éclairage, les ombres, l’éclairage global, etc., les matériaux ombrés permettent à la génération de shaders de se dérouler normalement, comme si le `CustomMaterial` était un ` PrincipledMaterial`. Les extraits de code des shaders de sommets et de fragments sont censés fournir des fonctions optionnelles qui sont ensuite appelées à certains moments, ce qui permet de personnaliser les couleurs et autres valeurs utilisées pour le calcul de l'éclairage et de la couleur finale du fragment.

Plutôt que de se contenter d’implémenter une simple fonction ` MAIN `, le shader de fragment d’un matériau personnalisé ombré peut implémenter plusieurs fonctions. Toutes les fonctions, y compris ` MAIN`, sont facultatives dans les matériaux personnalisés ombrés. Un extrait de shader vide, voire l’absence totale de spécification des propriétés ` vertexShader ` ou ` fragmentShader `, est également tout à fait valable.

Extraits de shader de sommets dans un matériau personnalisé ombré

Les fonctions suivantes peuvent être implémentées dans un extrait de shader de sommets :

  • void MAIN() Lorsqu’elle est présente, cette fonction est appelée afin de définir la valeur de POSITION, la sortie vec4 du shader de sommets, et, de manière facultative, de modifier les valeurs de VERTEX, COLOR, NORMAL, UV0, UV1, TANGENT, BINORMAL, JOINTS et WEIGHTS. Contrairement aux matériaux non ombrés, il est pertinent d’écrire dans ces variables car les valeurs modifiées sont ensuite prises en compte dans le reste du code de shader généré (alors que pour les matériaux non ombrés, aucun code de shader supplémentaire n’est généré). Par exemple, si le shader de sommets personnalisé déplace les sommets ou les normales, il devra stocker les valeurs modifiées dans VERTEX ou NORMAL, afin de permettre ensuite des calculs d’éclairage corrects. De plus, la fonction peut écrire dans des variables définies avec ` VARYING ` afin de transmettre des données interpolées au shader de fragment. Lorsque cette fonction ou une redéfinition de ` POSITION ` n’est pas présente, ` POSITION ` est calculé à partir de ` VERTEX ` et ` MODELVIEWPROJECTION_MATRIX`, exactement comme le ferait un shader de PrincipledMaterial.

    Exemple, utilisant à la fois les propriétés QML exposées en tant qu’uniformes et transmettant également des données au shader de fragment :

    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);
    }

    Remarque : dans l’exemple ci-dessus, l’affectation d’une valeur à ` POSITION ` est facultative, car l’utilisation dans ce cas est identique au comportement par défaut.

Remarque : pour transmettre des données sans interpolation de l’étape des sommets à celle des fragments, ajoutez le mot-clé flat avant le type dans les déclarations VARYING.

Extraits de shaders de fragment dans un matériau personnalisé avec ombrage

Les fonctions suivantes peuvent être implémentées dans un extrait de shader de fragment :

  • void MAIN() Lorsqu’elle est présente, cette fonction est appelée pour définir les valeurs des variables spéciales modifiables BASE_COLOR, METALNESS, ROUGHNESS, SPECULAR_AMOUNT, NORMAL, CLEARCOAT_FRESNEL_POWER, CLEARCOAT_FRESNEL_SCALE, CLEARCOAT_FRESNEL_BIAS, CLEARCOAT_AMOUNT, CLEARCOAT_ROUGHNESS, CLEARCOAT_NORMAL, FRESNEL_BIAS, FRESNEL_SCALE, FRESNEL_POWER, IOR, TRANSMISSION_FACTOR, THICKNESS_FACTOR, ATTENUATION_COLOR, ATTENUATION_DISTANCE et OCCLUSION_AMOUNT.

    Un cas d’utilisation courant consiste à définir la valeur de ` BASE_COLOR ` à partir d’un échantillonnage de texture, qu’il s’agisse d’une carte de couleur de base, d’une ` SCREEN_TEXTURE` ou de tout autre type de source. Cela peut s’avérer pertinent et pratique, en particulier lorsqu’aucune fonction de traitement de l’éclairage personnalisée n’est implémentée. Définir BASE_COLOR.a sur une valeur autre que la valeur par défaut 1,0 permet d’influencer la valeur alpha finale du fragment. (Notez que cela nécessitera souvent d’activer également le mélange alpha dans sourceBlend et destinationBlend)

    Un autre cas de figure se présente lorsqu’aucune fonction personnalisée « SPECULAR_LIGHT » n’est fournie, ou lorsqu’une sonde de lumière est définie dans SceneEnvironment. La métallicité, la rugosité et les autres valeurs qui influencent le calcul de la contribution spéculaire peuvent être définies dans MAIN selon les valeurs personnalisées souhaitées.

    La fonction peut écrire dans les variables spéciales suivantes. Les valeurs qui y sont écrites sont généralement soit codées en dur, soit calculées à partir de propriétés QML mappées à des variables uniformes. La sémantique est identique à celle de ` PrincipledMaterial`.

    • vec4 BASE_COLOR - Couleur de base et valeur alpha du matériau. Correspond à built-in materials' color property. Lorsque les fonctions du processeur d’éclairage ne sont pas implémentées, il peut être pratique de définir une couleur de base personnalisée dans MAIN, car celle-ci est alors prise en compte dans les calculs d’éclairage par défaut. La valeur par défaut est vec4(1.0), ce qui correspond à du blanc avec un alpha de 1,0. La valeur alpha influe sur l’alpha final du fragment. La valeur alpha finale correspond à l’opacité de l’objet (modèle) multipliée par l’alpha de la couleur de base. Lorsque vous spécifiez la valeur directement dans le code du shader, sans vous appuyer sur les valeurs uniformes exposées par les propriétés de couleur dans QML, sachez qu’il incombe au shader d’effectuer la conversion sRGB vers linéaire, si nécessaire. Par exemple, en supposant une vec3 color et une float alpha, cela peut être réalisé comme suit :
      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 - La couleur de l’auto-illumination. Correspond à la couleur émissive des matériaux intégrés, qui est définie par built-in materials's emissiveFactor property et built-in materials's emissiveMap property. La valeur par défaut est vec3(0.0). Lorsque vous spécifiez la valeur directement dans le code du shader, sans vous appuyer sur les valeurs uniformes exposées par les propriétés de couleur dans QML, sachez qu’il incombe au shader d’effectuer la conversion de sRGB en espace linéaire, si nécessaire.
    • float IOR Spécifie l’indice de réfraction du matériau. Une valeur courante, qui est également la valeur par défaut, est 1.5, car c’est celle qu’utiliserait un PrincipledMaterial.
    • 0.0 float TRANSMISSION_FACTOR Spécifie le degré de translucidité. Une valeur courante, qui est également la valeur par défaut, est 1.0, car c’est celle qu’utiliserait un PrincipledMaterial.
    • float THICKNESS_FACTOR Spécifie l’épaisseur du matériau translucide. Une valeur courante serait 10.0; la valeur par défaut est 0.0, car c’est celle utilisée par PrincipledMaterial.
    • vec3 ATTENUATION_COLOR Spécifie le décalage de couleur du matériau translucide en fonction de la distance. Une valeur typique, qui est également la valeur par défaut, serait vec3(1.0, 0.0, 0.0), soit vec3(1.0), ce qui correspond à la valeur utilisée par un PrincipledMaterial.
    • 0.0 float ATTENUATION_DISTANCE Spécifie l’atténuation en fonction de la distance du décalage de couleur du matériau translucide. Une valeur typique, qui est également la valeur par défaut, est 100.0, car c’est celle qu’utiliserait un PrincipledMaterial.
    • float METALNESS Niveau de métallicité compris entre 0,0 et 1,0. La valeur par défaut est 0. Doit être défini sur une valeur non nulle pour avoir un effet.
    • float ROUGHNESS Valeur de rugosité comprise entre 0,0 et 1,0. La valeur par défaut est 0.
    • float CLEARCOAT_FRESNEL_POWER Spécifie la puissance de Fresnel de la couche de vernis transparent. Une valeur typique, qui est également la valeur par défaut, est 5.0, car c’est celle qu’utiliserait un PrincipledMaterial.
    • float CLEARCOAT_FRESNEL_SCALE Spécifie l’échelle de Fresnel de la couche de vernis. Une valeur courante, qui est également la valeur par défaut, est 1.0, car c’est celle qu’utiliserait un PrincipledMaterial.
    • float CLEARCOAT_FRESNEL_BIAS Spécifie le biais de Fresnel de la couche de vernis. Une valeur courante, qui est également la valeur par défaut, est 0.0, car c’est celle qu’utiliserait un « PrincipledMaterial ».
    • 0.0 float CLEARCOAT_AMOUNT Spécifie l’épaisseur de la couche de vernis sur le matériau. Une valeur typique, qui est également la valeur par défaut, est 1.0, car c’est celle qu’utiliserait un PrincipledMaterial.
    • float CLEARCOAT_ROUGHNESS Spécifie la rugosité de la couche de vernis. Une valeur typique, qui correspondrait à 1.0 pour une couche de vernis entièrement floue, est également la valeur par défaut, à savoir 0.0, car c’est celle qu’utiliserait un PrincipledMaterial.
    • vec3 CLEARCOAT_NORMAL - La normale de la couche de vernis provenant du shader de sommets dans l’espace mondial. Bien que cette propriété ait la même valeur initiale que VAR_WORLD_NORMAL, seule la modification de la valeur de CLEARCOAT_NORMAL aura un effet sur la normale de la couche de vernis.
    • float FRESNEL_POWER Spécifie la puissance de Fresnel. Une valeur courante, qui est également la valeur par défaut, est 5.0, car c’est celle qu’utiliserait un PrincipledMaterial.
    • float FRESNEL_SCALE Spécifie l'échelle de Fresnel. Une valeur courante, qui est également la valeur par défaut, est 1.0, car c'est celle utilisée par PrincipledMaterial.
    • float FRESNEL_BIAS Spécifie le biais de Fresnel. Une valeur courante, qui est également la valeur par défaut, est 0.0, car c’est celle qu’utiliserait un « PrincipledMaterial ».
    • float SPECULAR_AMOUNT Intensité de la réflexion spéculaire comprise entre 0,0 et 1,0. La valeur par défaut est 0.5, ce qui correspond à PrincipledMaterial::specularAmount. Doit être définie sur une valeur non nulle pour être prise en compte.
    • float OCCLUSION_AMOUNT Spécifie le facteur AO. Une valeur courante, qui est également la valeur par défaut, est 1.0, car c’est celle qu’utiliserait un PrincipledMaterial.
    • vec3 NORMAL - La normale provenant du shader de sommets dans l’espace mondial. Bien que cette propriété ait la même valeur initiale que VAR_WORLD_NORMAL, seule la modification de la valeur de NORMAL aura un effet sur l’éclairage.
    • vec3 TANGENT - La tangente provenant du shader de sommets dans l'espace mondial. Cette valeur est susceptible d'être ajustée en fonction de la double face.
    • vec3 BINORMAL - La binormale provenant du shader de sommets dans l'espace mondial. Cette valeur est susceptible d'être ajustée pour tenir compte de la double face.
    • vec2 UV0 - Le premier ensemble de coordonnées de texture provenant du shader de sommets. Cette propriété est en lecture seule dans le shader de fragments.
    • vec2 UV1 - Le deuxième ensemble de coordonnées de texture provenant du shader de sommets. Cette propriété est en lecture seule dans le shader de fragments.

    MAIN Remarque : contrairement aux matériaux non ombrés, les coordonnées de texture de fragment d’un matériau ombré n’ont aucun contrôle direct sur FRAGCOLOR. Ce sont plutôt les valeurs DIFFUSE et SPECULAR définies dans les fonctions du processeur de lumière qui déterminent la couleur finale du fragment. Lorsqu’une fonction du processeur de lumière n’est pas implémentée, les calculs d’ombrage par défaut correspondants sont effectués comme pour un PrincipledMaterial, en tenant compte de BASE_COLOR et des autres valeurs de la liste ci-dessus.

    Voici un exemple de shader simple pour un matériau personnalisé de type métallique :

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

    Voici un autre exemple, dans lequel la couleur de base et la transparence sont définies par échantillonnage d'une texture :

    VARYING vec2 texcoord;
    void MAIN()
    {
        BASE_COLOR = texture(uColorMap, texcoord);
    }
  • void AMBIENT_LIGHT() Lorsqu’elle est présente, cette fonction est appelée une fois pour chaque fragment. Son rôle est d’ajouter la contribution ambiante totale à une variable spéciale modifiable, DIFFUSE. Elle peut bien sûr choisir de calculer une valeur différente, ou de ne pas modifier DIFFUSE du tout (pour ignorer complètement l’éclairage ambiant). Lorsque cette fonction est totalement absente, la contribution ambiante est calculée normalement, comme le ferait un « PrincipledMaterial ».

    La fonction peut écrire dans les variables spéciales suivantes :

    • vec3 DIFFUSE Accumule les contributions de lumière diffuse, par fragment. Les fonctions du processeur de lumière y ajouteront généralement (+=), car écraser la valeur ferait perdre la contribution des autres lumières.

    La fonction peut lire les variables spéciales suivantes, en plus des uniformes de type matrice (tels que MODEL_MATRIX) et de type vecteur (tels que CAMERA_POSITION) du tableau ci-dessus :

    • vec3 TOTAL_AMBIENT_COLOR La contribution ambiante totale dans la scène.

    Exemple :

    void AMBIENT_LIGHT()
    {
        DIFFUSE += TOTAL_AMBIENT_COLOR;
    }
  • void DIRECTIONAL_LIGHT() Lorsqu’elle est présente, cette fonction est appelée pour chaque lumière directionnelle active de la scène, pour chaque fragment. Cette fonction a pour rôle d’ajouter la contribution diffuse à une variable spéciale modifiable DIFFUSE. La fonction peut également choisir de ne rien faire, auquel cas les contributions diffuses des lumières directionnelles sont ignorées. Lorsque la fonction est totalement absente, les contributions diffuses des lumières directionnelles sont cumulées normalement, comme le ferait un processeur de lumière ( PrincipledMaterial ).

    La fonction peut écrire dans les variables spéciales suivantes :

    • vec3 DIFFUSE Accumule les contributions de lumière diffuse, par fragment. Les fonctions du processeur de lumière y ajouteront généralement (+=), car écraser cette valeur ferait perdre la contribution des autres lumières.

    La fonction peut lire les variables spéciales suivantes, en plus des uniformes de type matrice (par exemple, MODEL_MATRIX) et de type vecteur (par exemple, CAMERA_POSITION) du tableau ci-dessus :

    • vec3 LIGHT_COLOR Couleur de la lumière diffuse.
    • float SHADOW_CONTRIB Contribution de l’ombre, ou 1,0 s’il n’y a pas d’ombre du tout ou si le fragment ne reçoit pas d’ombres.
    • vec3 TO_LIGHT_DIR Vecteur pointant vers la source lumineuse.
    • vec3 NORMAL Le vecteur normal dans l’espace mondial.
    • vec4 BASE_COLOR La couleur de base et la valeur alpha du matériau.
    • float METALNESS Le niveau de métallicité.
    • float ROUGHNESS Le niveau de rugosité.

    Exemple :

    void DIRECTIONAL_LIGHT()
    {
        DIFFUSE += LIGHT_COLOR * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(VAR_WORLD_NORMAL), TO_LIGHT_DIR)));
    }
  • void POINT_LIGHT() Lorsqu’elle est présente, cette fonction est appelée pour chaque lumière ponctuelle active de la scène, pour chaque fragment. Cette fonction a pour rôle d’ajouter la contribution diffuse à une variable spéciale modifiable DIFFUSE. La fonction peut également choisir de ne rien faire, auquel cas les contributions diffuses des lumières ponctuelles sont ignorées. Lorsque la fonction est totalement absente, les contributions diffuses des lumières ponctuelles sont cumulées normalement, comme le ferait un « PrincipledMaterial ».

    La fonction peut écrire dans les variables spéciales suivantes :

    • vec3 DIFFUSE Accumule les contributions de lumière diffuse, par fragment.

    La fonction peut lire les variables spéciales suivantes, en plus des uniformes de type matrice (tels que MODEL_MATRIX) et de type vecteur (tels que CAMERA_POSITION) du tableau ci-dessus :

    • vec3 LIGHT_COLOR Couleur de la lumière diffuse.
    • float LIGHT_ATTENUATION Atténuation de la lumière.
    • float SHADOW_CONTRIB Contribution à l’ombre, ou 1,0 s’il n’y a pas d’ombre du tout ou si l’objet ne reçoit pas d’ombres.
    • vec3 TO_LIGHT_DIR Vecteur pointant vers la source lumineuse.
    • vec3 NORMAL Vecteur normal dans l’espace mondial.
    • vec4 BASE_COLOR Couleur de base et valeur alpha du matériau.
    • float METALNESS Niveau de métallicité.
    • float ROUGHNESS Niveau de rugosité.

    Exemple :

    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() Lorsqu’elle est présente, cette fonction est appelée pour chaque spot actif de la scène, pour chaque fragment. Le rôle de cette fonction est d’ajouter la contribution diffuse à une variable spéciale modifiable DIFFUSE. La fonction peut également choisir de ne rien faire, auquel cas les contributions diffuses des spots sont ignorées. Lorsque la fonction est totalement absente, les contributions diffuses des projecteurs ponctuels sont cumulées normalement, comme le ferait un « PrincipledMaterial ».

    La fonction peut écrire dans les variables spéciales suivantes :

    • vec3 DIFFUSE Cumul des contributions de lumière diffuse, par fragment.

    La fonction peut lire les variables spéciales suivantes, en plus des uniformes de matrice (tels que MODEL_MATRIX) et de vecteur (tels que CAMERA_POSITION) du tableau ci-dessus :

    • vec3 LIGHT_COLOR Couleur de la lumière diffuse.
    • float LIGHT_ATTENUATION Atténuation de la lumière.
    • float SHADOW_CONTRIB Contribution de l’ombre, ou 1,0 s’il n’y a pas d’ombre du tout ou si le fragment ne reçoit pas d’ombres.
    • vec3 TO_LIGHT_DIR Vecteur pointant vers la source lumineuse.
    • float SPOT_FACTOR Facteur de lumière ponctuelle.
    • vec3 NORMAL Vecteur normal dans l’espace mondial.
    • vec4 BASE_COLOR Couleur de base et valeur alpha du matériau.
    • float METALNESS Valeur de métallicité.
    • float ROUGHNESS Valeur de rugosité.

    Exemple :

    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() Lorsqu’elle est présente, cette fonction est appelée pour chaque lumière active de la scène, pour chaque fragment. La fonction a pour tâche d’ajouter la contribution spéculaire à une variable spéciale modifiable SPECULAR. La fonction peut également choisir de ne rien faire, auquel cas les contributions spéculaires des lumières sont ignorées. Lorsque la fonction est totalement absente, les contributions spéculaires des lumières sont cumulées normalement, comme le ferait un « PrincipledMaterial ».

    La fonction peut écrire dans les variables spéciales suivantes :

    • vec3 SPECULAR Cumulent les contributions spéculaires des lumières, par fragment. Les fonctions du processeur de lumière y ajouteront généralement (+=), car écraser la valeur entraînerait la perte de la contribution des autres lumières.

    La fonction peut lire les variables spéciales suivantes, en plus des uniformes de matrice (tels que MODEL_MATRIX) et de vecteur (tels que CAMERA_POSITION) du tableau ci-dessus :

    • vec3 LIGHT_COLOR Couleur de la lumière spéculaire.
    • float LIGHT_ATTENUATION Atténuation de la lumière. Pour les lumières directionnelles, la valeur est 1
    • ,
    • 0. Pour les lumières ponctuelles, la valeur est identique à celle de LIGHT_ATTENUATION * SPOT_FACTOR de void SPOT_LIGHT().
    • float SHADOW_CONTRIB Contribution de l’ombre, ou 1,0 s’il n’y a pas d’ombre du tout ou si l’objet ne reçoit pas d’ombres.
    • vec3 FRESNEL_CONTRIB Contribution de Fresnel issue du calcul de Fresnel intégré
    • .
    • vec3 TO_LIGHT_DIR Vecteur pointant vers la source lumineuse.
    • vec3 NORMAL Le vecteur normal dans l’espace mondial.
    • vec4 BASE_COLOR La couleur de base et la valeur d’alpha du matériau.
    • float METALNESS Le niveau de métallicité.
    • float ROUGHNESS Le niveau de rugosité.
    • float SPECULAR_AMOUNT L'intensité de la réflexion spéculaire. Cette valeur, comprise entre 0,0 et 1,0, correspondra à celle définie dans la fonction personnalisée MAIN. Elle sera utile pour calculer les contributions de Fresnel lorsque l'on n'utilise pas la contribution de Fresnel intégrée fournie par FRESNEL_CONTRIB.
    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() Lorsqu'elle est présente, cette fonction est appelée à la fin du pipeline de fragments. Cette fonction a pour rôle de finaliser COLOR_SUM avec les termes diffus, spéculaires et émissifs finaux. Contrairement à FRAGCOLOR pour un matériau non ombré, COLOR_SUM sera automatiquement soumis à un tonemapping avant d’être écrit dans le framebuffer. À des fins de débogage, il est parfois utile de renvoyer une valeur qui ne doit pas être traitée comme une couleur. Pour éviter que le tonemapping ne déforme cette valeur, il est possible de le désactiver en définissant la propriété ` tonemapMode ` sur

    `

    TonemapModeNone

    `

    • .

    La fonction peut écrire dans les variables spéciales suivantes :

    • vec4 ` COLOR_SUM `

    :

    • la sortie du shader de fragment. La valeur par défaut est `vec4(DIFFUSE.rgb + SPECULAR + EMISSIVE, DIFFUSE.a)`.

    La fonction peut lire les variables spéciales suivantes.

    • vec4 DIFFUSE: le terme diffus final du pipeline de fragments.
    • vec3 SPECULAR: le terme spéculaire final du pipeline de fragments.
    • vec3 EMISSIVE: le terme émissif final du pipeline de fragments.
    • vec2 UV0: le premier jeu de coordonnées de texture provenant du shader de sommets.
    • vec2 UV1 - Le deuxième ensemble de coordonnées de texture provenant du shader de sommets.
    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() Lorsqu’elle est présente, cette fonction est appelée pour l’IBL (Image-Based Lighting). Elle a pour tâche d’ajouter les contributions diffuses et spéculaires de l’IBL aux variables spéciales modifiables DIFFUSE et SPECULAR.

    La fonction peut écrire dans les variables spéciales suivantes :

    • vec3 DIFFUSE Accumule les contributions de lumière diffuse, par fragment.
    • vec3 SPECULAR Accumule les contributions de lumière spéculaire, par fragment.

    La fonction peut lire les variables spéciales suivantes

      :
    • vec4 BASE_COLOR La couleur de base et la valeur alpha du matériau.
    • float AO_FACTOR Le facteur d'occlusion dans l'espace écran.
    • float SPECULAR_AMOUNT L'intensité spéculaire.
    • float ROUGHNESS Le terme d'émission final du pipeline de fragments.
    • vec3 NORMAL Le vecteur normal dans l'espace mondial.
    • vec3 VIEW_VECTOR Pointe vers la caméra.
    • mat3 IBL_ORIENTATION L'orientation de la sonde lumineuse. Elle provient de SceneEnvironment::probeOrientation.
    void IBL_PROBE()
    {
        vec3 smpDir = IBL_ORIENTATION * NORMAL;
        DIFFUSE += AO_FACTOR * BASE_COLOR.rgb * textureLod(IBL_TEXTURE, smpDir, IBL_MAXMIPMAP).rgb;
    }
  • Variables personnalisées entre les fonctions

    Des variables supplémentaires peuvent être transmises depuis la fonction MAIN vers les autres. Le mot-clé SHARED_VARS permet de définir de nouvelles variables personnalisées. Ces variables définies par l'utilisateur sont accessibles via SHARED.<nom de la variable>.

    Par exemple, un matériau personnalisé ombré peut récupérer une valeur partagée dans la fonction MAIN et l'utiliser dans d'autres fonctions.

    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;
    }

    Remarque : SHARED peut être utilisé dans toutes les fonctions ne comportant pas POST_PROCESS, mais il est plus sûr de l'utiliser dans MAIN et de le lire dans les autres fonctions.

    Remarque : un cas d'utilisation recommandé pour l'utilisation de SHARED dans les fonctions LIGHT consiste à le réinitialiser d'abord dans la fonction MAIN, puis à l'accumuler dans chaque fonction LIGHT.

    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;
    }

    Remarque : la fonction MAIN est appelée avant les autres, et POST_PROCESS après toutes les autres, mais il n’y a aucune garantie quant à l’ordre d’exécution des autres processeurs LIGHT.

    Mots-clés spéciaux supplémentaires

    Le code du shader de fragment personnalisé peut accéder librement aux uniformes (tels que CAMERA_DIRECTION ou CAMERA_POSITION) et aux variables transmises par le shader de sommet personnalisé. De plus, plusieurs variables intégrées sont disponibles sous forme de mots-clés spéciaux. Certains d’entre eux sont facultatifs dans la mesure où un « vertex- MAIN » pourrait les calculer et les transmettre de lui-même, mais afin de réduire la duplication des données, les shaders de fragment peuvent également s’appuyer sur ces variables intégrées. Ces variables intégrées sont disponibles dans les fonctions des processeurs légers et dans la fonction MAIN du shader de fragment.

    • vec3 VAR_WORLD_NORMAL - Normale interpolée transformée par NORMAL_MATRIX.
    • vec3 VAR_WORLD_TANGENT - Tangente interpolée transformée par MODEL_MATRIX.
    • vec3 VAR_WORLD_BINORMAL - Binormale interpolée transformée par MODEL_MATRIX
    • vec3 NORMAL - Contrairement à VAR_WORLD_NORMAL, qui correspond à la normale interpolée telle quelle, cette valeur est susceptible d’être ajustée pour tenir compte de la double face : lors du rendu avec le culling désactivé, la normale sera inversée si nécessaire. Il est donc recommandé, pour l’éclairage et les autres calculs, d’utiliser NORMAL plutôt que VAR_WORLD_NORMAL afin de garantir un comportement correct avec tous les modes de culling.
    • vec3 TANGENT - À l’instar de NORMAL, cette valeur est susceptible d’être ajustée en fonction de la double face : lors du rendu avec le culling désactivé, la tangente sera inversée si nécessaire.
    • vec3 BINORMAL - À l’instar de NORMAL, cette valeur est susceptible d’être ajustée en fonction de la double face : lors du rendu avec le culling désactivé, la binormale sera inversée si nécessaire.
    • vec3 VAR_WORLD_POSITION - Position interpolée du sommet dans l’espace mondial ((MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz)
    • vec4 VAR_COLOR - Couleur du sommet interpolée lorsque des couleurs sont fournies dans le maillage. Sinon, vec4(1.0).
    • vec3 VIEW_VECTOR - Pointe vers la caméra. Il s’agit en fait du vecteur CAMERA_POSITION - VAR_WORLD_POSITION normalisé.
    • vec4 FRAGCOORD - Contient les coordonnées relatives à la fenêtre du fragment actuel.
    • float FRAMEBUFFER_Y_UP - La valeur est 1 lorsque l’axe Y est orienté vers le haut dans le système de coordonnées des framebuffers (textures), ce qui signifie que (0, 0) correspond au coin inférieur gauche. La valeur est -1 lorsque l’axe Y est orienté vers le bas, (0, 0) correspondant alors au coin supérieur gauche. Ces différences entre les API graphiques sous-jacentes ne concernent pas la plupart des matériaux personnalisés. Une exception notable concerne l’échantillonnage d’ SCREEN_TEXTURE s avec des coordonnées de texture ne reposant pas sur FRAGCOORD. L’orientation de SCREEN_TEXTURE étant intrinsèquement liée à l’API graphique sous-jacente, l’utilisation des coordonnées de texture d’un maillage peut nécessiter des ajustements appropriés de la coordonnée Y.

      Par exemple, le shader de fragment suivant, adapté aux maillages de type Rectangle ou Cube, affichera les objets opaques de la scène sur le modèle :

      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);
      }

      Lors de l’échantillonnage de textures autres que SCREEN_TEXTURE et DEPTH_TEXTURE, ou lorsque FRAGCOORD est utilisé pour calculer la coordonnée de texture (ce qui correspond au cas d’utilisation typique pour accéder aux textures d’écran et de profondeur), un tel ajustement n’est pas nécessaire.

    • float NDC_Y_UP - La valeur est 1 lorsque l’axe Y est orienté vers le haut dans l’espace de coordonnées normalisées du périphérique, et -1 lorsque l’axe Y est orienté vers le bas. L’axe Y orienté vers le bas correspond au rendu avec Vulkan. La plupart des matériaux n’ont pas à se soucier de cela, mais la possibilité d’effectuer une branche en fonction de ce paramètre peut s’avérer utile dans certains cas d’utilisation avancés.
    • float NEAR_CLIP_VALUE - La valeur est -1 lorsque la plage des plans de découpe commence à -1 et va jusqu’à 1. C’est le cas lors de l’utilisation d’OpenGL pour le rendu. Pour les autres backends de rendu, la valeur de cette propriété sera 0, ce qui signifie que la plage des plans de découpe va de 0 à 1. Cette valeur est utile avec certaines techniques impliquant le DEPTH_TEXTURE

      Par exemple, le shader de fragment suivant illustre une technique permettant de reconstruire la position d’une valeur à partir du tampon de profondeur afin de déterminer la distance par rapport à la position actuelle en cours de rendu. Lorsqu’elle est utilisée en combinaison avec INVERSE_PROJECTION_MATRIX, la valeur de profondeur doit être exprimée en coordonnées normalisées du périphérique ; il est donc important de s’assurer que la plage des valeurs de profondeur reflète bien cela. Lorsque l’ NEAR_CLIP_VALUE est -1, la valeur de profondeur est alors mise à l’échelle pour se situer entre -1 et 1.

      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 - Quantité de lumière émise par la sonde lumineuse. Elle est dérivée de SceneEnvironment::probeExposure.
      DIFFUSE += AO_FACTOR * IBL_EXPOSE * BASE_COLOR.rgb * textureLod(IBL_TEXTURE, NORMAL, IBL_MAXMIPMAP).rgb;
    • float IBL_HORIZON - Valeur de coupure horizontale des reflets provenant de la moitié inférieure de l’environnement. Elle est issue de Horizon Cut-Off mais remappée sur [-1, 0).
      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 - Le niveau maximal de mipmap de IBL_TEXTURE.

    Instanciation

    Lors d'un rendu instancié, certains des mots-clés ci-dessus ne s'appliquent pas. Les mots-clés suivants ne sont disponibles qu'avec l'instanciation :

    • INSTANCE_MODEL_MATRIX -> mat4, qui remplace MODEL_MATRIX, et inclut la transformation d'instanciation.
    • INSTANCE_MODELVIEWPROJECTION_MATRIX -> mat4, remplace « MODELVIEWPROJECTION_MATRIX », en incluant la transformation d'instanciation.
    • INSTANCE_COLOR -> vec4, la couleur de l'instance : à combiner avec « COLOR ».
    • INSTANCE_DATA -> vec4, données personnalisées de l’instance.
    • INSTANCE_INDEX -> int, le numéro d'instance et l'index dans la table d'instanciation.

    Textures d'écran, de profondeur et autres

    Le pipeline de rendu peut mettre à la disposition des shaders de matériaux personnalisés un certain nombre de textures dont le contenu provient de passes de rendu spéciales. Cela s'applique aussi bien aux matériaux personnalisés ombrés qu'aux matériaux personnalisés non ombrés.

    Par exemple, un shader peut avoir besoin d’accéder à une texture de profondeur contenant le contenu du tampon de profondeur pour les objets opaques de la scène. Pour ce faire, il suffit d’échantillonner DEPTH_TEXTURE. Une telle texture n’est normalement pas générée, sauf en cas de besoin réel. Par conséquent, la présence des mots-clés suivants dans le shader de sommets ou de fragments sert également à activer ou désactiver les passes — potentiellement coûteuses — nécessaires à la génération de la texture en question. (Bien sûr, il se peut que certaines d’entre elles soient déjà activées en raison d’autres paramètres, tels que les paramètres d’occlusion ambiante disponibles à l’adresse SceneEnvironment ou en raison d’un effet de post-traitement s’appuyant sur la texture de profondeur ; dans ce cas, les textures en question sont générées indépendamment du matériau personnalisé et l’échantillonnage de ces textures spéciales dans le matériau n’entraîne donc aucun coût supplémentaire hormis l’accès à la texture lui-même)

    • SCREEN_TEXTURE - Lorsqu’elle est présente, une texture (sampler2D ou sampler2DArray) contenant le tampon de couleur d’un passage de rendu, qui inclut le contenu de la scène à l’exclusion de tout matériau transparent ou de tout matériau utilisant également la texture SCREEN_TEXTURE, est mise à la disposition du shader sous ce nom. Cette texture peut être utilisée pour des techniques nécessitant le contenu du framebuffer sur lequel le rendu est effectué. La texture SCREEN_TEXTURE utilise le même mode d’effacement que la texture « View3D ». La taille de ces textures correspond à celle de l’ View3D, en pixels. Par exemple, un shader de fragment pourrait contenir ce qui suit :
      vec2 uv = FRAGCOORD.xy / vec2(textureSize(SCREEN_TEXTURE, 0));
      vec2 displace = vec2(0.1);
      vec4 c = texture(SCREEN_TEXTURE, uv + displace);

      Sachez que l’utilisation de l’ SCREEN_TEXTURE nécessite une conception appropriée et réfléchie de la scène. Les objets utilisant de tels matériaux doivent être positionnés avec soin, généralement au-dessus de tous les autres objets censés être visibles dans la texture. Les objets qui utilisent une forme quelconque de semi-transparence ne font jamais partie de l’ SCREEN_TEXTURE. Souvent, SCREEN_TEXTURE sera utilisé en combinaison avec BASE_COLOR dans MAIN. Par exemple, le shader de fragment personnalisé suivant applique un effet de relief, tout en conservant la transparence des fragments non touchés par des objets opaques. Cela suppose que l’objet doté de ce matériau soit placé au premier plan et que le mélange soit activé.

      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);
      }

      Avec le rendu multivue, ` SCREEN_TEXTURE ` est un ` sampler2DArray`. Utilisez ` VIEW_INDEX ` pour sélectionner le calque à utiliser. Pour les applications VR/AR qui souhaitent prendre en charge les deux types de rendu, l’approche portable est la suivante :

      #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 - Identique à ` SCREEN_TEXTURE ` à bien des égards, la différence étant que cette texture dispose de mipmaps générées. Cette fonctionnalité peut s’avérer coûteuse en termes de performances, selon la taille de l’écran, et du fait que les mipmaps doivent être générées à chaque rendu de la scène. Par conséquent, privilégiez toujours l’utilisation de SCREEN_TEXTURE, sauf si une technique reposant sur les niveaux de mip de la texture (par exemple, l’utilisation de textureLod dans le shader) est implémentée par le matériau personnalisé.
    • DEPTH_TEXTURE - Lorsqu’elle est présente, une texture (sampler2D ou sampler2DArray) contenant le contenu (non linéarisé) du tampon de profondeur est exposée au shader sous ce nom. Seuls les objets opaques sont inclus. Par exemple, un shader de fragment pourrait contenir ce qui suit :
      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;

      Avec le rendu multivue, DEPTH_TEXTURE est un sampler2DArray. Utilisez VIEW_INDEX pour sélectionner la couche à utiliser. Pour les applications de réalité virtuelle (VR) ou de réalité augmentée (AR) qui souhaitent prendre en charge les deux types de rendu, l’approche portable est la suivante :

      #if QSHADER_VIEW_COUNT >= 2
          vec4 depthSample = texture(DEPTH_TEXTURE, vec3(uv, VIEW_INDEX));
      #else
          vec4 depthSample = texture(DEPTH_TEXTURE, uv);
      #endif
    • NORMAL_ROUGHNESS_TEXTURE - Lorsqu’elle est présente, une texture (sampler2D) contenant les normales dans l’espace mondial et la rugosité du matériau est mise à la disposition du shader sous ce nom. Seuls les objets opaques sont pris en compte. La rugosité est stockée dans le canal alpha. Par exemple, un shader de fragment pourrait contenir ce qui suit :
      vec3 N = normalize(texture(NORMAL_ROUGHNESS_TEXTURE, uv).rgb);
    • AO_TEXTURE -
    • Lors
    • qu
    • ’elle
    • est présente et que l’occlusion ambiante dans l’espace écran est activée (c’est-à-dire lorsque l’intensité et la distance de l’AO sont toutes deux non nulles) dans SceneEnvironment, la texture SSAO (sampler2D ou sampler2DArray) est mise à la disposition du shader sous ce nom. L'échantillonnage de cette texture peut s'avérer utile dans les matériaux non ombrés. Les matériaux ombrés intègrent nativement la prise en charge de l'occlusion ambiante. Cela signifie que le facteur d'occlusion ambiante est pris en compte automatiquement. En revanche, dans un shader de fragment pour un matériau non ombré, on pourrait écrire ce qui suit pour obtenir le même résultat :
      ivec2 aoSize = textureSize(AO_TEXTURE, 0);
      vec2 aoUV = (FRAGCOORD.xy) / vec2(aoSize);
      float aoFactor = texture(AO_TEXTURE, aoUV).x;

      Avec le rendu multivue, l’option « AO_TEXTURE » correspond à sampler2DArray. Utilisez VIEW_INDEX pour sélectionner le calque à utiliser. Pour les applications VR/AR qui souhaitent prendre en charge les deux types de rendu, l’approche portable est la suivante :

      #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 - Elle n'active aucun passage de rendu particulier, mais peut être utilisée lorsque le matériau dispose de l'option « Material::lightProbe » ou que le modèle se trouve dans le champ d'application de « SceneEnvironment::lightProbe ».
      void IBL_PROBE()
      {
          DIFFUSE += AO_FACTOR * BASE_COLOR.rgb * textureLod(IBL_TEXTURE, NORMAL, IBL_MAXMIPMAP).rgb;
      }
    • MOTION_VECTOR_TEXTURE — Active un passage de rendu dédié qui calcule les vecteurs de mouvement par objet pour la scène. Le résultat est une texture à quatre canaux : les composantes R et G contiennent les vecteurs de mouvement mis à l’échelle des modèles, tandis que les composantes B et A stockent les vecteurs de mouvement non mis à l’échelle.
    • VIEW_INDEX - Lorsqu’elle est utilisée dans le code d’un shader personnalisé, il s’agit d’une variable uint (non interpolée). Lorsque le rendu multivue n’est pas utilisé, la valeur est toujours 0. Avec le rendu multivue, la valeur correspond à l’index de vue actuel (par exemple, gl_ViewIndex). Particulièrement utile en combinaison avec DEPTH_TEXTURE et des fonctions similaires lorsque le rendu multivue est activé.

    Voir également SceneEnvironment::tonemapMode, Utilisation de l’éclairage basé sur l’image, Qt Quick 3D - Exemple de shaders personnalisés, Qt Quick 3D - Exemple de matériaux personnalisés, et Données programmables relatives aux matériaux, effets, géométrie et textures.

    Documentation sur les propriétés

    alwaysDirty : bool

    Indique que l'état du matériau est toujours « sale », ce qui signifie que le matériau doit être actualisé à chaque fois qu'il est utilisé par l'QtQuick3D.

    destinationAlphaBlend : enumeration [since 6.7]

    Spécifie le facteur de mélange alpha de destination. La valeur par défaut est CustomMaterial.NoBlend. Cette valeur n'est activement utilisée que si les paramètres « sourceBlend » et « destinationBlend » sont définis sur une valeur différente de la valeur par défaut.

    ConstanteDescription
    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

    Remarque : pour des raisons de compatibilité ascendante, lorsque cette propriété est laissée à sa valeur par défaut, elle se voit attribuer la même valeur que destinationBlend lorsque sourceBlend et destinationBlend sont définies sur des valeurs non par défaut.

    Cette propriété a été introduite dans Qt 6.7.

    Voir également destinationBlend.

    destinationBlend : enumeration

    Spécifie le facteur de mélange de destination. La valeur par défaut est CustomMaterial.NoBlend.

    ConstanteDescription
    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

    Remarque : les paramètres « sourceBlend » et « destinationBlend » doiventtous deux être définis sur une valeur autre que celle par défaut avant que le mélange ne soit activé.

    Voir également sourceBlend.

    fragmentShader : url

    Spécifie le fichier contenant l'extrait de code du shader de fragment personnalisé.

    La valeur est une URL et doit correspondre soit à un fichier local, soit utiliser le schéma qrc pour accéder à des fichiers intégrés via le système de ressources Qt. Les chemins d'accès relatifs (sans schéma) sont également acceptés ; dans ce cas, le fichier est considéré comme relatif au composant (le fichier .qml ).

    Avertissement : les extraitsde shader sont considérés comme du contenu fiable. Il est conseillé aux développeurs d’applications d’évaluer soigneusement les implications potentielles avant d’autoriser le chargement de contenu fourni par l’utilisateur qui ne fait pas partie de l’application.

    Voir également vertexShader.

    lineWidth : real

    Cette propriété détermine la largeur des lignes affichées lorsque la géométrie utilise un type de primitive « lignes » ou « bandes de lignes ». La valeur par défaut est 1,0. Cette propriété n'est pas applicable lors du rendu d'autres types de géométrie, tels que les maillages triangulaires.

    Avertissement : les largeursde ligne différentes de 1 peuvent ne pas être prises en charge lors de l'exécution, selon l'API graphique sous-jacente. Dans ce cas, la demande de modification de la largeur est ignorée. Par exemple, aucune des API suivantes ne devrait prendre en charge les lignes larges : Direct3D, Metal, OpenGL avec des contextes de profil de base.

    Remarque : contrairement à la largeur de ligne, dont la valeur fait partie de l’objet du pipeline graphique, la taille des points pour les géométries présentant une topologie de points est contrôlée par le shader de sommets (lorsqu’il est pris en charge) et ne dispose donc d’aucune propriété QML correspondante.

    shadingMode : enumeration

    Spécifie le type de matériau. La valeur par défaut est « Shaded ».

    ConstanteValeur
    CustomMaterial.Unshaded
    CustomMaterial.Shaded

    sourceAlphaBlend : enumeration [since 6.7]

    Spécifie le facteur de mélange alpha de la source. La valeur par défaut est CustomMaterial.NoBlend. Cette valeur n'est effectivement utilisée que si les paramètres « sourceBlend » et « destinationBlend » sont définis sur une valeur autre que celle par défaut.

    ConstanteDescription
    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

    Remarque : pour des raisons de compatibilité ascendante, lorsque cette propriété est laissée à sa valeur par défaut, elle se voit attribuer la même valeur que sourceBlend lorsque sourceBlend et destinationBlend sont définies sur des valeurs non par défaut.

    Cette propriété a été introduite dans Qt 6.7.

    Voir également sourceBlend.

    sourceBlend : enumeration

    Spécifie le facteur de fusion de la source. La valeur par défaut est « CustomMaterial.NoBlend ».

    ConstanteDescription
    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

    Remarque : les paramètres « sourceBlend » et « destinationBlend » doivent être définis sur une valeur autre que celle par défaut avant que la fusion ne soit activée.

    Voir aussi destinationBlend.

    vertexShader : url

    Spécifie le fichier contenant l'extrait de code du shader de sommet personnalisé.

    La valeur est une URL et doit correspondre soit à un fichier local, soit utiliser le schéma qrc pour accéder à des fichiers intégrés via le système de ressources Qt. Les chemins d'accès relatifs (sans schéma) sont également acceptés ; dans ce cas, le fichier est considéré comme relatif au composant (le fichier .qml ).

    Avertissement : les extraitsde shader sont considérés comme du contenu fiable. Il est conseillé aux développeurs d'applications d'évaluer soigneusement les implications potentielles avant d'autoriser le chargement de contenu fourni par l'utilisateur qui ne fait pas partie de l'application.

    Voir également fragmentShader.

    © 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.