CgFX - Des shaders temps réel dans le viewport Maya! - Part 4
Par Narann le mercredi, 4 août 2010, 23:49 - Script et code - Lien permanent
Si vous êtes arrivés jusque là, vous devez surement vous dire: "Qu'est ce que c'est que ce tuto de shader de merde ou l'on vous fait bouffer trois parties sans voir une seule texture?".
Rassurez-vous, vos efforts vont être récompensés! Nous allons attaquer les textures! :sourit:
Vous allez voir que leur mise en place est relativement simple. Cette partie sera moins longue que les autres car je préfère l'aborder dans un seul billet et laisser au prochain, un seul sujet, le bump!
Ajout d'une texture
Vous l'attendiez? Vous allez voir que ce n'est pas compliqué! :baffed:
Sommaire:
- Les attributs
- Mise à jour des structures
- Les UV: Vertex Shader et Pixel Shader
- Switch entre la diffuse color et la texture
- Conclusion
Les attributs
Comme d'habitude, il va falloir déclarer notre texture. Cette déclaration se fait en deux temps. Voici le code:
// Textures texture diffuseTexture < string ResourceName = "default_color.dds"; string UIName = "Diffuse Texture"; string ResourceType = "2D"; >; sampler2D diffuseSampler = sampler_state { Texture = <diffuseTexture>; MinFilter = LinearMipMapLinear; MagFilter = Linear; WrapS = Repeat; WrapT = Repeat; MaxAnisotropy = 16.0; };
Vous constaterez dans un premier temps que nous créons un attribut "texture". Si vous avez suivie ce tuto dans l'ordre, vous devriez déjà être en possession de cette texture, elle était donnée dans le shader d'exemple téléchargé en partie 1.
L'attribut suivant est de type sample2D. C'est ici que nous allons définir tous les paramètres "techniques" de notre texture.
Le premier paramètre:
Texture = <diffuseTexture>;
Est un lien vers notre "objet" texture créé plus haut.
MinFilter = LinearMipMapLinear;
Cela applique un filtre linéaire sur votre texture, quand les pixels de la texture sont plus petits que les pixels de votre écran (texture loin), et force à utiliser le mipmap. Et l'inverse:
MagFilter = Linear;
Cela applique un filtre linéaire sur votre texture, quand les pixels de la texture sont plus grands que les pixels de votre écran (texture proche).
WrapS = Repeat; WrapT = Repeat;
Si vous faite de la 3d, vous devez savoir à quoi ça correspond: C'est le comportement des textures quand on arrive au bout.
MaxAnisotropy = 16.0;
Héhé! Ici on demande à la carte graphique d'utiliser le filtrage anisotropique au lieu du filtrage linéaire, pour la texture. Le résultat est qu'il y a plus que piquet dans vos textures quand elles sont loin. Elles paraissent plus nettes. Vu que j'ai une grosse bite carte graphique pardon, je peux mettre à 16. Renseignez-vous sur la valeur maximum que supporte votre carte graphique. Sinon ça risque de ne pas marcher. :seSentCon:
Mise à jour des structures
L'étape suivante, avant d'aller utiliser nos textures, c'est de définir les arguments de notre structure en entrée et en sortie (on appele ça les varying, les "variant" en français). On définit ce que "transporte" les vertex:
struct vIN { float3 Position : POSITION; // La position du vertex en entrée float4 Normal : NORMAL; // La normal du vertex en entrée float4 UV : TEXCOORD0; // un set d'uv };
Et un set d'UV ajouté à nos vertex!
Rappelez-vous, c'est le vertex shader qui prend les varyings de vIN, les modifies (ou non) en créant vOUT, et c'est le Pixel Shader qui prend vOUT pour s'en servir. :zinzin:
struct vOUT { float4 Position : POSITION; // La position du vertex en sortie (doit être de type float4) float3 PointLight0Vec : TEXCOORD0; float3 PointLight1Vec : TEXCOORD1; float3 WorldNormal : TEXCOORD2; float3 WorldView : TEXCOORD3; float2 UV : TEXCOORD4; };
Voila! Maintenant, nos vertex et pixels sont prêt à accueillir nos UVs.
Les UVs: Vertex Shader et Pixel Shader
L'implémentation dans le Vertex Shader est d'une facilité déconcertante:
// On copie les UV OUT.UV = IN.UV.xy;
Trop dur... :siffle:
Du coup, je ne prends même pas la peine de vous expliquer tellement c'est simple...
Collez ça au dessus du "return OUT" et c'est fait!
Passons au Pixel Shader:
//Calcul la valeur de la couleur de la Diffuse float3 diffuseColorResult; //diffuseColorResult = diffuseColor.rgb; // On commente cette ligne pour ne récupérer que la couleur de la texture. diffuseColorResult = tex2D(diffuseSampler, IN.UV).rgb; diffuseColorResult *= diffuseFactor;
Ici point de diffuse, on commente la ligne qui récupère les valeurs RGB de la couleur (ne la supprimez pas, on va y revenir), puis on demande au shader de récupérer la couleur du sampler2D, et donc, de notre texture...
Faites mumuse avec les paramètres, histoire de voir comment tout ça fonctionne.
Vous pouvez télécharger le shader ici: ->cgfx_tuto_006.7z<-
Switch entre la diffuse color et la texture
Bon, c'est cool cette histoire mais si on veut pouvoir switcher entre la couleur ou la texture, on l'a dans l'os...
On va donc faire un petit switch (une checkbox on/off) pour changer ça. Retournez au niveau des paramètres et ajoutez ça:
bool bUseDiffuseTexture < string UIName = "Use Diffuse Texture"; string UIWidget = "RadioButton"; > = true;
Personnellement, j'ai calé ça dans la diffuse. :redface:
Maintenant allez directement dans le Pixel Shader et transformez les lignes de toute à l'heure:
//Calcul la valeur de la couleur de la Diffuse float3 diffuseColorResult; //diffuseColorResult = diffuseColor.rgb; diffuseColorResult = tex2D(diffuseSampler, IN.UV).rgb; diffuseColorResult *= diffuseFactor;
Par ça:
//Calcul la valeur de la couleur de la Diffuse float3 diffuseColorResult; if(bUseDiffuseTexture == true) { diffuseColorResult = tex2D(diffuseSampler, IN.UV).rgb; } else { diffuseColorResult = diffuseColor.rgb; } diffuseColorResult *= diffuseFactor;
Vous l'aurez compris, on fait un simple "if" pour savoir si oui ou non on n'utilise la texture.
Dans un commentaire, Glim me faisait remarquer qu'utiliser des conditions dans son shader était mauvais en terme de performance. Après renseignement, il s'avère en effet exact que l'utilisation des conditions est à proscrire, mais uniquement si elles sont utilisées sur des "varyings" (vIN, vOUT), ce qui n'est pas le cas ici car elles sont utilisé sur des "uniforms" (des valeurs qui ne changent pas durant la durée du rendu).
Vous pouvez télécharger le shader ici ->cgfx_tuto_007.7z<-
Conclusion
La partie concernant les textures est terminée. Vous voyez? Elle n'était pas compliquée! J'espère que vous êtes un peu moins frustrés maintenant. :hihi:
N'hésitez pas à faire des variations de votre shader! Il n'y a que comme ça que vous comprendrez et vous amuserez (j'espère... ^^ )
Si je n'ai pas été clair quelque part, laissez un commentaire et je corrigerai!
Le prochain tuto concernera le bump mapping. Vous allez voir que c'est beaucoup plus costaud!
A bientôt!
Dorian