### I.5 Matériaux

Chaque matériel utilisé dans le jeu doit être défini dans son propre fichier texte, dont le nom finit par ".mat", et qui contient une série de commandes qui permettent au moteur de bien l'afficher.

Le fichier doit absolument commencer par une ligne contenant Ark Shader Def, sans cette chaine de caractère, le matériel ne serait pas pris en compte.
Usuellement, cette chaine de caractère est mise dans un commentaire de type // sur la première ligne du fichier (Cf l'exemple). De plus toutes le bloc de définition en lui-même est entouré de deux accolades {}.

Par défaut, le matériel n'a ni texture ni éclairage. Un matériel non éclairé ne s'affichera pas en noir, mais il s'affichera avec la couleur exacte de la texture choisie. (comme si on avait mis une réflexion ambiente à 1.0,1.0,1.0 et ni réflexion diffuse ni réflexion spéculaire).

#### I.5.1 Lumière

Bon, maintenant on veut spécifier les paramètres de réflexion du matériel. Comment faire ? Simple, il suffit de rajouter trois lignes, une pour chacun des types de réflexion voulue :

        Ambient = couleur;
        Diffuse = couleur;
        Specular = couleur;

Où couleur est un couple de trois valeurs réelles entre 0 et 1, du type {R,V,B} (rouge vert bleu), par exemple {1.0, 1.0, 0.0} pour du jaune.

#### I.5.2 Autres paramètres

Toujours dans les paramètres globaux, il existe un paramètre pour spécifier si on peut marcher sur ce matériel (par exemple, on ne peut pas marcher sur de la lave), ce qui change le comportement du pathfinder.

       /* Si Walkable vaut True, alors on peut marcher sur ce matériel.
        * Si Walkable vaut False, il est impossible de marcher dessus.
        */
        Walkable = True;

#### I.5.3 Passes

Ensuite vient une série de passes qui permet l'affichage à proprement parler. Chaque passe est précédée du mot-clé Pass, et est entourée d'un couple d'accolades.

        Pass
        {
          // Première passe. La liste des propriétés de cette passe doit
          // être comprise entre ces accolades.
          // ...
        }

        Pass
        {
          // Deuxième passe.
        }

#### I.5.4 Texture

Chaque passe contient des informations sur la texture à employer...

          Map = "{game}/data/textures/grass.png";

#### I.5.5 Z-Buffer

... Ainsi que des informations sur le comportement du ZBuffer. Tout d'abord, est-ce que les objets dessinés avec ce matériel doivent cacher les objets qui peuvent apparaître derrière ? Cette propriété est dirigée par la variable DepthWrite. Par exemple, les ciels et certains systèmes de particules ne doivent pas masquer les objets, on met donc la valeur DepthWrite à False.
Un autre paramètre est lié au Z-Buffer : la valeur de DepthFunc permet de définir quand un objet doit être affiché ou non (en terme de profondeur) :

