Utiliser les effets de shader

Si vous avez joué à certains jeux récents, vous connaissez probablement le terme shaders. Une définition simple des shaders, est qu'ils permettent la création d'effets visuels. Mais cette réponse n'est pas suffisamment précise, en voici une plus détaillée. Il y a deux différents type de shaders: les vertex shaders et les pixel shaders. Les vertex shaders peuvent être utilisés seuls, tandis que les pixel shaders sont toujours utilisés avec les vertex shaders.

Usuellement, Ultimate 3D utilise le ffp (fixed function pipeline) pour afficher les modèles. Le ffp fait partie de Direct3D. Il calcule les données des vertex, cela signifie qu'il calcule les positions des vertex sur l'écran, l'éclairage des vertex et un ensemble d'autres bits de données. Une fois calculées, les données sont transférées et sont utilisées pour afficher chacun des triangles pixel par pixel. Lors de l'utilisation des shaders, on n'utilise plus le ffp, mais le programmable function pipeline. Cela signifie que la façon dont Ultimate 3D calcule les données des vertex et les couleurs des pixels peut être changée comme on le souhaite.  

Les Vertex shaders sont de minuscules programmes qui sont exécutés pour chacun des vertex à chaque frame, afin de calculer leurs données. De cette manière, il vous est possible de changer la géométrie des objets sans les fonctions de manipulation des meshs d'Ultimate 3D, vous pouvez changer la façon dont les textures sont appliquées à l'objet en modifiant la façon dont les coordonnées des textures finales sont calculées. En gros, vous pouvez créer votre propre moteur de lumière. Les pixel shaders sont des programmes encore plus petits, éxécutés pour chacun des pixels à chaque frame, afin de calculer les données de ces derniers. Ils peuvent retrouver les coordonnées des textures qui ont été calculées par le vertex shader et peuvent accéder aux textures. Le résultat des calculs d'un pixel shader ne peut être autre qu'une seule couleur qui sera utilisée comme couleur du pixel. Notez que les shaders peuvent être créés et édités dans n'importe quel éditeur de texte, par exemple le Bloc Note. La figure suivante en explique le fonctionnement:

ShaderVertexProcessing.png

Pour commencer les vertices sont calculés, soit par les transformations et l'éclairage, soit par les vertex shader. Ensuite ces vertices sont rastérisés (Ndt: La rastérisation consiste à transformer une image vectorielle en image matricielle, affichable donc sur un écran). Cela détermine quels pixels doivent être affichés pour les triangles du mesh. Finalement le ffp (fixed function pipeline) ou le pixel shader calculent les couleurs des pixels et les affiche à l'écran. En réalité, il y a quelques étapes supplémentaires dans le pipeline de rendu, comme le brouillard qui est appliqué après les pixel shader, mais les mentionner sur le schéma l'aurait rendu plus compliqué qu'il ne le faut. 

Juste pour vous donner une idée de comment se présente un shader, voici un exemple. Celui-ci présente un shader très simple. Il affiche seulement le rendu de l'objet en appliquant sa couleur de matériau et sa première texture. Un effet de shader est toujours constitué de deux ou trois fichiers. Un fichier de vertex shader (*.vsh) doit être disponible; un fichier de pixel shader (*.psh) lui, est optionel. Il y a également un fichier d'effet Ultimate 3D (*.ufx) qui contient les informations permettant à Ultimate 3D de savoir comment le vertex shader et le pixel shader doivent être utilisés.

Voici un vertex shader:

// Cela doit toujours être la première ligne de tous vos vertex shader
vs.1.1

// Cette ligne convertit la position du vertex dans les meshs en position sur
// l'écran. m4x4 est la commande utilisée à cet effet. oPos est le nom du
//
registre de sortie dans lequel le shader doit sauvegarder la position sur
//
l'écran. La position du vertex dans les meshs est toujours dans le
// registre v0. c0 est une variable qui est définie avant que le modèle ne
// soit rendu, qu'on appelle un registre constant. Les registres constants
// sont définis par le fichier *.ufx. Il contient le début de matrice de
// conversion requise pour calculer la position sur l'écran.
 
m4x4 oPos, v0, c0

// Cette ligne transmet la couleur du matériau, en le copiant simplement depuis
// le cinquième registre constant, dans le registre de sortie de la couleur
// diffuse.
mov oD0, c4

