Shaders : je craque!

Généralités sur la programmation 3D
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Shaders : je craque!

Message par kelebrindae »

:x AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGH !! :x

Je ne comprends rien aux shaders! J'y ai passé une partie du week-end, mais sans grand résultat. Soit il me manque les connaissances de bases, soit je suis un gros boulet. (ou les deux. Probablement les deux.)

J'ai écumé les forums d'Ogre, j'ai étudié les rares codes PB dispo à m'en user la rétine (merci Djes, au passage), rien à faire: je n'arrive pas à faire le lien entre le code du shader et les choses à mettre dans le fichier ".material". C'est frustrant. Je suis frustré.

Voici ma situation:
- Je dispose du shader HLSL suivant, dont le but est d'afficher la scène 3D en anaglyphes:

Code : Tout sélectionner

// Simple 3D shader
// Created 15 April 2009, edited 16 April 2009.

float4x4 wvp   : worldviewproj_matrix;
float4x4 wv    : worldview_matrix;
float4x4 proj  : projection_matrix;

float4 camOffset = {2.0, 0.0, 0.0, 0.0};

float4 leftColour = {0.0, 1.0, 1.0, 1.0};
float4 rightColour = {1.0, 0.0, 0.0, 1.0};

texture baseTexture < string ResourceName = ""; >;

sampler baseSample = sampler_state 
{ texture = <baseTexture>;
  mipFilter = linear;
  magFilter = linear;
  minFilter = linear;
  addressU = wrap;
  addressV = wrap;
};

struct VSInput
{ float4 pos   : position;
  float2 UV    : texcoord0;
};

struct VSOutput
{ float4 pos   : position;
  float2 UV    : texcoord0;
};

struct PSInput
{ float2 UV : texcoord0;
};

struct PSOutput { float4 col : color; };

VSOutput leftVShader(VSInput In, VSOutput Out)
{ // convert to camera coords and shift to left
  float4 vPos = mul(wv, In.pos) - camOffset;
  // convert to screen coords
  Out.pos = mul(proj, vPos);
  Out.UV = In.UV;
  return Out;
}

VSOutput rightVShader(VSInput In, VSOutput Out)
{ // convert to camera coords and shift to right
  float4 vPos = mul(wv, In.pos) + camOffset;
  // convert to screen coords
  Out.pos = mul(proj, vPos);
  Out.UV = In.UV;
  return Out;
}

PSOutput leftPShader(PSInput In, PSOutput Out)
{ Out.col = tex2D(baseSample, In.UV) * leftColour;
  return Out;
}

PSOutput rightPShader(PSInput In, PSOutput Out)
{ Out.col = tex2D(baseSample, In.UV) * rightColour;
  return Out;
}

technique test
{ pass left
  { vertexShader = compile vs_2_0 leftVShader();
    pixelShader  = compile ps_2_0 leftPShader();
    depthBias = 0.0005;
  }

  pass right
  { vertexShader = compile vs_2_0 rightVShader();
    pixelShader  = compile ps_2_0 rightPShader();
    depthBias = 0;
    alphaBlendEnable = true;
    blendOp = add;
    srcBlend = one;
    destBlend = one;
  }
}
-J'essaie d'écrire un fichier ".material" faisant appel à ce shader, mais je n'arrive pas plus loin que ça:

Code : Tout sélectionner

vertex_program left_vs hlsl
{
   source Anaglyph.fx
   entry_point leftVShader
   target vs_2_0
   
}

fragment_program left_ps hlsl
{
   source Anaglyph.fx
   entry_point leftPShader
   target ps_2_0
   
}

vertex_program right_vs hlsl
{
   source Anaglyph.fx
   entry_point rightVShader
   target vs_2_0
   
}

fragment_program right_ps hlsl
{
   source Anaglyph.fx
   entry_point rightPShader
   target ps_2_0
   
}


material teapot
{
  technique
  { 
    pass left
    { 
			vertex_program_ref left_vs
			{
			}
			fragment_program_ref left_ps
			{
			}
			
			texture_unit
			{

			}			
			
    }
    pass right
    { 
			vertex_program_ref right_vs
			{
			}
			fragment_program_ref right_ps
			{
			}
			
			texture_unit
			{

			}			
    }
  }
}
Je vois bien qu'il manque des trucs essentiels, notamment la façon de combiner les deux passes, mais je ne sais pas comment les ajouter.

Et puis, dans le code du shader, il y a du code, soit que je ne comprends pas, soit dont je devine l'utilité mais que je n'arrive pas à exploiter:

