Sur cette page

Effect QML Type

Composant de base permettant de créer un effet de post-traitement. En savoir plus...

Import Statement: import QtQuick3D
Inherits:

Object3D

Propriétés

Description détaillée

Le type « Effet » permet à l'utilisateur de mettre en œuvre ses propres effets de post-traitement pour QtQuick3D.

Effets de post-traitement

Un effet de post-traitement est conceptuellement très similaire à l'élément « ShaderEffect » d'Qt Quick. Lorsqu'un effet est présent, la scène est d'abord rendue dans une texture distincte. L'effet est ensuite appliqué en dessinant un quadrilatère texturé sur la cible de rendu principale, en fonction de l'render mode de l'View3D. L'effet peut fournir un shader de sommet, un shader de fragment, ou les deux. Les effets s’appliquent toujours à l’ensemble de la scène, conformément à View3D.

Les effets sont associés à l’ SceneEnvironment via la propriété SceneEnvironment::effects. Cette propriété est une liste : les effets peuvent être enchaînés ; ils sont appliqués dans l’ordre où ils apparaissent dans la liste, en utilisant la sortie de l’étape précédente comme entrée pour la suivante, la sortie du dernier effet définissant le contenu de l’ View3D.

Remarque : les propriétés ` SceneEnvironment ` et` ExtendedSceneEnvironment ` fournissent un ensemble d’effets intégrés, tels que la profondeur de champ, la lueur/le bloom, les reflets de lentille, l’étalonnage des couleurs et le vignettage. Vérifiez toujours en premier lieu si ceux-ci suffisent aux besoins de l’application, et privilégiez l’utilisation des fonctionnalités intégrées plutôt que de mettre en œuvre un effet de post-traitement personnalisé.

Les effets s’apparentent à custom materials à bien des égards. Cependant, un matériau personnalisé est associé à un modèle et est chargé du rendu de ce maillage donné. En revanche, le shader de sommets d’un effet reçoit toujours un quadrilatère (par exemple, deux triangles) en entrée, tandis que son shader de fragments échantillonne la texture avec le contenu de la scène.

Contrairement aux matériaux personnalisés, les effets prennent en charge plusieurs passes. Pour de nombreux effets, cela n’est pas nécessaire, et lorsqu’il est nécessaire d’appliquer plusieurs effets, on peut souvent obtenir des résultats identiques en enchaînant plusieurs effets dans « the SceneEnvironment ». L’exemple «Custom Effect» en fait également la démonstration. Cependant, les passes ont la possibilité de demander des tampons de couleur (textures) supplémentaires et de spécifier vers lequel de ces tampons supplémentaires elles doivent envoyer leur sortie. Cela permet de mettre en œuvre des techniques de traitement d’image plus complexes, puisque les passes suivantes peuvent alors utiliser un ou plusieurs de ces tampons supplémentaires, en plus du contenu original de la scène, comme entrée. Si nécessaire, ces tampons supplémentaires peuvent avoir une durée de vie prolongée, ce qui signifie que leur contenu est conservé d’une image à l’autre, ce qui permet de mettre en œuvre des effets qui reposent sur l’accumulation du contenu de plusieurs images, comme le flou de mouvement.

Par rapport à l’ ShaderEffect 2D de Qt Quick, les effets de post-traitement 3D présentent l’avantage de pouvoir exploiter les données du tampon de profondeur, ainsi que la possibilité de mettre en œuvre plusieurs passes avec des tampons intermédiaires. De plus, les capacités liées aux textures sont étendues : Qt Quick 3D permet un contrôle plus fin des modes de filtrage et permet aux effets de fonctionner avec des formats de texture autres que RGBA8, par exemple les formats à virgule flottante.

Remarque : les effetsde post-traitement sont actuellement disponibles lorsque l’ View3D a son paramètre « renderMode » défini sur « Offscreen », « Underlay » ou « Overlay ». Les effets ne seront pas rendus en mode « Inline ».

Remarque : lors de l’utilisation d’effets de post-traitement, les shaders fournis par l’application doivent s’attendre à des données de couleur linéaires sans mappage de tons appliqué. Le tonemapping effectué lors du passage de rendu principal (ou lors du rendu de la skybox, s’il y en a une) lorsque l’option « tonemapMode » est définie sur une valeur autre que « SceneEnvironment.TonemapModeNone », est automatiquement désactivé dès lors qu’au moins un effet de post-traitement est spécifié dans le paramètre « SceneEnvironment ». Le shader de fragment du dernier effet de la chaîne (plus précisément, le dernier passage du dernier effet de la chaîne) sera automatiquement modifié pour effectuer le même mappage de tons que celui effectué par le passage de rendu principal.

Remarque : les effets qui effectuent leur propre mappage de tons doivent être utilisés dans une « SceneEnvironment » dont le mappage de tons intégré est désactivé en définissant ` tonemapMode ` sur ` SceneEnvironment.TonemapModeNone`.

Remarque : par défaut, la texture utilisée comme entrée pour les effets est créée avec un format de texture à virgule flottante, tel que RGBA 16 bits à virgule flottante. Le format de la texture de sortie est identique, car il suit par défaut celui de l’entrée. Il est possible de le redéfinir à l’aide de ` Buffer ` en indiquant un nom vide. Le format RGBA16F par défaut est utile car il permet de travailler avec des données linéaires non soumises à un mappage de tons sans que les valeurs de couleur situées en dehors de l'intervalle 0-1 ne soient écrêtées.

Exposition des données aux shaders

Comme avec ` CustomMaterial ` ou ` ShaderEffect`, les propriétés dynamiques d’un objet `Effect` peuvent être modifiées et animées à l’aide des fonctionnalités habituelles de QML et d’ Qt Quick, et les valeurs sont automatiquement exposées aux shaders. 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 d’ PrincipledMaterial; ce comportement d’Effect correspond donc à celui-ci.
  • QRect, QRectF, rect -> vec4
  • QPoint, QPointF, point, QSize, QSizeF, size -> vec2
  • QVector2D, vector2d -> vec3
  • QVector3D, vector3d -> vec3
  • QVector4D, vector4d -> vec4
  • QMatrix4x4, matrix4x4 -> mat4
  • QQuaternion, quaternion -> vec4, 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 revient à exposer 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 d’ Texture, seules celles liées à la source, au mosaïquage et au filtrage sont prises en compte implicitement par les effets ; les autres (telles que les transformations UV) doivent ê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 de l’effet à 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 disposer d’une propriété correspondante déclarée dans l’objet Effect.

Premiers pas avec les effets définis par l’utilisateur

Un effet de post-traitement personnalisé nécessite au minimum un objet Effect et un extrait de shader de fragment. Certains effets nécessiteront également un shader de sommet personnalisé.

À titre d’exemple simple, créons un effet qui combine le contenu de la scène avec une image, tout en modifiant de manière animée la valeur du canal rouge :

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

Ici, la texture contenant l’image image.png est mise à la disposition du shader sous le nom tex. La valeur de redLevel est disponible dans le shader via un uniforme float portant le même nom.

Le shader de fragment doit contenir une fonction appelée MAIN. La couleur finale du fragment est déterminée par FRAGCOLOR. La texture d’entrée principale, contenant le contenu de la scène de l’uniforme View3D, est accessible sous un uniforme sampler2D portant le nom INPUT. Les coordonnées UV du quadrilatère se trouvent dans INPUT_UV. Ces valeurs UV conviennent toujours à l'échantillonnage de INPUT, quelle que soit l'API graphique sous-jacente au moment de l'exécution (et donc quelle que soit la direction de l'axe Y dans les images, puisque les ajustements nécessaires sont appliqués automatiquement par Qt Quick 3D). L’échantillonnage de la texture à partir de notre image externe s’effectue à l’aide de TEXTURE_UV. La fonction INPUT_UV n’est pas adaptée aux applications multiplateformes, car l’axe V doit être inversé pour tenir compte des différences de système de coordonnées mentionnées précédemment, en utilisant une logique différente selon qu’il s’agit de textures basées sur des images ou de textures utilisées comme cibles de rendu. Heureusement, tout cela est géré par le moteur ; le shader n’a donc pas besoin de logique supplémentaire à cet effet.

Une fois que `simpleEffect` est disponible, il peut être associé à la liste des effets de l’ View3D, via ` SceneEnvironment` :

environment: SceneEnvironment {
    effects: [ simpleEffect ]
}

Le résultat ressemblerait à peu près à ce qui suit, avec la scène d’origine à gauche et l’effet appliqué à droite :

Trois objets 3D différents

Trois objets 3D différents sur lesquels est superposé un logo Qt transparent, créant un effet plein écran

Remarque : la valeur de la propriété ` shader ` dans le shader est une URL, comme c’est l’usage dans QML et ` Qt Quick`, faisant référence au fichier contenant l’extrait de shader, et fonctionne de manière très similaire à ` ShaderEffect ` ou ` Image.source`. Seuls les schémas ` file ` et ` qrc ` sont pris en charge. Il est également possible d’omettre le schéma file, ce qui permet de spécifier un chemin relatif de manière pratique. Un tel chemin est résolu par rapport à l’emplacement du composant (le fichier .qml ).

Remarque : le codede shader est toujours fourni au format GLSL de style 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 l’effet ne constitue pas en soi des shaders GLSL complets. Il fournit plutôt une fonction « MAIN » et, éventuellement, un ensemble de déclarations « VARYING », qui sont ensuite complétées par du code de shader supplémentaire par le moteur.

Remarque : l’exemple ci-dessus n’est pas compatible avec le mode de rendu multivue optionnel utilisé dans certaines applications de réalité virtuelle (VR) ou de réalité augmentée (AR). Pour qu’il fonctionne aussi bien avec qu’sans le mode multivue, modifiez MAIN() comme suit :

void MAIN()
{
    vec4 c = texture(tex, TEXTURE_UV);
    c.r *= redLevel;
#if QSHADER_VIEW_COUNT >= 2
    FRAGCOLOR = c * texture(INPUT, vec3(INPUT_UV, VIEW_INDEX));
#else
    FRAGCOLOR = c * texture(INPUT, INPUT_UV);
#endif
}

Effets avec les shaders de sommets

Un shader de sommets, lorsqu’il est présent, doit fournir une fonction appelée MAIN. Dans la grande majorité des cas, le shader de sommets personnalisé ne voudra pas fournir son propre calcul de la position homogène des sommets, mais cela est possible à l’aide de POSITION, VERTEX et MODELVIEWPROJECTION_MATRIX. Lorsque POSITION n’est pas présent dans le code du shader personnalisé, une instruction équivalente à POSITION = MODELVIEWPROJECTION_MATRIX * vec4(VERTEX, 1.0); sera automatiquement injectée par Qt Quick 3D.

Pour transmettre des données entre les shaders de sommets et de fragments, utilisez le mot-clé VARYING. En interne, celui-ci sera alors converti en une déclaration appropriée de sortie de sommet ou d’entrée de fragment. Le shader de fragments peut utiliser cette même déclaration, ce qui permet ensuite de lire la valeur interpolée pour le fragment actuel.

Prenons un exemple, qui est en réalité très similaire à l’effet intégré DistortionSpiral :

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

La liste « passes » de l’objet Effect doit désormais spécifier à la fois les extraits de code pour les shaders de sommets et de fragments :