// Cette ligne transmet la première coordonnée de texture du mesh en le copiant depuis le septième registre de vertex, dans le registre de sortie des données de texture.
mov oT0, v7

Voici un pixel shader:

// Cela peut être ps.1.0, ps.1.1, ps.1.2, ps.1.3 ou ps.1.4. Si vous utilisez
// une plus haute version de pixel shader, moins de PCs supporteront
// l'effet, mais vous aurez plus de possibilités. Cette exemple utilise
// ps.1.4 parce que le code est plus simple dans cette version.

ps.1.4

// Utilise la première coordonnée de texture (t0), pour obtenir la couleur de la
// première texture (r0) et sauvegarde le résultat dans le registre temporaire
// r0. Commentaire: r0 a deux utilisés ici: il identifie la texture (cela sera r1
// pour la deuxième texture) et il est utilisé comme registre de sortie.

texld r0, t0

// Multiplie la couleur de la texture (r0) par la couleur du matériau (v0) et
// sauvegarde le résultat dans le registre de sortie (r0). La valeur de r0 à la
// fin du code sera utilisée comme couleur pour le pixel.

mul r0, r0, v0

Et voici, un fichier d'effet Ultimate 3D:

// Cela doit être la première ligne de tout fichier d'effet Ultimate 3D
Ultimate3DEffectFile 1.0

// Utilise le vertex shader (dans la mesure où il a été sauvegardé dans ce
// fichier)

VertexShaderFile effects/VertexShader.vsh
// Utilise le pixel shader. Comme je l'ai déjà dit le vertex shader peut être
// utilisé sans pixel shader, en tous cas il est utilisé ici.
PixelShaderFile effects/PixelShader.psh

// Les registres constants c0 à c3 doivent contenir les bonnes matrices de conversion dans le vertex shader.
VSConstant 0 VS_CONST_WORLD_VIEW_PROJ_TRANS_1
VSConstant 1 VS_CONST_WORLD_VIEW_PROJ_TRANS_2
VSConstant 2 VS_CONST_WORLD_VIEW_PROJ_TRANS_3
VSConstant 3 VS_CONST_WORLD_VIEW_PROJ_TRANS_4
// c4 doit contenir la couleur du matériau dans le vertex shader.
VSConstant 4 VS_CONST_MAT_DIFFUSE

Cela ne fait que sept lignes de code de shader et deux des sept lignes sont toujours les mêmes. Donc, comme vous pouvez le voir, la programmation de shader n'est pas si difficile. Cependant, cela nécessite quelques connaissances en mathématiques. Certaines de ces connaissances peuvent être lues dans le chapitre à propos des Fonctions Mathématiques d'Ultimate 3D. Si vous passez ce chapitre, il n'y a aucun problème. Mais le jour où vous vous rendrez compte que vous êtes devenu un meilleur programmeur, et vous sentirez prêt, vous devriez revenir pour étendre votre horizon.

Dans les jeux modernes, pratiquement tout ce que vous voyez utilise les effets de shader. Ils sont extrêmements importants pour les graphismes modernes. Une fois que vous êtes à même de programmer des shaders, vous avez la solution ultime pour tous vos effets spéciaux. Juste pour vous donner une idée de ce que vous ratez en passant outre ce chapitre, voici quelques exemples de techniques pouvant êtres réalisées facilement avec les shaders:
- La réflection et la réfraction pour une eau parfaite.
- Les Post Screen Shaders pour les effets tels que le HDR ou le motion blur.
- La perturbation de textures pour de superbes effets météorologiques et du feu extrêmement réaliste.
- Les effets d'étirements de l'écran.
- Et bien plus encore. Il n'y a probablement personne qui connaîsse toutes les techniques possibles.

Aussi, Ultimate 3D demo contient un ensemble d'effets de shaders plutôts sympas. Malheureusement cela prendrait trop de temps d'écrire une introduction complète à la programmation de shader. Heureusement d'autres personnes l'ont fait avant, notamment Wolfgang Engel. Il a écrit de superbes tutoriaux pour démarrer avec la programmation des shaders.

Il s'agit là d'un bon tutoriel sur la programmation des vertex shaders par Wolfgang Engel.


Un autre tutoriel de Wolfgang Engel à propos de la programmation des pixels shaders (Notez que vous ne pouvez utiliser les pixels shaders sans vertex shaders).