- Pourquoi les "worldviewproj_matrix" et autres ne sont-ils pas déclarés en paramètres d'entrée du shader?
- Et pourquoi il n'y pas pas de "main_vp" ou autre entry_point évident?
- Comment pourrais-je référencer ou appeler la technique décrite dans le shader? ça m'éviterait de la re-décrire dans le ".material", non?

Bref: je n'y entrave que dalle. Quelqu'un pourrait-il me donner un coup de pouce? Pitié!

Ps: voici un petit ".zip" qui contient le code, le mesh et tout ce que j'utilise pour tester (Le code PB est de Djes, encore grand merci à lui).
http://keleb.free.fr/pb/anaglyph.zip
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: Shaders : je craque!

Message par G-Rom »

Les shaders sont assez compliqué à comprendre , il faut commencer par la base de tout , c'est à dire arrivé à colorisé un objet avec une couleur donnée , par exemple le rouge. Ensuite il faut maitrisé les .material d'ogre , qui simplifie l'acces au shader et le linkage de tout.

Pour la vision stéréoscopique , le shader par objet n'est pas la bonne solution , le résultat sera foireux , ce qu'il faut c'est utilisé les compositors d'ogre et faire un rendu de la scene complète 2x , mais ce n'est pas possible sous purebasic , les compositors ne sont pas implémenté pour le moment...

Voici quand même un petit cour pour l'utilisation des shaders ( avec glsl car je suis sous linux )

l'exemple démontre comment colorié un mesh :

le .material :
vertex_program BlendVert glsl
{
source Blend.vert
}


fragment_program BlendFrag glsl
{
source Blend.frag
}


material Blend
{
technique
{

pass
{

vertex_program_ref BlendVert
{
}

fragment_program_ref BlendFrag
{
param_named NomDeTextureQueJeVeut int 0
param_named AutreNomDeTextureQueJeVeut int 1
}

texture_unit
{
texture MaTextureA.png 2d
}

texture_unit
{
texture MaTextureB.png 2d
}
}
}
}
Pour "linké" les unité de texture avec le shader , le point clé se trouve ici :
fragment_program_ref RustyFrag
{
param_named NomDeTextureQueJeVeut int 0
param_named AutreNomDeTextureQueJeVeut int 1

}
int 0 & int 1 represente les unité de texture dans la passe courante.
si il y avait une 3° texture on aurais rajouté :
param_named <nom dans le shader> int 3
Ensuite au niveau du shader :

Vertex shader minimal :
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}

Fragment shader :
uniform sampler2D NomDeTextureQueJeVeut;
uniform sampler2D AutreNomDeTextureQueJeVeut;

void main (void)
{

vec4 Texel0 = texture2D( NomDeTextureQueJeVeut , gl_TexCoord[0].st);
vec4 Texel1 = texture2D( AutreNomDeTextureQueJeVeut , gl_TexCoord[0].st);
vec4 Melange = (Texel0 * 0.5)+ (Texel1 * 0.5);

gl_FragColor = Melange;
}
Tu n'a plus qu'a créer un .mesh qui utilise le .material. et le tour et joué.

voici ce qu'il est possible de faire en purebasic avec la version actuelle :
Image

Avec un bon lien pour les .materials :

http://www.ogre3d.org/wiki/index.php/Ma ... transition

Pour le moment Parse3DScript() charge tout les .materials .mesh etc...
mais il n'y a pas de LoadMaterial() qui permettrais de l'appliqué à une entité...
il faut donc que ton .mesh soit créer avec le matérial avec ton logiciel d'exportation.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Shaders : je craque!

Message par djes »

kelebrindae a écrit ::x AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGH !! :x
ARGH aussi :)

kelebrindae a écrit : Je vois bien qu'il manque des trucs essentiels, notamment la façon de combiner les deux passes, mais je ne sais pas comment les ajouter.

Et puis, dans le code du shader, il y a du code, soit que je ne comprends pas, soit dont je devine l'utilité mais que je n'arrive pas à exploiter:

- Pourquoi les "worldviewproj_matrix" et autres ne sont-ils pas déclarés en paramètres d'entrée du shader?
- Et pourquoi il n'y pas pas de "main_vp" ou autre entry_point évident?
- Comment pourrais-je référencer ou appeler la technique décrite dans le shader? ça m'éviterait de la re-décrire dans le ".material", non?

Bref: je n'y entrave que dalle. Quelqu'un pourrait-il me donner un coup de pouce? Pitié!

Ps: voici un petit ".zip" qui contient le code, le mesh et tout ce que j'utilise pour tester (Le code PB est de Djes, encore grand merci à lui).
http://keleb.free.fr/pb/anaglyph.zip
En fait Ogre est très bien pensé, et même si ce n'est pas facile à appréhender, tout cela est très logique. Je ne suis cependant pas un spécialiste, je n'ai pas encore eu le temps de vraiment m'y mettre, mais je vais tâcher de te donner quelques pistes.

D'abord, les passes... Elles sont bien "exécutées" (rendues) séquentiellement, donc, pas de souci, ça marche.
- Pourquoi les "worldviewproj_matrix" et autres ne sont-ils pas déclarés en paramètres d'entrée du shader?
Ce sont des "variables" renseignées automatiquement par Ogre. Inutile de les déclarer, ce sont des "globales".
- Et pourquoi il n'y pas pas de "main_vp" ou autre entry_point évident?
Plein de raisons. D'une part parce que Ogre doit pouvoir gérer plein de techniques différentes (hlsl et autres), d'autre part parce qu'il ne s'agit pas comme en C d'un "main" mais de "programmes", qui peuvent tous êtres contenus dans un seul fichier : s'il n'y en avait qu'un, il ne pourrait y en avoir plusieurs (hum!)... Là tu en fais autant que tu veux, et tu dis à Ogre lequel appeler pour telle technique, dans le langage qui correspond... C'est super souple, du coup c'est un peu confus! Pense plutôt à ça comme des procédures.
- Comment pourrais-je référencer ou appeler la technique décrite dans le shader? ça m'éviterait de la re-décrire dans le ".material", non?
Je ne comprends pas; tu le fais... Tu décris les choses dans le material un peu comme des "declare" en PB, juste pour qu'il sache en fonction de la technique quels paramètres doivent être passés. Les techniques imposent des modes de passages différents.

Maintenant, pour ton code, je dirais qu'il est un peu compliqué pour un premier essai. En fait, j'ai l'impression que l'objet ne correspond pas à l'effet recherché. Les techniques semblent avoir besoin d'une texture, et celui-ci n'en a pas. Le fichier ogre.log n'indique pas d'erreur. Je ferai un petit test demain si j'ai le temps.
tmyke
Messages : 1554
Inscription : lun. 24/juil./2006 6:44
Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E

Re: Shaders : je craque!

Message par tmyke »

Dans ton shader, c'est du HLSL, en entête, il faudrait pour moi écrire plutôt:

Code : Tout sélectionner

float4x4 wvp   : WorldViewProjection;
float4x4 wv    : WorldView;
float4x4 proj  : Projection;

En suite, dans ton script material, moi j'écrirais:

Code : Tout sélectionner

vertex_program left_vs hlsl
{
   source Anaglyph.fx
   entry_point leftVShader
   target vs_2_0

   default_params
   {
      param_named_auto wvp  worldviewproj_matrix
      param_named_auto wv   worldview_matrix
      param_named_auto proj projection_matrix
   }
}
Contrairement a GLSL, le passage des paramètres n'est pas automatique, il faut le
spécifier, sinon, tu n'aura rien à l'écran. A voir si déjà tu as un affichage de ta scene
avec cela, même si en final pour le moment, l'effet souhaité n'ai pas encore au rendez vous.. ;)
Force et sagesse...
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Re: Shaders : je craque!

Message par kelebrindae »

Wow! Merci de vos réponses, les gars; ça va bien m'aider.

@G-rom:
G-Rom a écrit :Les shaders sont assez compliqué à comprendre , il faut commencer par la base de tout , c'est à dire arrivé à colorisé un objet avec une couleur donnée , par exemple le rouge.
Oui, tu as raison; je crois que j'ai essayé de courir avant de savoir marcher. J'étais naïf: je ne pensais pas avoir autant de mal à comprendre, et je ne pensais pas que le simple appel à un shader déjà écrit par quelqu'un d'autre serait si compliqué...
G-Rom a écrit :Pour la vision stéréoscopique , le shader par objet n'est pas la bonne solution [...] ce qu'il faut c'est utiliser les compositors d'ogre
Effectivement, en fouillant dans les forums d'Ogre, j'avais trouvé un compositor qui produisait des anaglyphes. J'ai essayé de l'implémenter, et je me suis retrouve avec un joli "Technique not supported" dans le log d'Ogre. C'est pour cela que je me suis tourné vers le shader.
Sinon, merci pour l'exemple et le lien, je vais étudier ça de plus près. :D

