Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3175 connectés 

  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  [XNA, HLSL][Résolu] Paramètres shader génériques

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[XNA, HLSL][Résolu] Paramètres shader génériques

n°1942589
Stnaire
Posté le 19-11-2009 à 22:42:27  profilanswer
 

Bonjour,
 
Je me retrouve une nouvelle fois devant un problème que je n'arrive pas a résoudre proprement.
Dans la réalisation de mon petit moteur 3D j'aimerai gérer une quantité n de matériaux différents.
 
Chaque matériau doit être facilement applicable à un modèle et décrit à l'aide d'un fichier .xml et d'un fichier .fx.
 
Le soucis est que dans cette optique, je ne connais ni le type, ni le nombre de variables qui seront à transmettre à la carte graphique, hormis les classiques matrices monde, vue, projection et les paramètres d'éclairage.
 
Par exemple, dans le cas d'un shader d'eau, j'ai un bon nombre de variable à passer :
 
- 2 textures : les maps de reflection et refraction.
- Plusieurs vecteurs : direction du vent, hauteur des vagues & co.
- des floats : comme par exemple le temps écoulé depuis la dernière frame.
 
Tout ces paramètres sont simple à passer en dur, mais j'aimerai ne pas m'amuser a faire une classe par matériau, l'idée de les ajouter via l'éditeur, au clic.
 
Donc au risque de me répéter, il faudrait que tout ces paramètres soit entièrement décrit dans un fichier de matériaux (un .xml dans mon cas).
 
Voici la ligne permettant d'ajouter un paramètre de façon classique (ici la couleur de l'eau) :

Code :
  1. this.effect.Parameters["xWaterColor"].SetValue(this.waterColor);


 
Le soucis est que SetValue() n'aime pas du tout les types génériques, elle possède une surcharge pour chaque type supporté.
 
J'ai donc pensé à une solution que je trouve TRÈS moche que voici :

Code :
  1. private SerializableDictionary<string, float> floatList     = new SerializableDictionary<string, float>();
  2. private SerializableDictionary<string, int> intList         = new SerializableDictionary<string, int>();
  3. private SerializableDictionary<string, Vector2> vector2List = new SerializableDictionary<string, Vector2>();
  4. [...]


 
Pour chaque type de paramètres supporté, j'ai un dictionnaire décrit dans le XML.
La clef du dictionnaire correspond au nom de la variable dans code HLSL, et la valeur, la valeur à passer.
 
D'une c'est moche, et absolument pas souple, ici pas de support de variables changeant au runtime (comme par exemple le temps), ce ne sont que des valeurs statiques et décrites de façon très lourde.
 
Voila j'espère ne pas avoir faire trop long, si l'un de vous à une solution plus souple et rapide je lui en serai fortement reconnaissant !
 
Merci :)


Message édité par Stnaire le 21-11-2009 à 00:28:19
mood
Publicité
Posté le 19-11-2009 à 22:42:27  profilanswer
 

n°1942623
Stnaire
Posté le 20-11-2009 à 02:10:56  profilanswer
 

Alors, salut et merci pour ta réponse.
 
Ce que je cherche a faire, c'est une implémentation propre.
Effectivement mon fichier XML contiendra de toute façon, une pair clef - valeur agrémentée d'un type.
 
Exemple :
 

Code :
  1. <Item>
  2.    <Key>WaterColor</key>
  3.    <Value>
  4.       <Vector4>
  5.          <X>.2f</X>
  6.          <Y>.1f</Y>
  7.          <Z>.6f</Z>
  8.          <W>1</W>
  9.       </Vector4>
  10.    </Value>
  11. </Item>


 
J'ai donc bien une pair clef - valeur.
La clef est "WaterColor" qui correspond au nom de la variable HLSL.
La valeur est contenu dans un Vector4.
 
Le problème c'est que pour avoir ce type de structure dans le XML il faut que j'ai le type de code que j'ai posté dans mon 1er message pour le recevoir, il faut bien que j'ai en dur dans mon code un  

Code :
  1. Dictionary<string, Vector4> vector4List;


 
 
Je suis oblige d'avoir ca pour chacun des types et je trouve simplement ca moche.
L'ideal serait un truc du genre :
 

Code :
  1. Dictionary<string, object> paramsList;


 
Le probleme c'est que je ne peux pas passer a SetValue() directement un type object, il faut le caster.
Et pour le caster je dois tester le type..
 

Code :
  1. if (paramsList.ElementAt(i).Value is Vector4)
  2.    this.effect.Parameters[paramsList.ElementAt(i).Key].SetValue((Vector4)paramsList.ElementAt(i).Value);


 
Je trouve ca encore plus moche que parcourir chacun des dictionnaires de type.
 
Voila, donc le probleme n'est pas vraiment "Comment le faire fonctionner", mais comment le rendre réellement générique, car pour moi tout ca reste encore plus ou moins en dur.
 

n°1942919
Stnaire
Posté le 20-11-2009 à 18:35:59  profilanswer
 


 
C'est un type Effect, maintenant je connais que cette façon d'assigner un paramètre HLSL, si il y a un moyen plus générique je suis curieux de le connaitre.
 
 
 
 
C'était bien sur pour l'exemple, j'ai codé ca sur le forum pendant la rédaction du message, l'idée ici était de présenter le problème pas d'optimiser :)
 
 
 
Il est défini juste au dessus dans mon précédent message :

Code :
  1. Dictionary<string, object> paramsList;


 
 
 
Bah je sais pas quoi te dire..  
 
Je vais avoir en entrée un XML chargé de décrire un matériau, ce matériau utilisera un fichier .fx qui demandera des variables à assigner dans le code XNA.
Le but était d'éviter de faire 50 000 dictionnaire comme je l'ai présenté dans mon 1er message, et d'éviter de faire un switch avec des "is" de 100 lignes pour tester chaque type.
 