Et voici un troisième tutoriel du même auteur, qui donne un exemple sympathique sur la programmation des shaders, en expliquant comment réaliser différentes techniques d'éclairage par pixel (per pixel lighting).


Vous ne devriez pas passer à côté de la documentation de référence sur les vertex shader de Microsoft, ni de la documentation de référence sur les pixel shaders. Ce n'est pas un tutoriel mais un endroit où vous pouvez chercher n'importe quoi sur la programmation des shaders et où vous recevrez des informations vraiment fiables.


Une fois que vous aurez lu et compris les tutoriaux de Wolfgang Engel's, vous devriez avoir les bases théoriques nécessaires pour programmer des shaders. Quoi qu'il en soit, apprendre par la pratique est le meilleur moyen d'apprendre la programmation des shaders. Donc amusez vous avec. Tous les shaders que vous faîtes ne sont pas obligés d'être utiles, du moment que vous y apprenez quelque chose en les écrivants. Si vous avez n'importe quelle question à propos de la programmation des shaders vous pouvez les poser sur la Communauté Ultimate 3D. Afin de programmer des shaders compatibles avec Ultimate 3D, vous avez besoin de quelques précisions: vous devez savoir quel type de donnée est présente dans les différents registres d'entrée des vertex shaders. En voici une petite liste:
v0 - Position dans l'espace de meshs.
v1 - Le facteur d'influence d'un os pour les modèles supportant le skinning, la deuxième position pour les modèles utilisant le tweening.
v2 - Quatre indices de matrice pour les modèles supportant le skinning, La deuxième normale pour les modèles supportant le vertex tweening (Si vous souhaitez des éclaircissements sur les normales cliquez ici).
v3 - La première normale
v7 à v14 - Jusqu'à huit coordonnées de texture à quatres dimensions.

Introduction au format de fichier *.ufx

La programmation de shaders est suffisamment difficile, cela serait donc difficile si vous deviez calculer les valeurs pour les constantes du shader également. C'est pourquoi, j'ai inventé le format de fichier *.ufx. C'est un format de fichier qui gère les effets de shader, en incluant toutes les informations qui leurs appartiennent. Si vous utilisez un fichier *.ufx pour vos effets de shader, vous n'aurez rien à faire après l'avoir chargé. Vous n'aurez pas à calculer un grand nombre de constantes pour le shader, parce que vous pourrez en choisir depuis une longue liste de constantes communément utilisées pour chacun des registres constants. Les constantes qui sont vraiment constantes pour chaque utilisation du shader peuvent être définies dans le fichier *.ufx ou en utilisant l'instruction def du shader. Vous pouvez aussi définir des effets alternatifs qui devront êtres utilisés, si la version des shaders requise n'est pas supportée (On appelle cela les techniques de "fallback", autrement dit techniques de repli).

Vous voyez donc que le format de fichier *.ufx peut vous épargner beaucoup de travail. Malheureusement il n'est pas encore vraiment intuitif. Mais ne vous inquiétez pas, j'écrirai un outil de création d'effets lorsque j'aurai le temps. Dans cet outil, il y aura un système de drag and drop pour créer des fichiers *.ufx et un aperçu du rendu de l'effet montrant le résultat immédiatement.

Expliquons le format de fichier *.ufx. Chaque fichier *.ufx doit être fait d'un ensemble de lignes. Chaque ligne peut contenir exactement une commande. Une commande commence toujours par un nom de commande. Puis, suivent un ensemble de paramètres, qui peuvent être des chaînes de caractères ou des nombres. Notez que vous pouvez mettre des commentaires partout ou vous le voulez en écrivant "//". La première commande qui doit être dans le fichier *.ufx est:

Ultimate3DEffectFile %version

version
Actuellement il existe les versions 1.0 et 1.1. Chaque fichier d'effet 1.0 est un shader 1.1 valide et sera compilé en conséquence. Vous devez donc toujours écrire 1.1 ici.

Ensuite vous devez définir les fichiers de shader à utiliser pour l'effet (cela doit être des fichiers *.vsh et *.psh). Il y a deux commandes différentes pour cela:

VertexShaderFile %FileNameWithPath

FileNameWithPath
Le nom de fichier et le chemin du fichier de shader relatif au dossier qui contient l'éxécutable du jeu, par exemple effects\EffectVertexShader.vsh.

Si vous avez travaillé avec le format de fichier d'effet 1.0 d'Ultimate 3D, vous vous demandez peut être où sont passés les paramètres TextureCoordinateSize. En fait Ultimate 3D les détermine automatiquement désormais, selon la donnée de vertex disponible dans le modèle. Cela rend le système de shader plus robuste. Si vous essayez d'appliquer un effet de shader pour un modèle qui n'a pas les données de vertex nécessaires, un message d'erreur apparaîtra. Après avoir définit le vertex shader, vous pouvez définir un pixel shader:

PixelShaderFile %FileNameWithPath

FileNameWithPath
Le nom de fichier et le chemin du fichier de shader relatif au dossier qui contient l'éxécutable du jeu, par exemple effects\EffectPixelShader.psh.

Remarquez que vous n'êtes pas obligé de définir un pixel shader. Après quoi, vous pouvez configurer les constantes qui doivent être définies pour les shaders. Il n'y a qu'une seule commande pour cela, mais elle peut prendre une longue liste de paramètres. Pour comprendre ce que les paramètres signifient, cela requièrt une connaissance des calculs des matrices et des vecteurs. Voici la commande de définition d'une constante pour les vertex shaders:

VSConstant %ConstantIndex %ConstantIdentifier %ManuallySettableValues

ConstantIndex
L'indice du registre constant auquel cette constante sera associée. Cela peut être une valeur allant de 0 à 95.

ConstantIdentifier
Ce qui suit est une longue liste des registres constants qu'Ultimate 3D peut calculer à votre place automatiquement. Toures les matrices et les vecteurs référant aux directions ou aux positions des autres objets sont déjà convertis en positions dans l'espace de meshs! Il est important de garder cela à l'esprit. Changer les directions ou les positions dans l'espace de meshs avant de les passer au vertex shader est bien plus efficace que de le faire pour chacun des vertex dans le vertex shader. Et usuellement, la position dans l'espace n'est pas requise. Au cas où vous en auriez tout de même besoin, vous pouvez la récupérer en la convertissant à l'aide de la matrice de conversion des positions de l'ensemble des meshs aux positions dans l'espace. L'exception ici est les modèles utilisants le vertex skinning, parce que ces derniers ont trop de conversions différentes entre les positions dans l'ensemble des meshs et les positions dans l'espace. Pour ceux dont les données des constantes sont passées sous formes de positions dans l'espace, et pour la matrice de conversion des positions de l'ensemble des meshs aux positions dans l'espace sont toujours la matrice d'identité. Les données des couleurs sont toujours passées en utilisant des valeurs allant de 0 à 1, à la place des valeurs allant de 0 à 255.


VS_CONST_MANUAL_SETTABLE: Ce paramètre dit à Ultimate 3D qu'il est supposé définir les constantes à l'aide des valeurs données dans le paramètre suivant (ManualSettableValues).
VS_CONST_WORLD_VIEW_PROJ_TRANS_1: La première colonne du produit des transformations de l'espace, de la vue et de la projection qui résultent dans la matrice de conversion des positions de l'ensemble des meshs aux positions dans l'espace.
VS_CONST_WORLD_VIEW_PROJ_TRANS_2: La deuxième colonne de cette même matrice.
VS_CONST_WORLD_VIEW_PROJ_TRANS_3: La troisième colonne de cette même matrice.
VS_CONST_WORLD_VIEW_PROJ_TRANS_4: La quatrième colonne de cette même matrice.
VS_CONST_WORLD_VIEW_TRANS_1: La première colonne du produit des transformations de l'espace et de la vue qui résultent dans la matrice de conversion des positions de l'ensemble des meshs aux positions dans l'espace. 
VS_CONST_WORLD_VIEW_TRANS_2: La deuxième colonne de cette même matrice.
VS_CONST_WORLD_VIEW_TRANS_3: La troisième colonne de cette même matrice.
VS_CONST_WORLD_VIEW_TRANS_4: La quatrième colonne de cette même matrice.
VS_CONST_WORLD_TRANS_1: La première colonne de la matrice de conversion des positions de l'ensemble des meshs aux positions dans l'espace.
VS_CONST_WORLD_TRANS_2: La deuxième colonne de la matrice de conversion des positions de l'ensemble des meshs aux positions dans l'espace.
VS_CONST_WORLD_TRANS_3: La troisième colonne de la matrice de conversion des positions de l'ensemble des meshs aux positions dans l'espace.
VS_CONST_WORLD_TRANS_4: La quatrième colonne de la matrice de conversion des positions de l'ensemble des meshs aux positions dans l'espace.
VS_CONST_INV_WORLD_TRANS_1: La première colonne de la matrice de conversion des positions dans l'espace aux positions dans l'ensemble des meshs.
VS_CONST_INV_WORLD_TRANS_2: La seconde colonne de la matrice de conversion des positions dans l'espace aux positions dans l'ensemble des meshs.
VS_CONST_INV_WORLD_TRANS_3: La troisième colonne de la matrice de conversion des positions dans l'espace aux positions dans l'ensemble des meshs.
VS_CONST_INV_WORLD_TRANS_4: La quatrième colonne de la matrice de conversion des positions dans l'espace aux positions dans l'ensemble des meshs.
VS_CONST_VIEW_TRANS_1: La première colonne de la matrice de conversion des positions dans l'espace aux positions sur l'écran.
VS_CONST_VIEW_TRANS_2: La deuxième colonne de la matrice de conversion des positions dans l'espace aux positions sur l'écran.
VS_CONST_VIEW_TRANS_3: La troisième colonne de la matrice de conversion des positions dans l'espace aux positions sur l'écran.
VS_CONST_VIEW_TRANS_4: La quatrième colonne de la matrice de conversion des positions dans l'espace aux positions sur l'écran.
VS_CONST_PROJ_TRANS_1: La première colonne de la matrice de conversion des positions sur l'écran aux positions dans l'espace de projection.
VS_CONST_PROJ_TRANS_2: La deuxième colonne de la matrice de conversion des positions sur l'écran aux positions dans l'espace de projection.
VS_CONST_PROJ_TRANS_3: La troisième colonne de la matrice de conversion des positions sur l'écran aux positions dans l'espace de projection.
VS_CONST_PROJ_TRANS_4: La quatrième colonne de la matrice de conversion des positions sur l'écran aux positions dans l'espace de projection.
VS_CONST_MATRIX_STACK: Cette constante est nécessaire pour les modèles utilisants le vertex skinning. Elle diffère de toutes les autres constantes parce qu'elle n'utilise par qu'un seul registre constant, mais tous les registres constants présents après celui défini. Le registre constant défini pour cette constant contiendra les valeurs x=nombre de matrices passées, y=registre constant de la première matrice, z=3, w=1. Ces valeurs sont requises pour convertir les indices de matrice de v2 en indices de registres constants décalés. Tous les registres constants derrière VS_CONST_MATRIX_STACK seront écrasés avec, les matrices de conversion transposées 4x3 des positions de l'ensemble des meshs aux positions de l'espace, de chacun des os. Vous pouvez utiliser m4x3 pour transformer les vecteurs avec celles-ci.
VS_CONST_CAMERA_POS: La position de la caméra (dans l'ensemble de meshs).
VS_CONST_MAT_AMBIENT: La couleur ambiante du matériau.
VS_CONST_MAT_DIFFUSE: La couleur diffuse du matériau.
VS_CONST_MAT_EMISSIVE: La couleur emissive du matériau.
VS_CONST_LIGHT_AMBIENT_COLOR: La couleur de la lumière ambiante.
VS_CONST_LIGHT0_COLOR: La couleur de la lumière de la première source de lumière définie pour ce shader (voir plus bas).
VS_CONST_LIGHT1_COLOR: La couleur de la lumière de la deuxième source de lumière définie pour ce shader (voir plus bas).
VS_CONST_LIGHT2_COLOR: La couleur de la lumière de la troisième source de lumière définie pour ce shader (voir plus bas).
VS_CONST_LIGHT_DIRECTIONAL_DIRECTION: La direction de la source de lumière directionnelle définie en tant que première source de lumière (voir plus bas).
VS_CONST_LIGHT_POINT0_POSITION_INV_RANGE: Ce paramètre dira à Ultimate 3D de passer la position dans l'ensemble des meshs de la première source de lumière aux éléments x,y et z de la constante du shader, et le nombre inverse de la portée de la lumière à l'élémént w.
VS_CONST_LIGHT_POINT1_POSITION_INV_RANGE: Même chose que ci-dessus mais pour la seconde source de lumière.
VS_CONST_LIGHT_POINT2_POSITION_INV_RANGE: Même chose que ci-dessus mais pour la troisième source de lumière.
VS_CONST_FOG_DISTANCE: Ce paramètre dira à Ultimate 3D de passer la distance de départ du brouillard à l'élément x, la distance de fin du brouillard à l'élément y, le nombre inverse de la distance de départ du brouillard à l'élément z et le nombre inverse de fin du brouillard l'élément w.
VS_CONST_CURRENT_TIME: Ce paramètre dira à Ultimate 3D de passer le temps, en secondes, qui s'est déroulé depuis que le système a démarré à l'élément x, le temps qui s'est déroulé depuis qu'Ultimate 3D a été initialisé à l'élément y, 0 à l'élément z et 1 à l'élément w.
VS_CONST_CURRENT_FRAME: Ce paramètre demandera à Ultimate 3D de passer la partie fractionnaire de la valeur actuelle de frame à l'élément x, et un moins le contenu de l'élément x à l'élément y. L'élément z contiendra 0 et l'élément w contiendra 1. Cette constante est prévue pour permettre l'implémentation du vertex tweening. 

ManuallySettableValues
Ce paramètre n'est obligatoire que si vous avez passé VS_CONST_MANUAL SETTABLE pour le paramètre précédent. Dans ce cas vous devrez donner dix valeurs sous forme de réels, qui seront définies comme valeurs pour les éléments x, y, z et w de la constante du shader.

Définir des constantes de pixel shader est plus facile, parce que vous n'avez pas ce large choix de constantes différentes. Les pixel shaders fonctionnent à un niveau moins élevé que les vertex shaders, et peuvent prendre au plus huit constantes de shader. C'est pourquoi le choix est plus petit ici. Voici la commande requise pour définir des constantes de pixel shader:

PSConstant %ConstantIndex %ConstantIdentifier %ManuallySettableValues

ConstantIndex
L'indice du registre de constante que vous souhaitez définir. Cette valeur peut être comprise entre 0 et 7.

ConstantIdentifier
Comme je l'ai déjà dit qu'il n'y a pas tellement d'identifiants différents que pour les constantes des vertex shader. En voici la liste:

PS_CONST_MANUAL_SETTABLE: Ce paramètre dit à Ultimate 3D qu'il est supposé définir la constante à la valeur donnée dans le paramètre suivant (ManualSettableValues).
PS_CONST_LIGHT_AMBIENT_COLOR: La couleur de la lumière ambiante.
PS_CONST_LIGHT_AMBIENT_COLOR_MATERIAL: La couleur résultant des couleurs de la lumière ambiante et de la couleur ambiante du matériau.
PS_CONST_LIGHT0_COLOR: La couleur de la première source de lumière définie pour cet effet (voir plus bas).
PS_CONST_LIGHT1_COLOR: La couleur de la deuxième source de lumière définie pour cet effet (voir plus bas).
PS_CONST_LIGHT2_COLOR: La couleur de la troisième source de lumière définie pour cet effet (voir plus bas).
PS_CONST_LIGHT0_COLOR_MATERIAL: La couleur de la première source de lumière définie pour ce shader, multipliée par la couleur diffuse du matériau.
PS_CONST_LIGHT1_COLOR_MATERIAL: La couleur de la deuxième source de lumière définie pour ce shader, multipliée par la couleur diffuse du matériau.
PS_CONST_LIGHT2_COLOR_MATERIAL: La couleur de la troisième source de lumière définie pour ce shader, multipliée par la couleur diffuse du matériau.
PS_CONST_MAT_AMBIENT: La couleur ambiante du matériau.
PS_CONST_MAT_DIFFUSE: La couleur diffuse du matériau.
PS_CONST_MAT_EMISSIVE: La couleur émissive du matériau.

ManuallySettableValues
Ce paramètre n'est obligatoire que si vous avez passé PS_CONST_MANUAL_SETTABLE au paramètre précédent. Dans ce cas vous devrez donner quatre valeurs réelles qui seront définies comme valeurs pour les éléments x, y, z et w pour la constante du shader.

Ce sont toutes les commandes dont vous avez besoin pour créer un effet de shader. Mais qu'en est-il des techniques de fallback (de repli)? En réalité, elles sont très simples à mettre en place. Il vous suffit d'écrire:

FallBackTechnique{
}

Entre les deux accolades, vous pouvez mettre une commande de définition d'un fichier de Vertex Shader et une commande de définition d'un fichier de Pixel Shader et autant de constantes de vertex shader et de pixel shader que vous voulez.

Etant donné que cela fait beaucoup de définitions, voici un exemple de fichier *.ufx valide (dans la mesure, bien sûr, où les fichiers de shaders auxquels il se réfère existent).

// Voici un exemple de fichier *.ufx
Ultimate3DEffectFile 1.0

// Le pixel shader ci-dessous utilise la version 1.4 des pixels shaders
VertexShaderFile shaders/ShaderEffect1_4.vsh
PixelShaderFile shaders/ShaderEffect1_4.psh

VSConstant 0 VS_CONST_WORLD_VIEW_PROJ_1
VSConstant 1 VS_CONST_WORLD_VIEW_PROJ_2
VSConstant 2 VS_CONST_WORLD_VIEW_PROJ_3
VSConstant 3 VS_CONST_WORLD_VIEW_PROJ_4

VSConstant 4 VS_CONST_MAT_DIFFUSE

// Le shader a besoin de ces valeurs pour calculer quelque chose. Elles peuvent aussi être définies avec la commande def du vertex shader.
VSConstant 5 VS_CONST_MANUAL_SETTABLE 3.14 6.28 -1 5

// Cette technique de fallback (de repli) sera utilisée si la version 1.4 des pixels shaders n'est pas supportée
FallBackTechnique{
// Le pixel shader ci-dessous utilise la version 1.2 des pixels shaders
VertexShaderFile shaders/ShaderEffect1_2.vsh
PixelShaderFile shaders/ShaderEffect1_2.psh
VSConstant 0 VS_CONST_WORLD_VIEW_PROJ_1
VSConstant 1 VS_CONST_WORLD_VIEW_PROJ_2
VSConstant 2 VS_CONST_WORLD_VIEW_PROJ_3
VSConstant 3 VS_CONST_WORLD_VIEW_PROJ_4

VSConstant 4 VS_CONST_MAT_DIFFUSE

VSConstant 5 VS_CONST_MANUAL_SETTABLE 3.14 6.28 -1 5
}

Application d'un shader

C'était beaucoup de théorie. Revenons en à l'utilisation pratique des effets de shader. Définir un effet de shader est très simple. Chacun des matériaux d'un modèle peut avoir son propre effet de shader. Pour le définir, une seule fonction suffit:

Cette fonction charge le fichier *.ufx donné et l'utilise pour le matériau précisé de l'objet qui appelle cette fonction.

LoadMaterialEffect(
MaterialIndex,
UFXFile
)

MaterialIndex
L'indice du matériau pour lequel vous souhaitez appliquer l'effet de shader.

UFXFile
Le fichier *.ufx à utiliser pour ce matériau. Si vous passez une chaîne vide ("") pour cet argument, l'effet actuel sera désactivé.

Si vous avez utilisé les vertex shaders avec Ultimate 3D v.1.31 vous vous souvenez sûrement qu'il n'y avait pas de fichier *.ufx. À la place, vous chargiez juste le shader et il recevait un ensemble de constantes de shader prédéfinies. Etant donné que je ne voulais pas rendre complètement incompatible les anciens codes sources avec la nouvelle version d'Ultimate 3D, il existe une fonction dans Ultimate 3D 2.0 et plus, qui fonctionne de la même façon. Elle ne demande pas de fichier *.ufx mais un fichier *.vsh.

Cette fonction définit le vertex shader donné pour le matériau choisi, en utilisant l'ensemble de constantes suivant:


0: VS_CONST_VIEW_TRANS_1
1: VS_CONST_VIEW_TRANS_2
2: VS_CONST_VIEW_TRANS_3
3: VS_CONST_VIEW_TRANS_4
4: VS_CONST_WORLD_VIEW_PROJ_TRANS_1
5: VS_CONST_WORLD_VIEW_PROJ_TRANS_2
6: VS_CONST_WORLD_VIEW_PROJ_TRANS_3
7: VS_CONST_WORLD_VIEW_PROJ_TRANS_4
8: VS_CONST_WORLD_TRANS_1
9: VS_CONST_WORLD_TRANS_2
10: VS_CONST_WORLD_TRANS_3
11: VS_CONST_WORLD_TRANS_4
12: VS_CONST_MAT_DIFFUSE

CreateMaterialVSEffect(
MaterialIndex,
VertexShaderFile
)

MaterialIndex
L'indice du matériau sur lequel le vertex shader sera appliqué.

VertexShaderFile
Le nom de fichier et le chemin du vertex shader qui sera utilisé (par exemple "effects\VSEffect.vsh").

Je vous déconseille d'utiliser cette fonction à moins que vous ne voulez utiliser des shaders développés pour Ultimate 3D 1.31. Si ce n'est pas le cas, vous devriez créer un fichier *.ufx. Ce qui est intéressant avec les fichiers *.ufx c'est qu'ils font la plupart du travail pour vous. Si vous souhaitez aider la communauté Ultimate 3D et que vous savez comment écrire des effets de shaders, vous pourriez faire un pack d'effets de shader sympas, incluant les fichiers *.ufx et le poster sur le forum. Avoir une collection d'effets de shaders sympas serait vraiment cool.

Définition des contantes de shader

La plupart des constantes de shader requises peuvent être définies en utilisant les fichiers *.ufx. Mais qu'en est-il de celles ne pouvant être calculées automatiquement par Ultimate 3D? Pour celles là, il existe deux fonctions très simple, permettant de modifier les valeurs des constanstes de vertex et de pixel shader, qui ne sont pas définies automatiquement par Ultimate 3D. Voici une description de celles-ci:

Cette fonction définit une nouvelle valeur pour les registres constants de vertex shader ayant l'indice donné, dans la mesure où il n'est pas défini automatiquement par Ultimate 3D.

SetMaterialEffectVSConstant(
MaterialIndex,
VSConstantIndex,
XValue, YValue, ZValue, WValue
)

MaterialIndex
L'indice du matériau qui utilise l'effet.

VSConstantIndex
L'indice du registre constant que vous souhaitez modifier. Cette valeur doit être inclue entre 0 et 95.

XValue, YValue, ZValue, WValue
Les nouvelles valeurs du registre constant. Cela peut être n'importe quelle valeur réelle.

La fonction SetMaterialEffectPSConstant(...) fait exactement la même chose pour les constantes de pixel shader. La seule différence est que l'indice du registre constant doit être entre 0 et 7. C'est pourquoi je ne l'expliquerai pas en détail ici.

Un peu plus haut dans ce chapitre, j'ai dit de regarder 'ci-dessous' un certain nombre de fois, lorsque je parlais des registres constants donnant des informations à propos des sources de lumière. Nous y voici enfin, lisez ce qui suit. Vous pouvez définir trois sources de lumière à utiliser pour l'effet de shader. Pour cela, il y a la fonction suivante:

Cette fonction définit les trois sources de lumière à utiliser avec l'effet de shader du matériau donné de l'objet de modèle.

SetMaterialEffectLightSource(
MaterialIndex,
LightSourceID1, LightSourceID2, LightSourceID3
)

MaterialIndex
L'indice du matériau pour lequel les sources de lumière seront définies.

LightSourceID1, LightSourceID2, LightSourceID3
L'Id d'instance Game Maker des sources de lumière, qui seront utilisées pour l'effet de shader. Vous pouvez entrer l'id des objets pour ces paramètres. Si vous n'avez pas besoin des trois sources de lumières, mettez 0 pour celles que vous ne voulez pas.

Si vous avez lu l'ensemble du chapitre et des chapitres à propos de la programmation des shaders, vous devez être vraiment content. Vous savez maintenant comment utiliser la plus flexible et adaptable des fonctionnalités d'Ultimate 3D. Ne la sous-estimez pas. Au début, il se peut que vous ne sachiez pas quoi faire avec les shaders, mais bien vite vous aurez des idées d'application de cette technique. D'autant qu'il y a des tonnes de tutoriaux sur internet à propos d'effets vraiment superbes qui peuvent être réalisés à l'aide de shaders. En général, il y a un exemple de donné. Je vous conseille de jouer énormément avec les shaders pour les apprendre. C'est vraiment la meilleure façon d'amasser de l'expérience. Tous les effets que vous faites ne doivent pas nécessairement avoir de sens, du moment que vous apprennez quelque chose en les faisant. En changeant seulement quelques lignes dans le code d'un shader vous pouvez obtenir des effets vraiments intéressants, que vous ne pourriez réaliser sans shaders. Par exemple, vous pouvez donner les normales des vertex en tant que couleur diffuse des vertex (dans le vertex shader).

Maintenant, amusez-vous bien :D .



© Christoph Peters. Certains droits réservés. (Traduction FR 04/2008, Franck Vernel / Damien Buhl).

Creative Commons License XHTML 1.0 Transitional