@Djes:
Ma question concernant la technique, c'était celle-ci: dans le code du shader, il est décrit une technique "test" avec une passe "Left" et une passe "Right", cette dernière étant apparemment semi-transparente ("alphaBlendEnable = true"). Nickel.
Ce que je m'attendrais à faire dans le material, c'est un appel à cette technique avec un truc dans le genre "technique_ref", un peu comme on appelle les vertex programs avec des "vertex_program_ref"...
Ferais-je fausse route?

@Tmyke:
Je crois que les vertex_programs "leftVShader" et "rightVShader" ne prennent pas en paramètres d'entrée "worldviewproj_matrix", "worldview_matrix" et "projection_matrix". Quand on regarde le code du shader, on remarque que ces trois valeurs ne sont pas déclarés comme des paramètres d'entrée des procédures, mais plutôt comme des "globales" du shader; c'est un peu ça qui me trouble (d'où ma question initiale: "Pourquoi les "worldviewproj_matrix" et autres ne sont-ils pas déclarés en paramètres d'entrée?").
En fait, si je comprends bien le code, les paramètres sont décrits dans les structures VSinput, VSoutput, PSinput et PSoutput. Par exemple, "leftVShader" et "rightVShader" attendent en entrée une position (celle du vertex, je pense) et une texture. Dois-je leur passer manuellement, ou bien c'est automatique? :?
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Re: Shaders : je craque!

Message par kelebrindae »

Woohoo !

J'ai atteint un début de prémices de succès !

En gros, il y avait plusieurs erreurs:
- Dans le code PB, déjà, la caméra était trop loin de l'objet, ce qui fait que même si le shader avait marché, on aurait rien vu... :lol:
- Dans le Material, Tmyke avait raison: il fallait passer "worldview_matrix" et "projection_matrix" en paramètres. Ce qui provoquait des erreurs lors de mes premiers essais, c'est que je passais aussi "worldviewprojection_matrix". Or, comme cette valeur n'est pas utilisée dans le code du vertex_program, la compil' du shader supprimait tout bonnement le paramètre => erreur "paramètre inconnu". Féroce, l'optimisation des shaders! 8O
- Enfin, dans le shader, les valeurs par défaut pour leftColour, rightColour, cameraOffset sont apparemment ignorées: il faut que je les repasse en paramètres. Comme cela ne provoque pas d'erreur dans le log d'Ogre, j'ai mis un bout de temps à comprendre...

Bon, ce n'est pas parfait, mais je commence à y voir plus clair :D