- Si DepthFunc = Equal, alors il ne sera affiché que s'il est à la même distance que ce qui était auparavant à l'écran.
- Si DepthFunc = LEqual, l'objet qui utilise le matériel ne sera affiché que s'il est plus proche que l'objet précédemment à l'écran. (c'est le mode par défaut).
- Si DepthFunc = Always, l'objet sera affiché quelque soit la distance de ce qui était à l'écran. Ce mode est utilisé pour dessiner les menus, fenêtres, etc, qui se dessinent par dessus le monde de toute façon.

#### I.5.6 Mélange de textures (Blending)

Le blending, qui permet de gérer des effets de transparence poussés est un domaine assez complexe. Plutôt que d'essayer d'expliquer comment il fonctionne nous allons les deux modes qui seront utilisé 90% du temps. Après vous pouvez expérimenter, changer les valeurs afin de voir ce qui correspond à l'effet que vous recherchez.

Tout d'abord, voyons la syntaxe :

        Pass
        {
           // ... Paramètres ...
           Blending = (srcblend, dstblend);
        }

En gros la formule pour calculer la couleur affichée à l'écran, quand on dit que srccolor est la couleur de l'objet, dstcolor la couleur précedemment à l'écran est :

          dstcolor = srcfactor * srccolor + dstfactor * dstcolor;

Valeur donnée à srcblend (ou dstblend). | srcfactor (ou dstfactor).
--- | ---
One | 1.0
Zero | 0.0
SrcColor | srccolor
OneMinusSrcColor | 1.0 - srccolor
SrcAlpha | srcalpha
OneMinusSrcAlpha | 1.0 - srcalpha
SrcColor | srccolor
OneMinusSrcColor | 1.0 - srccolor
SrcAlpha | srcalpha
OneMinusSrcAlpha | 1.0 - srcalpha

(srcfactor et dstfactor sont déterminés en fonction de la valeur donnée à srcblend et dstblend)

Deux modes très utilisés :

- Mode mélange : utilisé pour les objets transparent, la couleur de l'objet se mélange avec la couleur de fond en fonction du facteur de transparence de la texture ou de l'objet lui-même (alpha channel). Blending = (SrcAlpha, OneMinusSrcAlpha);
- Mode additif : la couleur de l'objet s'ajoute à la couleur de fond, celle ci tend donc rapidement vers le blanc. Cela peut être utilisé pour certains systèmes de particule (feux), et cela _DOIT_ être utilisé pour les textures de sol : les dégradés entre différents sols doivent impérativement utiliser ces valeurs.
  Blending = (SrcAlpha, One);

#### g. Génération des coordonnées de texture...

Optionnellement, les coordonnées de textures peuvent être générées. Cela à divers intêrets. Tout d'abord cela peut permettre l'animation de textures, comme le déplacement de l'eau ou de lave. De plus cela permet des effets qui simulent la réflexion, comme l'environment mapping.

Génération linéaire : Cela n'a de sens que pour les textures qui se répètent, comme les textures de sol, ou les textures de liquides. Syntaxe :

        TextureGen = Linear ({ua, ub, uc, ud},
                             {va, vb, vc, vd});

Les coordonnées (u,v) de textures sont calculées en fonction de la coordonnée (x,y,z) du point :

        u = ua * x + ub * y + uc * z + ud;

        v = va * x + vb * y + vc * z + vd;

Pour une texture projetée verticalement qui se répète une fois par mètre, on écrira :

        TextureGen = Linear ({1.0, 0.0, 0.0, 0.0},
                             {0.0, 0.0, 1.0, 0.0});

Si on veut qu'elle se répète deux fois par mètre, on remplacera les 1.0 par des 0.5, et ainsi de suite...

Environment mapping : ce mode de génération de texture se base sur les normales de l'objet, et permet de simuler la réflexion. On distingue l'environment mapping sphérique, qui se fait avec une seul texture "courbé" (comme un globe aplati), et l'environment mapping cubique, qui se fait avec 6 textures, une pour chaque face du cube.
Le choix de l'un de ces deux modes est fait en fonction des capacités de la carte graphique (à cette heure, seule la GeForce2 supporte le cubic environment mapping), il suffit donc d'écrire une seule ligne :

        TextureGen = Environment;

#### I.5.7 Exemple complet

    // Ark Shader Def
    {
    	// Propriétés de réflexion du matériel
    	Ambient = {0.2, 0.2, 0.2, 1.0};
    	Diffuse = {0.8, 1.0, 0.8, 1.0};
    	Specular = {0.5, 0.6, 0.5, 1.0};

    	// Eh oui, on peut marcher sur l'herbe :)
    	Walkable = True

    	Pass
    	{
    		Map = "{game}/data/textures/grass.png";
    		DepthFunc = LEqual;
    		DepthWrite = True;

    		// Toutes les textures de terrain doivent avoir un blending
    		// additif, et un mapping linéaire vertical.
    		Blending = (SrcAlpha, One);
    		TextureGen = Linear ({0.0625, 0.0, 0.0, 0.0},
    		                     {0.0, 0.0, 0.0625, 0.0});
    	}
    }