Dorian Fevrier's blog - Mot-clé - ddsJe m’appelle FEVRIER Dorian, je suis infographiste 3D passionné par mon métier, l’informatique en général, l’internet, la programmation et l’évolution de tout ce petit monde. Vous trouverez sur ce blog des tutoriaux, mes coups de cœurs, avis, etc.2024-01-02T23:48:05+01:00FEVRIER Dorianurn:md5:695d9c73474c33ce3dab043823509c4bDotclearCgFX - Des shaders temps réel dans le viewport Maya! - Part 1urn:md5:f74859b2f7a2ea14091b212d19b9bb342010-04-26T23:43:00+02:002020-11-14T22:34:58+01:00NarannScript et codecgfxddsfrhardwaremayamental rayshader<p><img src="https://www.fevrierdorian.com/blog/public/logos/CG_logo150.png" alt="CG_logo150.png" style="float:left; margin: 0 1em 1em 0;" title="CG_logo150.png, juin 2009" />Lors d'un ancien post, <a href="https://www.fevrierdorian.com/blog/index.php?post/2009/01/16/dds-textures">je vous parlais des textures dds</a>. Je pensais que ce format résolvait tout les problèmes de plantage dûs à l'affichage mais ce n'a pas été complètement le cas. En effet, même si les plantages étaient mineurs, il restaient présents lors de l'ouverture-fermeture récurrentes des scènes. J'ai donc commencé à chercher d'autres solutions. Je me suis tourné vers les hardwares shaders (elle m'intriguait depuis longtemps cette connexion) et je viens de découvrir le langage CgFX. Après quelques galères, j'ai réussi à faire ce que je voulais dans Maya et, comme vous le savez, je ne peux pas m'empêcher de <del>frimer</del> partager (modestement en fait) mes découvertes sur le sujet, tellement (encore une fois) ce genre d'informations manque sur le net et (d'une certaine façon) fait défaut à l'infographie 3D française. :mechantCrash:</p> <center>:longBar:</center>
<h5>Bon alors Cg c'est quoi?</h5>
<p>Cg ça veut dire "C for Graphics". C'est un langage haut niveau (ne traduisez pas par "langage de noobs" ça reste du C <sup></sup> et c'est déjà bien balèze pour le scripteur que je suis). Je ne vais pas vous recopier wikipedia, la page est <a href="http://en.wikipedia.org/wiki/Cg_(programming_language)" hreflang="en">ici</a>. Grosso modo, c'est un langage qui permet de programmer des vertex shaders (skinning pour les jeux vidéo par exemple) et des pixel shaders (la représentation visuel de l'objet).</p>
<center>:longBar:</center>
<h5>C'est pour les jeux vidéos ton truc... A quoi ça sert dans notre métier?</h5>
<p>C'est une bonne question. A priori, il n'est pas particulièrement utile d'avoir un rendu viewport de qualité quand nous travaillons. Et pourtant. Il peut arriver, dans certains projets que le retour viewport ait besoin d'une qualité minimum:</p>
<ul>
<li>Pour faciliter une validation par un réal'.</li>
<li>Pour permettre aux animateurs de mieux travailler.</li>
<li>Car, si combiné aux textures .dds (cf <a href="https://www.fevrierdorian.com/blog/index.php?post/2009/01/16/dds-textures">ancien billet qui en parle</a>), les <a href="http://fr.wikipedia.org/wiki/Shader" hreflang="fr">shaders</a> CgFX peuvent utiliser pas mal de textures sans trop saturer la mémoire (et donc, diminuer les plantages). Ça demande une certaine préparation (un pipeline qui charge les .dds quand on en a besoin et passe en .map au moment du rendu) mais ça se fait (je l'ai fait sur une production qui à duré un an et demi sans aucun souci).</li>
<li><del>Pour se la péter devant ses clients/employeurs</del>, ou pas... Personnellement, je trouve qu'un playblast bien propre, ça fait toujours plus sérieux, mais ce n'est que mon avis...</li>
<li>Éviter de bricoler avec les shaders pour "mieux voir" ce qui ce passe dans ce p*tain de viewport. :nevroz:</li>
</ul>
<p>Pour "vendre" leur langage, Nvidia a fait <a href="http://developer.nvidia.com/docs/IO/8229/Cg-Workflow-And-Tools.pdf" hreflang="en">un jolie paper</a> qui fait un rapide tour de ce qu'il est possible de faire avec CgFX. Il vaut le détour car il est très orienté "Computer graphics" avec des exemples d'application Maya et 3Ds Max.</p>
<center>:longBar:</center>
<h5>Petit exemple</h5>
<p>Un exemple rapide trouvé sur youtube:</p>
<center>
<iframe width="580" height="330" src="https://www.youtube-nocookie.com/embed/EzH4q0lq8K8" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</center>
<p>C'est quand même plus classe dans une démo que ce qu'on à l'habitude de voir non? :laClasse:</p>
<center>:longBar:</center>
<h5>Par quoi on commence?</h5>
<p>En effet, le plus dur, c'est de commencer, pour la petite histoire, j'ai fait simple: "<a href="http://www.google.fr/search?q=hardware+shader+maya+cgfx" hreflang="en">Google is your friend</a>"...
Au fil de mes recherche je suis donc tombé sur la page de <a href="http://www.vailias.com/" hreflang="en">Brandon Newton</a> qui proposait <a href="http://www.vailias.com/CGFX_Tut.htm" hreflang="en">un tutorial</a> sur les CgFX shader dans Maya (Le site n'est plus disponible...).</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/Techniques_1_.jpg" alt="Techniques_1_.jpg" style="display:table; margin:0 auto;" title="Techniques_1_.jpg, juin 2009" /></p>
<p>J'ai donc commencé à tripatouiller <a href="http://www.vailias.com/Technical.html" hreflang="en">le shader</a> qu'il proposait pour en tirer ce que j'en voulais. J'ai viré tout ce que je n'avais pas besoin pour l'instant en me promettant d'y revenir (Normal map, spéculaire, glow...) pour ne laisser plus qu'un seul paramètre, la texture... Son shader ne gérant pas la transparence, j'ai du l'ajouter moi même, ce qui n'a pas été évident, ceci étant ma première expérience en "shading langage" (heureusement que j'avais regardé l'OpenGL sinon je n'y serais jamais arrivé, comme quoi, tout est lié :hehe: ).</p>
<center>:longBar:</center>
<h5>Ça été facile?</h5>
<p>Non <sup></sup>' J'ai méchamment galéré (c'est aussi la raison de ce billet) et je suis passé par plusieurs techniques avant de réussir à avoir un alpha convenable. Je me suis beaucoup aidé du <a href="http://www.mentalwarp.com/~brice/brdf.php" hreflang="en">GenericBRDF shader</a> de <a href="http://www.mentalwarp.com/~brice/" hreflang="en">Brice Vandemoortele</a> que je vous encourage très fortement à télécharger, utiliser, regarder, kiffer!).
Il y a pas mal de façons d'obtenir les mêmes choses et chacune ayant ses spécificités. :redface:</p>
<center>:longBar:</center>
<h5>Avant de commencer...</h5>
<p>...je tiens à vous dire que les informations que vous allez lire <del>sont top secret et nullement référencés dans un quelconque registre des services de renseignement américain</del> ne sont que le fruit de mes investigations personnelles mêlées à mes (maigres) connaissances en temps réel... Elles sont donc à prendre avec précaution. Si vous y trouvez une erreur, je vous invite à laisser un commentaire avec une explication que je puisse moi même comprendre et modifier mon billet en conséquent. :sourit:</p>
<center>:longBar:</center>
<h5>Lets go! Théorie now! :marioCours:</h5>
<p>Bon, les hardware shaders dans Maya c'est quoi? Et bien ce que vous voyez tous simplement! :hehe: En effet, dans votre viewport Maya, ce que vous voyez c'est une représentation des informations de votre scène.</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/schemaSceneGraph001.png" alt="schemaSceneGraph001.png" style="display:table; margin:0 auto;" title="schemaSceneGraph001.png, juin 2009" /></p>
<p>Il y a plusieurs éléments mais le plus important est le scenegraph. Ce terme n'a pas de définition précise mais, quand on en parle, il s'agit généralement de l'architecture (l'organisation) des données dans la mémoire (<a href="http://fr.wikipedia.org/wiki/Graphe_de_sc%C3%A8ne" hreflang="fr">Définition Wikipedia</a>). C'est à partir de ces informations (position des points, uvs, lumières) que vous pouvez "représenter" votre scène dans n'importe quelle façon (dans un logiciel de rendu par exemple). Ainsi, votre shader à plusieurs représentations (Viewport, Maya Software, Mental Ray).</p>
<p>Au même titre que l'on peut, dans un shading group, forcer l'utilisation d'un shader mental ray d'un certain type alors qu'on utilise un type tout autre dans Maya Software:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_004.png" alt="cgfx_intro_004.png" style="display:table; margin:0 auto;" title="cgfx_intro_004.png, juin 2009" /></p>
<p><em>Dans le cas ci dessus, si vous rendez le shader avec mental ray vous aurez un mia_material_x, et si vous le rendez avec Maya Software, vous aurez un rampShader</em></p>
<p>Il est possible (dans certains shaders) de forcer l'utilisation d'un harware shader dans le viewport:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_005.png" alt="cgfx_intro_005.png" style="display:table; margin:0 auto;" title="cgfx_intro_005.png, juin 2009" /></p>
<center>:longBar:</center>
<h5>Pédalage...</h5>
<p>:reflechi: Une explication, mais ce n'est que mon interprétation: Pour la plupart des shaders (ceux de base, du genre Lambert), il y a leur version Maya software, Mental Ray, et Hardware. Je suppose que la version Maya Software et la version Hardware sont codées en dur dans l'application. La version Mental Ray étant chargée depuis la dll:</p>
<blockquote><p>base.dll</p></blockquote>
<p>Sans que l'utilisateur est à s'en soucier. A l'époque (lors de l'intégration de Mental Ray), l'idée était qu'on puisse rendre ses scènes faites pour Maya Software en Mental Ray sans avoir à retravailler ses shaders. Il en résulte une intégration "transparente" pour l'utilisateur final.</p>
<p>EDIT: Je viens de compiler lambertShader.cpp et je dois dire que je suis troublé... J'ai un feedback de la couleur et la transparence dans le viewport pourtant il n'y a pas une seule ligne dans le code qui parle d'OpenGL (ou n'importe quoi relatif à l'affichage hardware). J'en conclus donc une chose (moi et mes conclusions foireuses :seSentCon: ): C'est Maya qui gère ça en interne... <del>Traduisez, ça sent le caca...</del>. Ainsi, Maya ne ferait pas la différence entre Hardware Shader et Software Shader (Raytrace en moins)... J'avoue ne pas tout comprendre mais il semble qu'historiquement (encore une fois...) Alias (à l'époque) souhaitait proposer une API qui permette de développer des shaders sans se soucier de son affichage (et inversement). Tout cela doit donc se passer dans le "core" de Maya. Si c'est réellement ça, c'est typiquement le genre de truc que je peux pas supporter... Mais je sais aussi qu'on peut dériver les classes donc je suppose qu'il est possible de dériver la composante hardware de son shader et de faire mumuse avec OpenGL (ou <a href="https://www.fevrierdorian.com/blog/index.php?post/2009/01/07/Apprendre-le-MEL-%28Ou-plut%C3%B4+t%2C-%C3%A9ssayer...%29#openGLVersionMaya">OpenMGL</a> :baffed: ). Je vais donc m'arrêter ici afin d'éviter de m'enfoncer dans des interprétations dignent d'un scripteur qui se prend pour un développeur...</p>
<center>:longBar:</center>
<h5>Reprenons</h5>
<p>Comme vous l'avez vu ci dessus, on peut facilement distinguer le shader Maya Software (connecté au "Surface material") et le shader Mental Ray. J'ai souvent vu des infographistes (moi le premier) <del>utiliser</del> bricoler les shader Maya Sofware pour "overrider" l'affichage, dans le viewport, des shaders Mental Ray (qui sont souvent vert ou rouge, pas très bandant...). L'idée de cette manipulation est, vous l'aurez compris, de pouvoir afficher dans le viewport un shader indépendamment du shader rendu (souvent, pour mettre une textures, car quand on présente une scène de rendu avec que des mia, c'est pas la joie pour celui qui la regarde votre viewport).</p>
<p>C'est le même principe que je vous propose de regarder aujourd'hui mais au lieu de bidouiller les shaders Maya Software, nous allons coder un CgFX Shader (et prendre quelques bonnes habitudes).</p>
<center>:longBar:</center>
<h5>Let's go 2 - Le vrai!</h5>
<p>Nous allons, dans un premier temps activer le plugin qui nous permettra d'ouvrir des fichiers CgFX:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_001.png" alt="cgfx_intro_001.png" style="display:table; margin:0 auto;" title="cgfx_intro_001.png, juin 2009" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_002.png" alt="cgfx_intro_002.png" style="display:table; margin:0 auto;" title="cgfx_intro_002.png, juin 2009" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_003.png" alt="cgfx_intro_003.png" style="display:table; margin:0 auto;" title="cgfx_intro_003.png, juin 2009" /></p>
<p>Il suffira maintenant d'aller chercher notre fichier .cgfx pour havoir un hardware shader qu'il ne nous restera plus qu'a connecter ici:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_005.png" alt="cgfx_intro_005.png" style="display:table; margin:0 auto;" title="cgfx_intro_005.png, juin 2009" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_013.png" alt="cgfx_intro_013.png" style="display:table; margin:0 auto;" title="cgfx_intro_013.png, avr. 2010" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_014.png" alt="cgfx_intro_014.png" style="display:table; margin:0 auto;" title="cgfx_intro_014.png, avr. 2010" /></p>
<p>Le site de Vailias n'étant plus disponible, je vous invite à aller sur <a href="http://developer.download.nvidia.com/shaderlibrary/webpages/cgfx_shaders.html" hreflang="en">le site de Nvidia</a> qui propose pas mal de shaders HLSL et CgFX et de prendre le "blinn bump reflect" qui fait des choses intéressantes:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_012.png" alt="cgfx_intro_012.png" style="display:table; margin:0 auto;" title="cgfx_intro_012.png, avr. 2010" /></p>
<p>Téléchargez la version CgFX, dézippez la et allez chercher le fichier .cgfx. Vous aurez à relinker les trois textures dds (voir <a href="https://www.fevrierdorian.com/blog/post/2009/01/16/dds-textures">mon ancien billet</a> pour des explications sur ce format de fichier):</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_015.png" alt="cgfx_intro_015.png" style="display:table; margin:0 auto;" title="cgfx_intro_015.png, avr. 2010" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_016.png" alt="cgfx_intro_016.png" style="display:table; margin:0 auto;" title="cgfx_intro_016.png, avr. 2010" /></p>
<blockquote><p>Note au utilisateurs de carte graphique ATI Radeon, passez <a href="https://www.fevrierdorian.com/blog/post/2010/04/25/CgFX-Faire-du-Bump-mapping-avec-les-cartes-ATI-Radeon">par ici</a> si vous voulez que tout fonctionne.</p></blockquote>
<p>Pour l'instant, ça ne rend pas grand chose dans le viewport, vous en conviendrez... :seSentCon: En effet, il faut configurer deux trois choses.</p>
<p>Sélectionnez votre cgfxShader:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_017.png" alt="cgfx_intro_017.png" style="display:table; margin:0 auto;" title="cgfx_intro_017.png, avr. 2010" /></p>
<p>Note: L'interface n'est pas terrible. En effet, les shaders CgFX de Nvidia n'utilisent pas les fonctions d'interfaçage que peut prendre Maya (un vrai widget de couleur plutôt que trois valeurs à entrer à la main. Nous verrons plus tard comment les utiliser).</p>
<p>Vous remarquez un champ vide, celui de la lampe. Créez une pointLight et copiez collez son nom:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_018.png" alt="cgfx_intro_018.png" style="display:table; margin:0 auto;" title="cgfx_intro_018.png, avr. 2010" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_019.png" alt="cgfx_intro_019.png" style="display:table; margin:0 auto;" title="cgfx_intro_019.png, avr. 2010" /></p>
<p>Hop! C'est déjà mieux. Vous pouvez tourner autour (Ouah! Ça reflète avec du bump et tout!) et commencer à modifier les paramètres pour vous amuser (on fait comme on peut... :hihi: )</p>
<p>Bon, c'est super cool mais comment on en fait un nous même?</p>
<center>:longBar:</center>
<h5>Ouverture et analyse du shader</h5>
<p>Et bien pour le savoir, allez ouvrir "blinn_bump_reflect.cgfx" avec un éditeur de texte. Je vous conseille <a href="http://notepad-plus.sourceforge.net/fr/site.htm" hreflang="fr">Notepad++</a>, passez le en langage C:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_020.png" alt="cgfx_intro_020.png" style="display:table; margin:0 auto;" title="cgfx_intro_020.png, avr. 2010" /></p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_021.png" alt="cgfx_intro_021.png" style="display:table; margin:0 auto;" title="cgfx_intro_021.png, avr. 2010" /></p>
<p>Bam! :aupoil: Là il va falloir analyser un peut... Avant de commencer, vous devez être conscient de la différence entre les Vertex Shaders et les Pixels Shaders (cf <a href="http://www.shadows.fr/tutoriaux-3D/shaders-3d-temps-reel" hreflang="fr">le billet de Shadow</a> qui explique bien ces différences)</p>
<p>Si vous regardez bien, vous verrez que le code est décomposé comme suit:</p>
<p>Déclarations des variables globales, divisées en deux parties:</p>
<ul>
<li>Les unchangeables (Matrices du monde...).</li>
</ul>
<p>Exemple:</p>
<pre>[c]
float4x4 wMatrix : World;</pre>
<ul>
<li>Les modifiables (Couleurs, valeurs, textures, etc...).</li>
</ul>
<p>Exemple:</p>
<pre>[c]
// Ambient Light
float3 gAmbiColor
<
string UIName = "Ambient Light";
string UIWidget = "Color";
> = {0.07f,0.07f,0.07f};</pre>
<p>Ensuite viennent les Data Structures (deux en fait):</p>
<ul>
<li>Une pour les entrées (appdata), qui permet de savoir ce que nous allons avoir besoin pour faire notre shader. C'est un peut notre point de départ, les informations de la géométrie en brut.</li>
</ul>
<p>Exemple:</p>
<pre>[c]
struct vIN
{
float4 Position : POSITION;
half4 Color : COLOR0;
half2 TexCoord : TEXCOORD0;
};</pre>
<ul>
<li>Une pour les sorties (vertexOutput), qui nous permet de savoir qu'est ce qu'on à besoin "en sortie" du shader... L'idée est de "remplir" cette structure de A à Z.</li>
</ul>
<p>Exemple:</p>
<pre>[c]
struct vOUT
{
float4 Position : POSITION;
half4 Color : COLOR0;
half2 TexCoord : TEXCOORD0;
};</pre>
<p>Deux programmes (std_dp_VS et blinn_PS). Ce sont eux nos shaders:</p>
<ul>
<li>VS pour Vertex Shader qui "compute" la géométrie (position des vertex, uv, etc...). C'est le premier "Program" qui est exécuté. On lui donne la structure d'entrée (appdata) et il renvoie la structure de sortie (vertexOutput) remplie.</li>
</ul>
<p>Exemple:</p>
<pre>[c]
vOUT MainVS(vIN IN)
{
vOUT OUT;
// On remplit notre OUT: position ,uvs
OUT.Position = mul(wvpMatrix, IN.Position);
OUT.TexCoord.xy = IN.TexCoord;
OUT.Color = IN.Color;
return OUT;
}</pre>
<ul>
<li>PS pour Pixel Shader qui "compute" chaque pixel en fonction du vertex. Il renvoie une couleur mais nécessite la structure de sortie (vertexOutput, calculé par le Vertex Shader) en argument pour pouvoir justement, calculer cette couleur.</li>
</ul>
<p>Exemple:</p>
<pre>[c]
float4 MainPS(vOUT IN)
{
half4 diffuse = tex2D(colorSampler, IN.TexCoord.xy).rgba; //Notre diffuse utilise la texture
return float4(diffuse.rgb, 1.0);
}</pre>
<p>Les exemples que j'ai donnés sont volontairement plus simples que le CgFX de Nvidia. Mais vous pouvez aisément retrouver leur équivalent. Toutefois, n'essayez pas de tout comprendre, c'est des maths purs, notre but est de savoir comment ça fonctionne, pas de savoir comment calculer du SSS en temps réel. Personnellement, quand j'ai un CgFX à faire, j'isole des morceaux de code bout à bout (lambert, color, reflect, etc...) pour rester le plus simple possible. :sourit:</p>
<p>Et on finit par la dernière "chose": Les program "technique". Un program technique permet, comme son nom l'indique, d'utiliser plusieurs techniques pour calculer son shader. Vous pouvez ensuite demander à Maya (ou votre logiciel) d'utiliser une de ses technique. Ce shader ayant qu'une seul technique (Main) Maya n'en propose qu'une seule:</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billets/cgfx_intro/cgfx_intro_022.png" alt="cgfx_intro_022.png" style="display:table; margin:0 auto;" title="cgfx_intro_022.png, avr. 2010" /></p>
<p>Mais rien n'empêche d'en faire d'autres:</p>
<ul>
<li>Surface shader</li>
<li>Illumination</li>
<li>Illum+Textures</li>
<li>Illum+Textures+Bump</li>
<li>etc...</li>
</ul>
<p>C'est, je crois, une des spécificités du langage CgFX qui le rend particulièrement modulable.</p>
<p>Mais avançons un peu. Chaque technique peut avoir plusieurs "passes" (un peut comme le compositing). Un exemple d'utilisation des "pass" dans les shaders peut être pour les calculs de la relfection/refraction de l'eau dans les jeux vidéos: Une première passe calcule tout, sans l'eau. Une seconde copie le frambuffer, applique des déformations et le tout est superposé.</p>
<p>Dans notre cas, nous n'utilisons qu'une seule pass.</p>
<p>S'en suit plusieurs choses (qui sont les "options" de rendu). Par exemple, "CullFaceEnable = false;" active le backface culling pour le rendu de ce shader. Il est très intéressant de pouvoir contrôler ces paramètres mais nous n'allons pas nous y attarder (Un shader CgFX peut fonctionner sans).</p>
<p>Les choses indispensables sont cependant les deux "Programs":</p>
<ul>
<li>VertexProgram: Indique ou est notre Vertex Shader. "compile vp40" indique qu'il faut utiliser le profile de compilation vp40 (pour ceux que ça interesse: <a href="http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter10.html" hreflang="en">Quelques explications ici</a>) et le dernier, c'est la fonction à compiler...</li>
<li>FragmentProgram: Tout pareille ici mais pour le Pixel Shader.</li>
</ul>
<p>Ouf! Nous avons fait le tour et allons être capable de commencer à concevoir notre propre shader CgFX!</p>
<p>Prenez le temps de bien saisir tout ça, la suite dans <a href="https://www.fevrierdorian.com/blog/post/2010/05/27/CgFX-Des-shaders-temps-reel-dans-le-viewport-Maya-Part-2">le prochain billet</a>. :laClasse:</p>
<p>A bientôt!</p>
<p>Dorian</p>
<center>:marioCours:</center>
Un max de textures dans le viewport Maya: La Solution!urn:md5:54865e3606837979c0c49f6830aa609b2009-01-18T18:24:00+01:002013-07-26T22:43:40+02:00NarannInfographie 3D - Boulot3dcompressionddsDirectDraw Surfacefrmapmayanconvertnvdxtnvidiaphotoshops3texturexnview<p><a href="http://img262.imageshack.us/img262/9154/2281134222bd559a34e61dw7.jpg"><img src="http://img262.imageshack.us/img262/9154/2281134222bd559a34e61dw7.th.jpg" alt="" style="float:left; margin: 0 1em 1em 0;" /></a>Il arrive sur certains projets que les animateurs ou le réalisateur veuillent voir les textures dans le viewport Maya. Le réflexe est d'appuyer sur la touche "6" du pavé numérique pour les afficher. Ce genre de manipulation est souvent imprévisible dans la mesure oû les textures peuvent être de très grandes tailles (ce qui prend du temps à mettre dans la ram, sans garantie de succès) et faire minablement planter Maya. Ne reste alors qu'une seule alternative:</p>
<ul>
<li>Pleurer</li>
</ul> <p>Nan je déconne! :D Il existe une solution alternative et intéressante : les textures <a href="http://en.wikipedia.org/wiki/DirectDraw_Surface">DirectDraw Surface</a> (ou DDS). Sans rentrer dans les détails, je vous explique déjà comment Maya fait quand on lui donne, par exemple, un BMP (on rit pas, je prends un cas simple).</p>
<h5>Forcément, si tu prends un BMP, c'est lourd!</h5>
<p>Héhé... Sachez que, que ce soit un JPG, un TGA, un BMP, Maya ouvre la texture, la décompresse, la lit et place tous les pixels dans la mémoire de la carte graphique pour l'afficher. C'est énorme et très lourd à supporter pour la-dite carte qui dans un logiciel de 3D fonctionne très différemment que dans un jeux vidéo où le calcul des tailles des textures est millimétré. L'astuce que je vous propose consiste à utiliser un format de fichier texture que la carte graphique connait... le format DDS !</p>
<h5>Dintendo DS!</h5>
<p>Le format DDS, c'est quoi ? Pour faire simple disons que c'est un peu le JPG de la carte graphique. C'est la société <a href="http://en.wikipedia.org/wiki/S3_Graphics">S3 Graphics</a> qui a développé les premières cartes supportant la compression-décompression des textures en hardware (la <a href="http://en.wikipedia.org/wiki/Savage_3D">Savage 3D</a>). Cette technologie fut ensuite implémentée dans Directx (6.0) et se propagea très rapidement (les possibilités offertes pour l'époque étaient révolutionnaire pour le jeux vidéo). La compression est destructive (on s'en fout pour un viewport vous me direz), mais l'image est stockée compressée dans la mémoire et décompressée "à la volée". Il y a plusieurs façons de créer une image dds à partir d'un autre format. La plus simple (mais vous allez voir qu'on est limité par cette simplicité) étant selon moi d'utiliser <a href="http://pierre.g.pagesperso-orange.fr/xnview/frxnview.html">XnView</a> : On ouvre, "Outils/Convertir" puis DDS (Il ne génère cependant pas les <a href="http://fr.wikipedia.org/wiki/MIP_mapping">mipmap</a>). J'ajouterai une dernière chose, c'est que ce que XnView fait, <a href="http://pierre.g.pagesperso-orange.fr/xnview/fr_nconvert.html">nconvert</a> le fait aussi :D . Il est donc possible de convertir ses images en ligne de commande (pratique en production).</p>
<p>Voici la ligne de commande BAT:</p>
<pre>
nconvert.exe -out dds -o "monFichier.dds" "monFichier.bmp"
</pre>
<p>Simpliste non? Et bien en fait pas tout à fait ! Il faut savoir une chose quand on fait ce genre de manipulation, c'est que les images doivent avoir des tailles puissance de 2 (512x512, 1024x256 est possible aussi). En jeux vidéo, cette contrainte est primordiale et est donc prise en compte dès le début du projet. En précal', les softs gérant assez bien ce genre de problèmes, on se fout un peu de savoir si les textures sont carrées et (ou) puissance de quoi que ce soit. Il faut donc être rigoureux là-dessus. Si vous ne le faîtes pas, Nconvert va prendre automatiquement la première puissance de 2 (128, 256, 512 etc...) supérieure à la résolution de l'image et remplir le reste de noir. Ce qui rend la position de l'image par rapport à ses uvs faussée. La technique consiste donc à déformer l'image (ça peut sembler paradoxal mais quand on y réfléchit et qu'on teste un peu, c'est logique) en la resizant manuellement dans la taille du "bloc multiple" le plus proche. Personnellement et dans un souci de simplifier le tout, je mets toutes les images en 1024 par 1024 qui est un bon compromis (Cela dit, si vous avez le luxe de pouvoir resizer les maps au cas par cas ne vous gênez pas (C'est vrai que c'est dommage de resizer une map 1310x100 en 1024x1024, c'est vous qui voyez, faut pas se brosser non plus, c'est de la préviz). Voila donc une ligne de BAT possible:</p>
<pre>
nconvert.exe -rflag orient -resize 1024 1024 -rtype lanczos -out dds -o "monFichier.dds" "monFichier.bmp"
</pre>
<p><a href="https://www.fevrierdorian.com/blog/public/billet_dds/image01.jpg"><img src="https://www.fevrierdorian.com/blog/public/billet_dds/.image01_m.jpg" alt="image01.jpg" style="display:block; margin:0 auto;" title="image01.jpg, janv. 2009" height="448" width="448" /></a>
Bon, vous connaissez maintenant les grandes lignes de la manipulation.</p>
<h5>Pas d'alpha, pas de chocolat</h5>
<p>Si vous avez testé avec une image contenant un canal alpha, vous aurez peut-être remarqué que Maya l'interprète différemment (dans mon cas, l'alpha de mon image est censé être son inverse).
<a href="https://www.fevrierdorian.com/blog/public/billet_dds/image02.jpg"><img src="https://www.fevrierdorian.com/blog/public/billet_dds/.image02_m.jpg" alt="image02.jpg" style="display:block; margin:0 auto;" title="image02.jpg, janv. 2009" height="295" width="448" /></a>
L'alpha semble être interprété sur les bords. Je ne sais pas si le problème vient de Maya ou XnView mais il est bien présent. Il y a cependant plusieurs façons de le contourner.</p>
<h5>Nvidia Pawa</h5>
<p><a href="https://www.fevrierdorian.com/blog/public/logos/nvidia_logo_1_.jpg"><img src="https://www.fevrierdorian.com/blog/public/logos/.nvidia_logo_1__s.jpg" alt="logo nvidia" style="float:left; margin: 0 1em 1em 0;" title="logo nvidia, janv. 2009" height="186" width="240" /></a>
Heureusement qu'ils sont là ceux là. En effet, <a href="http://fr.wikipedia.org/wiki/Nvidia">Nvidia</a> propose pas mal d'outils destinés aux développeurs. Ceux qui nous intéressent sont les <a href="http://developer.nvidia.com/object/nv_texture_tools.html">textures tools</a> et plus précisément les <a href="http://developer.nvidia.com/object/dds_utilities_legacy.html">DDS Utilities</a>. Téléchargez les, installez les et allez récupérer le fichier "nvDXT.exe" qui est un convertisseur en ligne de commande (il est placé dans le dossier d'installation). Ce programme à bon nombre d'options que je ne vous expliquerai pas ici (je me contente de laisser les paramètres par défaut), je préfère rester concis (vous pouvez toutefois, si le cœur vous en dit, lire le PDF inclut).</p>
<p>Grosso modo, la ligne de commande est la même que pour nconvert:</p>
<pre>
nvdxt.exe -file maMap.tga -output maMap.dds
</pre>
<p><a href="https://www.fevrierdorian.com/blog/public/billet_dds/image03.jpg"><img src="https://www.fevrierdorian.com/blog/public/billet_dds/.image03_m.jpg" alt="image03.jpg" style="display:block; margin:0 auto;" title="image03.jpg, janv. 2009" height="448" width="448" /></a></p>
<p>Sympa n'est-ce pas? ;)</p>
<p>Je viens aussi (en direct live!) de me rendre compte que les images ayant des tailles qui ne sont pas des puissances de 2 passent très bien ! (Un petit warning mais la conversion se fait)</p>
<p><img src="https://www.fevrierdorian.com/blog/public/billet_dds/image04.gif" alt="image04.gif" style="display:block; margin:0 auto;" title="image04.gif, janv. 2009" height="69" width="352" />
<a href="https://www.fevrierdorian.com/blog/public/billet_dds/image05.jpg"><img src="https://www.fevrierdorian.com/blog/public/billet_dds/.image05_m.jpg" alt="image05.jpg" style="display:block; margin:0 auto;" title="image05.jpg, janv. 2009" height="338" width="448" /></a></p>
<p>Bon, je suis pas sûr que ce soit très propre tout ça, je vous donne aussi la commande qui resize l'image en 1024 par 1024:</p>
<pre>
nvdxt.exe -prescale 1024 1024 -RescaleKaiser -file maMap.tga -output maMap.dds
</pre>
<p>Encore une fois, pour une explication des options, lisez le PDF. J'ai aussi l'impression que l'option -prescale ne fonctionne pas sur des images de grandes tailles (8192 par 8192 par exemple).</p>
<h5>Houai, mais n'empêche que ça pue tes lignes de commande toutes noires!</h5>
<p>Ne vous inquiétez pas! Nvidia a pensé aux <del>attardés</del> personnes n'étant pas à l'aise avec les applications en ligne de commande (Je rigolais hein? Je me sers beaucoup de l'outil qui va suivre car il est plus pratique pour visualiser ce qui se passe dans l'image). Ainsi, ils ont sorti un <a href="http://developer.nvidia.com/object/photoshop_dds_plugins.html">plug-ins Photoshop</a> qui permet également de créer des normal maps à partir de maps de bump (en niveau de gris).</p>
<p><a href="http://developer.nvidia.com/object/photoshop_dds_plugins.html"><img src="http://developer.nvidia.com/docs/IO/20926/TextureCompression.jpg" alt="" style="display:block; margin:0 auto;" /></a></p>
<p>Une fois de plus, je ne vais pas m'étaler (l'objectif étant de sortir des dds, pas de tout vous expliquer, la documentation Nvidia est d'ailleurs très bien faite et je vous invite à la lire si le sujet vous intéresse).</p>
<p>J'espère que ce billet vous aura servi ou vous servira à l'avenir. N'hésitez pas à tester chez vous et à laisser un commentaire si vous avez rencontré des problèmes, si vous pensez que je suis trop vague dans mes explications ou que vous avez la conviction que j'ai écris une énormité.</p>
<p>Pour ceux qui ont déjà utilisé les dds en production, je serai également intéressé de connaitre les limites de ce format ou les contraintes qu'il peut générer.</p>
<p>A bientôt!</p>
<p>Dorian</p>
<h5>MAJ 2011 - 09 - 11 <a name="maj_20110911"></a></h5>
<p>Bon, ça fait un moment que ce billet est écrit mais je fait une MAJ car j'ai pas mal potassé le sujet depuis et j'ai fait deux vidéos.</p>
<p>La première (septembre 2010) présente Maya affichant 4 maps dds de 8k. Mais pour être honnête, je soupçonne que ce n'était la bonne solution car c'est Maya qui envoi les maps dans le GPU:</p>
<iframe width="580" height="356" src="http://www.youtube.com/embed/aVghteicCGM?hd=1" frameborder="0" allowfullscreen></iframe>
<p>Après <a href="http://area.autodesk.com/forum/autodesk-maya/autodesk-maya-2012/cgfx-and-dds-textures-in-gpu-memory/">m'être acharné</a> à trouver de l'aide sur Area, j'ai finalement obtenu une réponse.</p>
<p>Mais il fallait que je test pour être sur. C'est donc chose faite: Pour profiter correctement du format dds, il faut utiliser un shader cgfx. Dans l'exemple qui suite, Maya peut afficher, sans broncher, 9 maps dds de 8k.</p>
<iframe src="http://player.vimeo.com/video/28788662" width="579" height="315" frameborder="0" webkitAllowFullScreen allowFullScreen></iframe>
<p>Et encore, là j’utilisai une compression DXT5 (qui prends le double de place que la DXT1). Donc à priori (il faut que je retest), je dois pouvoir afficher 18 maps dds de 8k dans le viewport Maya :baffed: .</p>
<p>La grande classe! :laClasse:</p>