Sur cette page

Effect QML Type

Composant de base pour la création d'un effet de post-traitement. Plus d'informations...

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 de Qt Quick. Lorsqu'un effet est présent, la scène est d'abord rendue dans une texture séparée. L'effet est ensuite appliqué en dessinant un quadrillage texturé sur la cible de rendu principale, en fonction du site render mode de View3D. L'effet peut fournir un nuanceur de sommets, un nuanceur de fragments ou les deux. Les effets sont toujours appliqués à l'ensemble de la scène, par View3D.

Les effets sont associés à la propriété SceneEnvironment dans 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 de la liste, en utilisant la sortie de l'étape précédente comme entrée de l'étape suivante, la sortie du dernier effet définissant le contenu de la propriété View3D.

Remarque : SceneEnvironment et ExtendedSceneEnvironment fournissent un ensemble d'effets intégrés, tels que la profondeur de champ, la lueur/le flou, le reflet de l'objectif, l'étalonnage des couleurs et la vignette. Il faut toujours se demander si ces effets sont suffisants pour répondre aux besoins de l'application et préférer utiliser les fonctions intégrées plutôt que d'implémenter un effet de post-traitement personnalisé.

Les effets sont similaires à custom materials à bien des égards. Cependant, un matériau personnalisé est associé à un modèle et est responsable de l'ombrage de ce maillage donné. Le vertex shader d'un effet reçoit toujours un quad (par exemple, deux triangles) en entrée, tandis que son fragment shader é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, des résultats identiques peuvent souvent être obtenus en enchaînant plusieurs effets à l'adresse the SceneEnvironment. L'exemple de l'effet personnalisé le démontre également. Cependant, les passes ont la possibilité de demander des tampons de couleur supplémentaires (texture), et de spécifier vers lequel de ces tampons supplémentaires ils sortent. 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, ainsi que le contenu de la scène d'origine, en tant qu'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 préservé entre les images, ce qui permet de mettre en œuvre des effets qui reposent sur l'accumulation du contenu de plusieurs images, tels que le flou de mouvement.

Par rapport au site Qt Quick's 2D ShaderEffect, les effets de post-traitement 3D ont l'avantage de pouvoir travailler avec des données de tampons de profondeur, ainsi que la possibilité de mettre en œuvre des passages multiples avec des tampons intermédiaires. En outre, les capacités liées à la texture sont étendues : Qt Quick 3D permet un contrôle plus fin des modes de filtrage et permet aux effets de travailler avec des formats de texture autres que RGBA8, par exemple des formats à virgule flottante.

Remarque : les effets de post-traitement sont actuellement disponibles lorsque View3D a son renderMode réglé sur Offscreen, Underlay ou Overlay. Les effets ne seront pas rendus pour le mode Inline.

Remarque : lors de l'utilisation d'effets de post-traitement, les nuanceurs fournis par l'application doivent s'attendre à des données de couleur linéaires sans application de la cartographie des tons. La conversion de ton qui est effectuée pendant la passe de rendu principale (ou pendant le rendu de la boîte à ciel, s'il y a une boîte à ciel) lorsque tonemapMode est défini sur une valeur autre que SceneEnvironment.TonemapModeNone, est automatiquement désactivée lorsqu'il y a au moins un effet de post-traitement spécifié dans SceneEnvironment. Le dernier effet de la chaîne (plus précisément, la dernière passe du dernier effet de la chaîne) verra automatiquement son nuanceur de fragment modifié pour effectuer la même conversion de ton que celle de la passe de rendu principale.

Remarque : les effets qui effectuent leur propre cartographie tonale doivent être utilisés dans un site SceneEnvironment dont la cartographie tonale intégrée est désactivée en réglant tonemapMode sur SceneEnvironment.TonemapModeNone.

Remarque : par défaut, la texture utilisée en entrée des effets est créée avec un format de texture à virgule flottante, tel que RGBA à virgule flottante 16 bits. Le format de la texture de sortie est le même puisque, par défaut, il suit le format d'entrée. Ceci peut être modifié en utilisant Buffer et un nom vide. Le format par défaut RGBA16F est utile car il permet de travailler avec des données linéaires non tonemappées sans que les valeurs de couleur en dehors de la plage 0-1 ne soient bridées.

Exposition des données aux nuanceurs

Comme avec CustomMaterial ou ShaderEffect, les propriétés dynamiques d'un objet Effect peuvent être modifiées et animées à l'aide des fonctions habituelles de QML et de Qt Quick, et les valeurs sont automatiquement exposées aux shaders. La liste suivante montre comment les propriétés sont mappées :

  • bool, int, real -> bool, int, float
  • QColor color -> vec4, et la couleur est convertie en linéaire, en supposant l'espace sRGB pour la valeur de couleur spécifiée dans QML. Les couleurs Qt XML intégrées, telles que , sont également dans l'espace de couleur sRGB, et la même conversion est effectuée pour toutes les propriétés de couleur de DefaultMaterial et , de sorte que ce comportement d'Effect correspond à ces propriétés. "green" PrincipledMaterial
  • 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é de texture de TextureInput. Définir la propriété enabled à false conduit à exposer une texture factice au shader, ce qui signifie que les shaders sont toujours fonctionnels mais échantillonneront une texture avec un contenu d'image noir opaque. Faites attention au fait que les propriétés des échantillonneurs doivent toujours faire référence à un objet TextureInput, et non à un objet Texture directement. En ce qui concerne les propriétés de Texture, les propriétés liées à la source, au tuilage et au filtrage sont les seules qui sont prises en compte implicitement avec les effets, car le reste (comme les transformations UV) est à la charge des shaders personnalisés qui doivent les implémenter comme ils le souhaitent.

Note : Lorsqu'un uniforme référencé dans le code du shader n'a pas de propriété correspondante, cela provoquera une erreur de compilation du shader lors du traitement de l'effet au moment de l'exécution. Il existe quelques exceptions à cette règle, comme les uniformes d'échantillonneurs, qui obtiennent une texture fictive lorsqu'aucune propriété QML correspondante n'est présente, mais en règle générale, tous les uniformes et échantillonneurs doivent avoir une propriété correspondante déclarée dans l'objet Effect.

Pour commencer avec les effets définis par l'utilisateur

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

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

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 exposée au shader sous le nom tex. La valeur de redLevel est disponible dans le shader dans un uniforme float portant le même nom.

Le nuanceur 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, avec le contenu de la scène de View3D, est accessible sous un sampler2D portant le nom INPUT. Les coordonnées UV du quadrilatère se trouvent à l'adresse INPUT_UV. Ces valeurs UV conviennent toujours à l'échantillonnage 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 avec notre image externe se fait à l'aide de TEXTURE_UV. INPUT_UV n'est pas adapté aux applications multiplateformes car 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 pour les textures basées sur des images et les textures utilisées comme cibles de rendu. Heureusement, tout ceci est pris en charge par le moteur et le shader n'a donc pas besoin d'une logique supplémentaire pour cela.

Une fois que simpleEffect est disponible, il peut être associé à la liste des effets de View3D's SceneEnvironment:

environment: SceneEnvironment {
    effects: [ simpleEffect ]
}

Les résultats ressembleraient à ce qui suit, avec la scène originale à gauche et l'effet appliqué à droite :

Trois objets 3D différents

Trois objets 3D différents avec le logo transparent de Qt 3D superposé en tant qu'effet plein écran.

Remarque : la valeur de la propriété shader dans Shader est une URL, comme c'est le cas dans QML et Qt Quick, qui fait 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 code des shaders est toujours fourni à l'aide de GLSL de style Vulkan, quelle que soit l'API graphique utilisée par Qt au moment de l'exécution.

Remarque : le code de nuanceur de sommets et de fragments fourni par l'effet n'est pas un nuanceur GLSL complet en soi. Ils fournissent plutôt une fonction MAIN, et éventuellement un ensemble de déclarations VARYING, qui sont ensuite modifiées par le moteur avec d'autres codes de shaders.

Remarque : l'exemple ci-dessus n'est pas compatible avec le mode de rendu multivue optionnel utilisé dans certaines applications VR/AR. Pour qu'il fonctionne avec et 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 vertex shaders

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

Pour transmettre des données entre les nuanceurs de sommets et de fragments, utilisez le mot-clé VARYING. En interne, ces données seront transformées en déclaration de sortie de vertex ou d'entrée de fragment appropriée. Le nuanceur de fragment peut utiliser la même déclaration, ce qui permet de lire la valeur interpolée pour le fragment actuel.

Examinons un exemple qui est en fait 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;
        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 maintenant spécifier à la fois les vertex et les fragments :

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

Le résultat final ressemble à ce qui suit :

Trois objets 3D différents

Vue déformée de trois objets 3D différents montrant l'effet vertex shader

Mots-clés spéciaux dans les nuanceurs d'effet

  • VARYING - Déclare une sortie vertex ou une entrée fragment, selon le type du shader actuel.
  • MAIN - Cette fonction doit toujours être présente dans un nuanceur d'effet.
  • FRAGCOLOR - vec4 - La couleur finale du fragment ; la sortie du nuanceur de fragment. (nuanceur de fragment uniquement)
  • POSITION - vec4 - Position homogène calculée dans le nuanceur de sommets. (nuanceur de sommets uniquement)
  • MODELVIEWPROJECTION_MATRIX - mat4 - Matrice de transformation pour le quadrant de l'écran.
  • VERTEX - vec3 - Les sommets du quadrilatère ; l'entrée du nuanceur de sommets. (nuanceur de sommets uniquement)
  • INPUT - sampler2D ou sampler2DArray - L'échantillonneur pour la texture d'entrée avec le rendu de la scène, sauf si une passe redirige son entrée via un objet BufferInput, auquel cas INPUT fait référence à la texture du tampon de couleur supplémentaire référencée par BufferInput. Lorsque le rendu multivue est activé, ce qui peut être pertinent pour les applications VR/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 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 - Taille de la texture INPUT, en pixels.
  • OUTPUT_SIZE - vec2 - Taille du tampon de sortie, en pixels. Souvent identique à INPUT_SIZE, sauf si la passe sort dans un tampon supplémentaire avec un multiplicateur de taille.
  • FRAME - float - Un compteur d'images, incrémenté après chaque image dans View3D.
  • DEPTH_TEXTURE - sampler2D ou sampler2DArray - Une texture de profondeur avec 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 de l'espace-monde et la rugosité des objets opaques dans la partie visible de la scène. Comme pour CustomMaterial, la présence de ce mot-clé dans le shader implique une passe de rendu supplémentaire pour générer la texture normale.
  • VIEW_INDEX - uint - Lorsque le rendu multivue est activé, il s'agit de l'indice de vue actuel, disponible dans les nuanceurs de sommets et de fragments. Toujours 0 lorsque le rendu multivue n'est pas utilisé.
  • PROJECTION_MATRIX - mat4, la matrice de projection. Notez qu'avec le rendu multivues, il s'agit d'un tableau de matrices.
  • INVERSE_PROJECTION_MATRIX - mat4, la matrice de projection inverse. Notez qu'avec le rendu multi-vues, il s'agit d'un tableau de matrices.
  • VIEW_MATRIX -> mat4, la matrice de vue (caméra). Notez qu'avec le rendu multivue, il s'agit d'un tableau de matrices.
  • float NDC_Y_UP - La valeur est 1 lorsque l'axe Y pointe vers le haut dans l'espace de coordonnées normalisé de l'appareil, et -1 lorsque l'axe Y pointe vers le bas. L'axe Y pointant vers le bas est le cas lorsque le rendu se fait avec Vulkan.
  • float FRAMEBUFFER_Y_UP - La valeur est 1 lorsque l'axe Y pointe vers le haut dans le système de coordonnées des framebuffers (textures), ce qui signifie que (0, 0) est le coin inférieur gauche. La valeur est -1 lorsque l'axe Y pointe vers le bas, (0, 0) étant le coin supérieur gauche.
  • float NEAR_CLIP_VALUE - La valeur est -1 lorsque la plage du plan d'écrêtage commence à -1 et va jusqu'à 1, ce qui est le cas lors de l'utilisation d'OpenGL pour le rendu. Pour les autres systèmes de rendu, la valeur de cette propriété sera 0, ce qui signifie que le plan d'écrêtage se situe entre 0 et 1.

Création d'effets multi-passages

Un effet multi-passes utilise souvent plus d'un jeu de shaders et utilise les propriétés output et commands. Chaque entrée de la liste des passes se traduit par une passe de rendu dessinant un quad dans la texture de sortie de la passe, tout en échantillonnant la texture d'entrée de l'effet et éventuellement d'autres textures.

Le schéma typique d'un effet multi-passes peut ressembler à ce qui 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 tampon et sa référence à partir de la propriété output d'un passage entraîne la création d'une texture dont la taille correspond à 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 conduire à ce que les uniformes INPUT_SIZE et OUTPUT_SIZE dans le shader aient des valeurs différentes.

Par défaut, Effect ne peut pas compter sur le fait que les textures conservent leur contenu entre les images. Lorsqu'une nouvelle texture intermédiaire est créée, elle est effacée à vec4(0.0). Par la suite, la même texture peut être réutilisée à d'autres fins. Par conséquent, les passes d'effet doivent toujours écrire dans la texture entière, sans faire d'hypothèses sur leur contenu au début de la passe. Il existe une exception à cette règle : Les objets Buffer dont la valeur 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 préservé entre les images. Cette méthode est généralement utilisée en mode ping-pong dans des effets tels que le flou de mouvement : la première passe prend le tampon persistant comme entrée, en plus de la texture d'entrée principale de l'effet, et sort dans un autre tampon intermédiaire, tandis que la deuxième passe sort dans le tampon persistant. Ainsi, dans la première image, la première passe échantillonne une texture vide (transparente), tandis que dans les images suivantes, elle échantillonne la sortie de la deuxième passe de l'image précédente. Une troisième passe peut alors mélanger l'entrée de l'effet et la sortie de la deuxième passe.

Le type de commande BufferInput est utilisé pour exposer des tampons de texture personnalisés à la passe de rendu.

Par exemple, pour accéder à someBuffer dans les shaders de la passe de rendu sous le nom mySampler, la commande suivante peut être ajoutée à sa liste de commandes :

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

Si le nom 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 les textures préchargées à l'effet, TextureInput doit être utilisé à 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 par leurs noms de propriétés.

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 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 surcharger la valeur d'un uniforme juste pour une passe donnée. Pour ce faire, il suffit d'ajouter la commande SetUniformValue à la liste des commandes de la passe.

Note : Le target du fixateur de valeur d'uniforme spécifique à la passe ne peut faire référence qu'à un nom qui est le nom 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

Soyez conscient de l'augmentation de l'utilisation des ressources et de la réduction potentielle des performances lors de l'utilisation d'effets de post-traitement. Tout comme pour les calques Qt Quick et ShaderEffect, le rendu de la scène dans une texture et son utilisation pour texturer un quad n'est pas une opération bon marché, 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 du site 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 multi-passages, ainsi que l'application de plusieurs effets, augmentent encore les besoins en ressources et en performances.

Il est donc fortement conseillé de s'assurer, dès le début du cycle de développement, que l'appareil ciblé et la pile graphique sont capables de gérer les effets inclus dans la conception de la scène 3D à la résolution de l'écran du produit final.

Bien qu'inévitable pour les techniques qui en ont besoin, DEPTH_TEXTURE implique une passe de rendu supplémentaire pour générer le contenu de cette texture, ce qui peut également représenter un inconvénient pour le matériel moins performant. Par conséquent, n'utilisez DEPTH_TEXTURE dans les shaders de l'effet que lorsque c'est indispensable.

La complexité des opérations dans les shaders est également importante. Tout comme pour CustomMaterial, un nuanceur de fragments sous-optimal peut facilement entraîner une baisse des performances de rendu.

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

Considérations relatives à la RV/AR

Lors du développement d'applications pour la réalité virtuelle ou augmentée à l'aide de Qt Quick 3D XR, les effets de post-traitement sont fonctionnels et disponibles. Toutefois, les concepteurs et les développeurs doivent prendre soin de comprendre quels effets et quels types d'effets ont un sens dans un environnement de réalité virtuelle. Certains effets, y compris certains des effets intégrés dans ExtendedSceneEnvironment ou le module Effects, qui est obsolète, n'offrent pas une bonne expérience visuelle dans un environnement de réalité virtuelle, et peuvent même affecter physiquement l'utilisateur (en provoquant, par exemple, le mal des transports ou des vertiges).

Lorsque le mode de rendu multivue, plus efficace, est activé dans une application VR/AR, il n'y a pas de passe de rendu séparée pour les contenus de l'œil gauche et de l'œil droit. Au lieu de cela, tout se passe en une seule passe, en utilisant un tableau de textures 2D avec deux couches au lieu de deux textures 2D indépendantes. Cela signifie également que de nombreux tampons intermédiaires, c'est-à-dire des textures de couleur ou de profondeur, devront devenir des tableaux de textures dans ce mode. Cela a 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 en tant que 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. Alors que textureSize() renvoie un vec3, et non un vec2. Les effets destinés à fonctionner indépendamment du mode de rendu peuvent être écrits avec 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 qui gèrent les deux cas. Par exemple, il peut être utile de définir des macros qui gèrent les deux cas :

#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

Ceci ne s'applique pas à NORMAL_ROUGHNESS_TEXTURE qui est toujours une texture 2D, même lorsque le rendu multi-vues est actif :

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

Note : 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 en fonction de la présence du mot-clé dans l'extrait de shader n'importe où. Cette méthode est plus coûteuse, tant en termes de performances que d'utilisation des ressources. Il est donc recommandé de n'ajouter ces #defines que lorsque les textures et les matrices seront réellement utilisées dans l'effet.

Voir aussi 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 de rendus passes mis en œuvre 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.