Voici le code du shader (pratiquement pas de modif', sauf celle indiquée par Tmyke):

Code : Tout sélectionner

// Simple 3D shader
// Created 15 April 2009, edited 16 April 2009.

float4x4 wvp : WorldViewProjection ;
float4x4 wv : WorldView;
float4x4 proj : Projection;

float4 camOffset = {2.0, 0.0, 0.0, 0.0};

float4 leftColour = {0.0, 1.0, 1.0, 1.0};
float4 rightColour = {1.0, 0.0, 0.0, 1.0};

texture baseTexture < string ResourceName = ""; >;

sampler baseSample = sampler_state 
{ texture = <baseTexture>;
  mipFilter = linear;
  magFilter = linear;
  minFilter = linear;
  addressU = wrap;
  addressV = wrap;
};

struct VSInput
{ float4 pos   : position;
  float2 UV    : texcoord0;
};

struct VSOutput
{ float4 pos   : position;
  float2 UV    : texcoord0;
};

struct PSInput
{ float2 UV : texcoord0;
};

struct PSOutput { float4 col : color; };

VSOutput leftVShader(VSInput In, VSOutput Out)
{ // convert to camera coords and shift to left
  //float4 camOffset = {2.0, 0.0, 0.0, 0.0};

  float4 vPos = mul(wv,In.pos ) - camOffset;
  // convert to screen coords
  Out.pos = mul(proj,vPos);
  Out.UV = In.UV;
  return Out;
}

VSOutput rightVShader(VSInput In, VSOutput Out)
{ // convert to camera coords and shift to right
  // float4 camOffset = {2.0, 0.0, 0.0, 0.0};

  float4 vPos = mul(wv,In.pos ) + camOffset;
  // convert to screen coords
  Out.pos = mul(proj,vPos );
  Out.UV = In.UV;
  return Out;
}

PSOutput leftPShader(PSInput In, PSOutput Out)
{  
  Out.col = tex2D(baseSample, In.UV) * leftColour;

  return Out;
}

PSOutput rightPShader(PSInput In, PSOutput Out)
{ 
  Out.col = tex2D(baseSample, In.UV) * rightColour;

  return Out;
}

technique test
{ pass left
  { vertexShader = compile vs_2_0 leftVShader();
    pixelShader  = compile ps_2_0 leftPShader();
    depthBias = 0.0005;
  }

  pass right
  { vertexShader = compile vs_2_0 rightVShader();
    pixelShader  = compile ps_2_0 rightPShader();
    depthBias = 0;
    alphaBlendEnable = true;
    blendOp = add;
    srcBlend = one;
    destBlend = one;
  }
}
Voici le ".material" :

Code : Tout sélectionner

vertex_program left_vs hlsl
{
   source Anaglyph.fx
   entry_point leftVShader
   target vs_2_0
   default_params
   {
      param_named_auto wv worldview_matrix
      param_named_auto proj projection_matrix
      param_named camOffset float4 0.02 0 0 0
   }  
}

fragment_program left_ps hlsl
{
   source Anaglyph.fx
   entry_point leftPShader
   target ps_2_0
   
   default_params
   {
      param_named leftColour float4 0.0 1.0 1.0 1.0
   }  
   
}

vertex_program right_vs hlsl
{
   source Anaglyph.fx
   entry_point rightVShader
   target vs_2_0
   default_params
   {
      param_named_auto wv worldview_matrix
      param_named_auto proj projection_matrix
      param_named camOffset float4 0.02 0 0 0
   }  
   
}

fragment_program right_ps hlsl
{
   source Anaglyph.fx
   entry_point rightPShader
   target ps_2_0
   
   default_params
   {
      param_named rightColour float4 1.0 0.0 0.0 1.0
   }  

}


material cube
{
  technique test
  { 
    pass left
    { 
      // depth_bias 0.0005
      depth_write off
      vertex_program_ref left_vs {}
      fragment_program_ref left_ps {}
      texture_unit
      {
      		texture Ogre-logo.png 2d
      }

    }
  
    pass right
    { 
      // depth_bias 0.0
      depth_write off
      scene_blend add
      vertex_program_ref right_vs {}
      fragment_program_ref right_ps {}
      texture_unit
      {
  				texture Ogre-logo.png 2d
      }
      
    }
  }
}
Et voici le .zip qui permet de tester le tout (avec un mesh "cube", car le mesh utilisé dans l'exemple précédent n'avait pas de coordonnées UV) :
http://keleb.free.fr/pb/anaglyph.zip
Dernière modification par kelebrindae le mar. 09/mars/2010 22:45, modifié 1 fois.
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Shaders : je craque!

Message par djes »

Oui, c'est dans le .material que certains paramètres sont automatiquement renseignés, et c'est à partir de là qu'il faut les passer aux shaders.
C'est cool de voir de nouvelles personnes mettre les mains dans le cambouis 3D :)

Par contre il y a une erreur dans mon code, il faut faire une boucle while windowevent() : wend pour traiter tous les messages.
tmyke
Messages : 1554
Inscription : lun. 24/juil./2006 6:44
Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E

Re: Shaders : je craque!

Message par tmyke »

kelebrindae a écrit :Woohoo !

J'ai atteint un début de prémices de succès !
Cool, tu progresse et c'est ça le plus important. C'est bien sympa ;)

Oui, les shaders ont une syntaxe rigide, pas toujours simple, c'est d'ailleurs un secteur de prog bien spécifique désormais, avec des mecs dans les
équipes de dev qui font que ça.
Mais en y allant doucement, on y arrive et on peut faire des truc vraiment super avec :mrgreen:
Force et sagesse...
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Re: Shaders : je craque!

Message par kelebrindae »

@Djes:
L'erreur n'est pas de toi: j'avais viré l'include "screenRequester" au début du code, et le "while windowEvent" était dedans... :wink:

J'ai mis à jour le code PB dans le zip pour corriger ça et présenter les résultats de façon plus évidente:
http://keleb.free.fr/pb/anaglyph.zip

Dobro, est-ce que l'effet te paraît correct ?
Image
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Avatar de l’utilisateur
venom
Messages : 3136
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: Shaders : je craque!

Message par venom »

hey ! le rendu est plutôt sympa bravo kelebrindae :wink:






@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Re: Shaders : je craque!

Message par kelebrindae »

Merci!
Je l'avais fait un peu évoluer sur les conseils de Dobro:
http://www.purebasic.fr/french/viewtopi ... 13&t=10378

Ce n'est encore pas parfait, loin de là, mais ça marche mieux...
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Répondre