passes: Pass {
   shaders: [
       Shader {
           stage: Shader.Vertex
           shader: "effect.vert"
       },
       Shader {
           stage: Shader.Fragment
           shader: "effect.frag"
       }
    ]
}

Le résultat final se présente comme suit :

Trois objets 3D différents

Vue déformée de trois objets 3D différents illustrant l'effet du shader de sommets

Mots-clés spéciaux dans les shaders d’effet

  • VARYING - Déclare une sortie de sommet ou une entrée de fragment, selon le type du shader actuel.
  • MAIN - Cette fonction doit toujours être présente dans un shader d'effet.
  • FRAGCOLOR - vec4 - La couleur finale du fragment ; la sortie du shader de fragment. (shader de fragment uniquement)
  • POSITION - vec4 - La position homogène calculée dans le shader de sommets. (shader de sommets uniquement)
  • MODELVIEWPROJECTION_MATRIX - mat4 - La matrice de transformation du quadrilatère à l'écran.
  • VERTEX - vec3 - Les sommets du quadrilatère ; l'entrée du shader de sommets. (shader de sommets uniquement)
  • INPUT - sampler2D ou sampler2DArray - L'échantillonneur de la texture d'entrée dans laquelle la scène est rendue, sauf si un passage redirige son entrée via un objet « BufferInput » ; dans ce cas, INPUT fait référence à la texture du tampon de couleur supplémentaire référencée par l'objet « BufferInput ». Lorsque le rendu multivue est activé, ce qui peut être pertinent pour les applications de réalité virtuelle (VR) ou de réalité augmentée (AR), il s’agit d’un sampler2DArray, tandis que la texture d’entrée devient un tableau de textures 2D.
  • INPUT_UV - vec2 - Coordonnées UV pour l'échantillonnage de INPUT.
  • TEXTURE_UV - vec2 - Coordonnées UV adaptées à l'échantillonnage d'une texture dont le contenu est chargé à partir d'un fichier image.
  • INPUT_SIZE - vec2 - La taille de la texture « INPUT », en pixels.
  • OUTPUT_SIZE - vec2 - La taille du tampon de sortie, en pixels. Elle est souvent identique à celle de INPUT_SIZE, sauf si le passage génère une sortie vers un tampon supplémentaire dont la taille est multipliée.
  • FRAME - float - Un compteur d’images, incrémenté après chaque image dans la texture « View3D ».
  • DEPTH_TEXTURE - sampler2D ou sampler2DArray - Une texture de profondeur contenant le contenu du tampon de profondeur avec les objets opaques de la scène. Comme pour CustomMaterial, la présence de ce mot-clé dans le shader déclenche la génération automatique de la texture de profondeur.
  • NORMAL_ROUGHNESS_TEXTURE - sampler2D - Une texture contenant les normales dans l'espace mondial et la rugosité des matériaux des objets opaques dans la partie actuellement visible de la scène. Comme avec CustomMaterial, la présence de ce mot-clé dans le shader implique un passage de rendu supplémentaire pour générer la texture de normales.
  • VIEW_INDEX - uint - Lorsque le rendu multivue est activé, il s’agit de l’index de vue actuel, disponible à la fois dans les shaders de sommets et de fragments. Il est toujours égal à 0 lorsque le rendu multivue n’est pas utilisé.
  • PROJECTION_MATRIX - mat4: la matrice de projection. Notez qu’avec le rendu multivue, il s’agit d’un tableau de matrices.
  • INVERSE_PROJECTION_MATRIX - mat4, la matrice de projection inverse. Notez qu’avec le rendu multivue, il s’agit d’un tableau de matrices.
  • VIEW_MATRIX -> mat4, la matrice de vue (caméra). Notez qu’avec le rendu multi-vues, il s’agit d’un tableau de matrices.
  • float NDC_Y_UP - La valeur est 1 lorsque l'axe Y est orienté vers le haut dans l'espace de coordonnées normalisé 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.
  • 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 tampons d’image (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.
  • float NEAR_CLIP_VALUE - La valeur est -1 lorsque la plage du plan de découpage 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 du plan de découpage va de 0 à 1.

Création d’effets en plusieurs passes

Un effet multipasse utilise souvent plusieurs ensembles de shaders et fait appel aux propriétés ` output ` et ` commands `. Chaque entrée de la liste des passes correspond à une passe de rendu dessinant un quadrilatère dans la texture de sortie de la passe, tout en échantillonnant la texture d’entrée de l’effet et, éventuellement, d’autres textures également.

La structure type d’un effet multi-pass peut se présenter comme suit :

passes: [
    Pass {
        shaders: [
            Shader {
                stage: Shader.Vertex
                shader: "pass1.vert"
            },
            Shader {
                stage: Shader.Fragment
                shader: "pass1.frag"
            }
            // This pass outputs to the intermediate texture described
            // by the Buffer object.
            output: intermediateColorBuffer
        ],
    },
    Pass {
        shaders: [
            Shader {
                stage: Shader.Vertex
                shader: "pass2.vert"
            },
            Shader {
                stage: Shader.Fragment
                shader: "pass2.frag"
            }
            // The output of the last pass needs no redirection, it is
            // the final result of the effect.
        ],
        commands: [
            // This pass reads from the intermediate texture, meaning
            // INPUT in the shader will refer to the texture associated
            // with the Buffer.
            BufferInput {
                buffer: intermediateColorBuffer
            }
        ]
    }
]

Qu’est-ce que intermediateColorBuffer?

Buffer {
    id: intermediateColorBuffer
    name: "tempBuffer"
    // format: Buffer.RGBA8
    // textureFilterOperation: Buffer.Linear
    // textureCoordOperation: Buffer.ClampToEdge
}

Les propriétés commentées ne sont pas nécessaires si les valeurs souhaitées correspondent aux valeurs par défaut.

En interne, la présence de cet objet Buffer et sa référence via la propriété ` output ` d’un passage entraînent la création d’une texture dont la taille correspond à celle de l’ View3D, et donc à la taille des textures d’entrée et de sortie implicites. Lorsque cela n’est pas souhaité, la propriété sizeMultiplier peut être utilisée pour obtenir une texture intermédiaire d’une taille différente. Cela peut entraîner des valeurs différentes pour les uniformes INPUT_SIZE et OUTPUT_SIZE dans le shader.

Par défaut, l’effet ne peut pas compter sur le fait que les textures conservent leur contenu d’une image à l’autre. Lorsqu’une nouvelle texture intermédiaire est créée, elle est effacée et mise à « vec4(0.0) ». Par la suite, cette même texture peut être réutilisée à d’autres fins. Par conséquent, les passes d’effet doivent toujours écrire sur l’intégralité de la texture, sans faire d’hypothèses sur son contenu au début de la passe. Il existe toutefois une exception à cette règle : les objets « Buffer » dont la propriété « bufferFlags » est définie sur « Buffer.SceneLifetime ». Cela indique que la texture est associée de manière permanente à une passe de l’effet et qu’elle ne sera pas réutilisée à d’autres fins. Le contenu de ces tampons de couleur est conservé d’une image à l’autre. Cette technique est généralement utilisée selon un principe de « ping-pong » dans des effets tels que le flou de mouvement : le premier passage utilise le tampon persistant comme entrée, en plus de la texture d’entrée principale de l’effet, et envoie sa sortie vers un autre tampon intermédiaire, tandis que le deuxième passage envoie sa sortie vers le tampon persistant. De cette manière, dans la première image, le premier passage échantillonne une texture vide (transparente), tandis que dans les images suivantes, il échantillonne la sortie du deuxième passage de l’image précédente. Un troisième passage peut alors mélanger l’entrée de l’effet et la sortie du deuxième passage.

Le type de commande « BufferInput » est utilisé pour exposer des tampons de texture personnalisés au passage de rendu.

Par exemple, pour accéder à someBuffer dans les shaders du passage de rendu sous le nom mySampler, on peut ajouter ce qui suit à sa liste de commandes :

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

Si le nom de l'sampler n'est pas spécifié, INPUT sera utilisé par défaut.

Les tampons peuvent être utiles pour partager des résultats intermédiaires entre les passes de rendu.

Pour exposer des textures préchargées à l’effet, il convient d’utiliser « TextureInput » à la place. Celles-ci peuvent être définies comme des propriétés de l’effet lui-même et seront automatiquement accessibles aux shaders via leurs noms de propriété.

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

Ici, ` tex ` est un échantillonneur valide dans tous les shaders de toutes les passes de l’effet.

En ce qui concerne les valeurs uniformes issues des propriétés, toutes les passes de l’effet lisent les mêmes valeurs dans leurs shaders. Si nécessaire, il est possible de redéfinir la valeur d’un uniforme uniquement pour une passe donnée. Pour ce faire, il suffit d’ajouter la commande « SetUniformValue » à la liste des commandes de la passe.

Remarque : l' target e du sélecteur de valeur uniforme spécifique au pass ne peut faire référence qu'à un nom correspondant à celui d'une propriété de l'effet. Il peut remplacer la valeur de l'uniforme correspondant à une propriété, mais il ne peut pas introduire de nouveaux uniformes.

Considérations relatives aux performances

Tenez compte de l'augmentation de la consommation de ressources et de la baisse potentielle des performances lors de l'utilisation d'effets de post-traitement. Tout comme pour les couches d'Qt Quick et les ShaderEffect, le rendu de la scène dans une texture puis l'utilisation de celle-ci pour texturer un quad ne sont pas des opérations légères, en particulier sur du matériel bas de gamme dont la puissance de traitement des fragments est limitée. La quantité de mémoire graphique supplémentaire nécessaire, ainsi que l’augmentation de la charge du GPU, dépendent toutes deux de la taille de l’ View3D (qui, sur les appareils embarqués sans système de fenêtrage, peut souvent être aussi grande que la résolution de l’écran). Les effets en plusieurs passes, ainsi que l’application d’effets multiples, augmentent encore davantage les exigences en matière de ressources et de performances.

Il est donc fortement recommandé de s'assurer dès le début du cycle de développement que le dispositif cible et la pile graphique sont capables de prendre en charge les effets inclus dans la conception de la scène 3D à la résolution d'écran du produit final.

Bien qu’inévitable avec certaines techniques qui en ont besoin, l’ DEPTH_TEXTURE implique un passage de rendu supplémentaire pour générer le contenu de cette texture, ce qui peut également constituer un frein sur du matériel moins performant. Par conséquent, n’utilisez l’ DEPTH_TEXTURE dans les shaders de l’effet que lorsque cela est indispensable.

La complexité des opérations dans les shaders est également un facteur important. Tout comme pour l’ CustomMaterial, un shader de fragment sous-optimal peut facilement entraîner une baisse des performances de rendu.

Faites preuve de prudence avec les « sizeMultiplier in Buffer » lorsque des valeurs supérieures à 1 sont impliquées. Par exemple, un multiplicateur de 4 signifie créer puis rendre une texture dont la taille est 4 fois supérieure à celle de l’« View3D ». Tout comme pour les cartes d’ombres et le multi-échantillonnage ou le suréchantillonnage, les coûts accrus en ressources et en performances peuvent rapidement l’emporter sur les avantages liés à une meilleure qualité sur les systèmes dotés d’une puissance GPU limitée.

Considérations relatives à la RV/RA

Lors du développement d’applications pour la réalité virtuelle ou augmentée à l’aide d’ Qt Quick 3D XR, les effets de post-traitement sont fonctionnels et disponibles. Cependant, les concepteurs et les développeurs doivent veiller tout particulièrement à bien comprendre quels effets, et de quel type, sont pertinents dans un environnement de réalité virtuelle. Certains effets, notamment certains de ceux intégrés dans ExtendedSceneEnvironment ou dans le module Effects (désormais obsolète), n’offrent pas une bonne expérience visuelle dans un environnement VR et peuvent même avoir des répercussions physiques sur l’utilisateur (provoquant, par exemple, le mal des transports ou des vertiges).

Lorsque le mode de rendu multivue, plus efficace, est activé dans une application de réalité virtuelle ou augmentée, il n’y a pas de passe de rendu distincte pour les contenus destinés à l’œil gauche et à l’œil droit. Au lieu de cela, tout se fait en un seul passage, à l’aide d’un tableau de textures 2D comportant deux couches, plutôt que de deux textures 2D indépendantes. Cela signifie également que de nombreux tampons intermédiaires, c’est-à-dire les textures de couleur ou de profondeur, devront être convertis en tableaux de textures dans ce mode. Cela a alors des implications pour les matériaux personnalisés et les effets de post-traitement. Les textures telles que la texture d’entrée (INPUT) et la texture de profondeur (DEPTH_TEXTURE) deviennent des tableaux de textures 2D, exposés dans le shader sous la forme d’un sampler2DArray au lieu de sampler2D. Cela a des implications pour les fonctions GLSL telles que texture(), textureLod() ou textureSize(). La coordonnée UV est alors un vec3, et non un vec2. Or, textureSize() renvoie un vec3, et non un vec2. Les effets destinés à fonctionner quel que soit le mode de rendu peuvent être écrits à l'aide d'un ifdef approprié :

#if QSHADER_VIEW_COUNT >= 2
    vec4 c = texture(INPUT, vec3(INPUT_UV, VIEW_INDEX));
#else
    vec4 c = texture(INPUT, INPUT_UV);
#endif

Il peut également être utile de définir des macros gérant les deux cas. Par exemple :

#if QSHADER_VIEW_COUNT >= 2
#define SAMPLE_INPUT(uv) texture(INPUT, vec3(uv, VIEW_INDEX))
#define SAMPLE_DEPTH(uv) texture(DEPTH_TEXTURE, vec3(uv, VIEW_INDEX)).r
#define PROJECTION PROJECTION_MATRIX[VIEW_INDEX]
#define INVERSE_PROJECTION INVERSE_PROJECTION_MATRIX[VIEW_INDEX]
#else
#define SAMPLE_INPUT(uv) texture(INPUT, uv)
#define SAMPLE_DEPTH(uv) texture(DEPTH_TEXTURE, uv).r
#define PROJECTION PROJECTION_MATRIX
#define INVERSE_PROJECTION INVERSE_PROJECTION_MATRIX
#endif

Cela ne s’applique pas à ` NORMAL_ROUGHNESS_TEXTURE `, qui est toujours une texture 2D, même lorsque le rendu multivue est activé :

#define SAMPLE_NORMAL(uv) normalize(texture(NORMAL_ROUGHNESS_TEXTURE, uv).rgb)

Remarque : la présence de mots-clés tels que « DEPTH_TEXTURE » déclenche des passes de rendu supplémentaires, et les uniformes tels que « INVERSE_PROJECTION_MATRIX » sont calculés et définis dès lors que le mot-clé apparaît n’importe où dans l’extrait de shader. Cela représente une charge plus importante, tant en termes de performances que d’utilisation des ressources. Il est donc recommandé de n’ajouter de telles définitions #define que lorsque les textures et les matrices seront réellement utilisées dans l’effet.

Voir également Shader, Pass, Buffer, BufferInput et Qt Quick 3D - Exemple d’effet personnalisé.

Documentation sur les propriétés

passes : list [read-only]

Contient une liste des « passes s de rendu » implémentées par l'effet.

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