Maintenant si c'est trop complexe ca en devient inutile, simplement si une solution simple existe j'aurai aimé la connaitre.

n°1942966
Stnaire
Posté le 20-11-2009 à 21:37:16  profilanswer
 

Hum, le XML je le déserialise qu'on soit bien d'accord, j'aurais peut-être du etre plus clair la dessus dès le début.
 
Donc vu que je le déserialise je suis obligé d'avoir la représentation de la structure du XML en code C# pour reconstruire un objet.
 
D'ou mes listes pour chaque type.
 
Un exemple du genre de XML que j'utilise :
 

Code :
  1. <?xml version="1.0"?>
  2. <Dictionary>
  3.   <Item>
  4.     <Key>
  5.       <string>Water</string>
  6.     </Key>
  7.     <Value>
  8.       <Material xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  9.         <AsReflection>false</AsReflection>
  10.         <AsRefraction>false</AsRefraction>
  11.         <FloatList>
  12.           <Item>
  13.             <Key>
  14.               <string>Water heights</string>
  15.             </Key>
  16.             <Value>
  17.               <float>12.24</float>
  18.             </Value>
  19.           </Item>
  20.           <Item>
  21.             <Key>
  22.               <string>Water speed</string>
  23.             </Key>
  24.             <Value>
  25.               <float>22.24</float>
  26.             </Value>
  27.           </Item>
  28.           <Item>
  29.             <Key>
  30.               <string>Water movement</string>
  31.             </Key>
  32.             <Value>
  33.               <float>112.24</float>
  34.             </Value>
  35.           </Item>
  36.         </FloatList>
  37.         <Vector2List>
  38.           <Item>
  39.             <Key>
  40.               <string>TexCoord</string>
  41.             </Key>
  42.             <Value>
  43.               <Vector2>
  44.                 <X>10</X>
  45.                 <Y>102.2</Y>
  46.               </Vector2>
  47.             </Value>
  48.           </Item>
  49.         </Vector2List>     
  50.       </Material>
  51.     </Value>
  52.   </Item>
  53. </Dictionary>


 
Chaque <Item> du 1er <Dictionary> décrit un matériau.
Ensuite à l'intérieur les variables sont classées par type, un dico par type.
La classe material est donc de la forme suivante :
 

Code :
  1. [Serializable]
  2. public class Material : IMaterial
  3. {
  4.         #region Fields
  5.         [NonSerialized, XmlIgnore]
  6.         private Effect effect;
  7.         private bool asReflection;
  8.         private bool asRefraction;
  9.         private SerializableDictionary<string, string> textureList      = new SerializableDictionary<string, string>();
  10.         private SerializableDictionary<string, float> floatList         = new SerializableDictionary<string, float>();
  11.         private SerializableDictionary<string, int> intList             = new SerializableDictionary<string, int>();
  12.         private SerializableDictionary<string, Vector2> vector2List     = new SerializableDictionary<string, Vector2>();
  13.         private SerializableDictionary<string, Vector3> vector3List     = new SerializableDictionary<string, Vector3>();
  14.         private SerializableDictionary<string, Vector4> vector4List     = new SerializableDictionary<string, Vector4>();
  15.         private SerializableDictionary<string, Matrix> matrixList       = new SerializableDictionary<string, Matrix>();
  16.         #endregion
  17.    [...]
  18. }


 
C'est un extrait des champs qu'utilise chaque matériaux.
A savoir que si 20 objets utilise le même matériau, ils utilisent la même instance, sinon bonjour la mémoire.


Message édité par Stnaire le 20-11-2009 à 21:41:00
n°1942980
Stnaire
Posté le 20-11-2009 à 23:32:07  profilanswer
 


 
Non ces listes sont uniquement décrites dans la classe Material, pas besoin d'héritage ici.
 
 
 
Ce n'est vraiment un problème comme je pensais l'avoir expliqué, c'est simplement que j'étais "choqué" d'avoir à créer toutes ces listes et je pensais passer a coté d'une fonctionnalité du C# en étant obligé de faire comme ca.
 
Maintenant si aucune autre manière n'existe pas de problème je garde mes dicos, ca marchera ;)

n°1942985
Stnaire
Posté le 21-11-2009 à 00:25:12  profilanswer
 


 
^^, je vais en rester là dans ce cas.
 
Merci beaucoup pour ton aide et pour le temps passé à me répondre :)

n°1943025
Stnaire
Posté le 21-11-2009 à 11:36:33  profilanswer
 


 
Oui et il faut le faire pour chacun des dico ^^, mais bon ca a la mérite de fonctionner c'est déjà bien :)

n°1959020
PERECil
Posté le 20-01-2010 à 13:32:21  profilanswer
 

Dans XNA 3.0, il y a un Content Importer spécifique qui fait pile poil ce que tu cherches. Voir http://www.gulix.fr/blog/spip.php?article142


Message édité par PERECil le 20-01-2010 à 13:36:24

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  [XNA, HLSL][Résolu] Paramètres shader génériques

 

Sujets relatifs
[Résolu][PHP] lecture d'objet XML en php[RESOLU] >>> Redirection vers une URL selon le mot de passe !
[Self-Résolu] Port Série (COM) et WriteFile()[GLSL - fragment shader] indéxer une texture
(résolu) Positionnement de footer[résolu][PHP/XML] lecture de fichier XML en PHP
[RESOLU] [AS2] Chemin[C] [resolu] lecture matrice alloué dynamiquement
Execution javascript et condition unique [resolu][Ruby] exécution d'une commande 'echo' avec ruby [résolu]
Plus de sujets relatifs à : [XNA, HLSL][Résolu] Paramètres shader génériques


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR