[GLSL-OSG] probleme avec les shaders GLSL sous osg

probleme avec les shaders GLSL sous osg [GLSL-OSG] - C++ - Programmation

Marsh Posté le 29-05-2007 à 12:11:08    

Bonjour!  
 
je suis entrain de réaliser un application permetant de charger un model 3D et de le visualiser dans un viewer a l'aide de QT et d'osg.
Et certain model on des normal inverser qui sont donc rendu noir par le rendu openGL de base.
 
Donc Premiere question:
- je voulais passer par les shader GLSL pour calculer moi meme l'éclairage et paré ce problème cela est t'il une bonne idée ? ou puis je faire plus simple avec les parametre de GL_LIGHT et les GL_FRONT and BACK et dans ce cas que faut t'il faire
 
Deuxieme question :
-Je me suis déja pas mal pencher sur les shader GLSL avant de venir vous embeter, mais j'ai aussi quelque probleme qui rende rallentise enormement mon programme.
-J'ai donc définie mon vertex shader  

Code :
  1. varying vec3 normal, eyeVec;
  2. void main(void)
  3. {
  4. normal = gl_NormalMatrix * gl_Normal;
  5. vec3 vVertex = vec3 ( gl_ModelViewMatrix*gl_Vertex);
  6. eyeVec = -vVertex;
  7.  gl_Position = ftransform();
  8. }

 
 
ainsi que mon fragment shader

Code :
  1. varying vec3 normal , eyeVec;
  2. void main()
  3. {
  4. vec4 diffuse = vec4 (0.0);
  5. vec4 specular = vec4 (0.0);
  6. float att = 0.0;
  7. vec3 norm = normalize ( normal );
  8. vec3  light = vec3( gl_LightSource[0].position.xyz + eyeVec );
  9.   light = normalize(light);
  10. vec4 ambient = gl_FrontMaterial.ambient ;// * gl_LightSource[0].ambient;
  11. ambient = normalize ( ambient );
  12. float NdotL = abs(dot ( norm , light ));
  13. diffuse = (gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse * NdotL);// + gl_FrontMaterial.emission;
  14. diffuse = (diffuse + gl_FrontMaterial.emission)/2.0;
  15. vec3 eye = normalize (eyeVec);
  16. vec3 refl = reflect ( -light, norm);
  17. float spec = max( dot ( refl , eye ), 0.0 );
  18. spec = pow( spec , gl_FrontMaterial.shininess );
  19. specular = gl_FrontMaterial.specular * gl_LightSource[0].specular * spec;
  20. float dist = length ( light );
  21. att = 1.0 / (gl_LightSource[0].constantAttenuation + (gl_LightSource[0].linearAttenuation*dist) + (gl_LightSource[0].quadraticAttenuation*dist*dist) );
  22. gl_FragColor = ambient + ( diffuse + specular) * att;
  23. gl_FragColor[3] = gl_FragColor[3]/2.0;
  24. //gl_FragColor = diffuse ;
  25. }


 
si j'applique mon shader a mon model sur le node racine je me retrouve avec le meme materiau sur tout mon object
ce qui fait que pour parer a ce probleme je fait mon appel de shader sur tout les node avec un materiau.
Mais je pense que normalement je ne devrai pas faire ca.  
Et evidament cette methode reduit considérablement ma vitesse d'execution.
 
je l'appel donc dans mon code (pour le moment) de cette facon

Code :
  1. bool MyOptimizer::ShaderVisitor::loadShaderSource(osg::Shader* obj, const std::string& fileName )
  2. {
  3. std::string fqFileName = osgDB::findDataFile(fileName);
  4.    if( fqFileName.length() == 0 )
  5.    {
  6.   // std::count << "File \"" << fileName << "\" not found." << std::endl;
  7.       return false;
  8.    }
  9.    bool success = obj->loadShaderSourceFromFile( fqFileName.c_str());
  10.    if ( !success  )
  11.    {
  12.       //std::count << "Couldn't load file: " << fileName << std::endl;
  13.       return false;
  14.    }
  15.    else
  16.    {
  17.       return true;
  18.    }
  19. }
  20. void MyOptimizer::ShaderVisitor::applyShader(osg::StateSet* pstate)
  21. {
  22. osg::StateAttribute * pstatsAtt;
  23. osg::StateAttribute* stateAtt;
  24. osg::Material* poMat;
  25. bool ok = false;
  26. {
  27.  pstatsAtt = pstate->getAttribute(osg::StateAttribute::MATERIAL);
  28.  if (pstatsAtt ) // si il y a un materiau
  29.  {
  30.   stateAtt = pstate->getAttribute(osg::StateAttribute::PROGRAM);
  31.   if ( stateAtt )// si il y a déja un program
  32.    m_pEclairageProgram = (osg::Program*) stateAtt;
  33.   else
  34.    m_pEclairageProgram = new osg::Program();
  35.   m_pEclairageProgram->setDataVariance(osg::Object::DYNAMIC);
  36.   m_pEclairageProgram->setName( "eclairage" );
  37.   m_pEclairageVertObj = new osg::Shader( osg::Shader::VERTEX );
  38.   m_pEclairageFragObj = new osg::Shader( osg::Shader::FRAGMENT );
  39.   ok = loadShaderSource( m_pEclairageVertObj, QFileInfo(qApp->argv()[0]).dir().filePath("data/shaders/MyVertexShader.vert" ).latin1())
  40.  && loadShaderSource( m_pEclairageFragObj, QFileInfo(qApp->argv()[0]).dir().filePath("data/shaders/MyFragmentShader.frag" ).latin1()) ;
  41.  }
  42. }
  43. if(ok)
  44. {
  45.   m_pEclairageProgram->addShader( m_pEclairageFragObj );
  46.   m_pEclairageProgram->addShader( m_pEclairageVertObj );
  47.   pstate->setAttributeAndModes(m_pEclairageProgram, osg::StateAttribute::ON); 
  48. }
  49. }


 
Merci d'avance

Reply

Marsh Posté le 29-05-2007 à 12:11:08   

Reply

Marsh Posté le 30-05-2007 à 01:58:31    

Salut,
 

nmantelier a écrit :

Donc Premiere question:
- je voulais passer par les shader GLSL pour calculer moi meme l'éclairage et paré ce problème cela est t'il une bonne idée ? ou puis je faire plus simple avec les parametre de GL_LIGHT et les GL_FRONT and BACK et dans ce cas que faut t'il faire


GLSL ne te sera pas d'une grande aide dans ce cas. Il n'est apellé que pour ce qui est actuellement dessiné, et si le modèle et/ou le noeud est mal préparé tu ne pourras rien faire. Le plus propre est assurément de t'assurer que les modèles ont les bonnes normales... Sinon, tout dépend de l'usage; tu peux fournir un paramètre flipNormal dans ton code de chargement, et inverser les normales à la mano si ce flag est activé. Tu peux peut-être détecter les modèles dont les normales sont inversées par programmation?
Si aucune de ces solutions ne peut convenir, alors il faudra que tu désactives GL_CULL_FACE, au détriment du temps de rendu...
 
Pour ta 2nde question, je ne connais pas osg, donc je m'abstiendrais de partir sur n'importe quelle supposition (en espérant déjà ne pas me planter sur ta première question :D)

Reply

Marsh Posté le 30-05-2007 à 10:47:16    

Citation :

Le plus propre est assurément de t'assurer que les modèles ont les bonnes normales...


 
Oui ca aurai ete le plus simple mais le probleme c que je fait un filer de choix de model pour des utilisateur non experimenter qui peuvent charger nimporte quel model. Donc je ne peu pas controler les model d'entrer.
 
 

Citation :

Sinon, tout dépend de l'usage; tu peux fournir un paramètre flipNormal dans ton code de chargement, et inverser les normales à la mano si ce flag est activé. Tu peux peut-être détecter les modèles dont les normales sont inversées par programmation?


 
Cette methode j'ai deja essayer de retourner les normals ( enfin avec osg et non flipnormal) mais le resultat est le meme.
C'est a dire que je ne peu pas définir une normal comme dans le mauvais sens puisque tout dépend de la position de l'obs ;'(.
ce qui fait que j'ai fait une methode automatique qui test les normals sur tout les intersection entre le vecteur de vue et mon model pour ensuite retourner les normals qui sont orienter dans la mauvaise direction.
Pb depend du point de vue (donc corrige que partielement l'objet) et de plus tres tres long puisque il calcul une intersection par pixel donc sur une fenetre 400 300 (voir plus resize) ca fait un certain nombre de calcul.
 

Citation :

Si aucune de ces solutions ne peut convenir, alors il faudra que tu désactives GL_CULL_FACE, au détriment du temps de rendu...


 
Cette option est deja active (avec posibilite de la désactiver ou non) mais le résultat ne va pas puisque si je désactive le culling je me retrouve avec des faces noires o milieu de certain model du au calcul d'eclairage OpenGL. D'ou mon idée de partir sur les shader pour parer a ce probleme.

Reply

Marsh Posté le 30-05-2007 à 12:50:23    

As-tu un éclairage ambiant ou uniquement des éclairages directionnels? Si le pixel est noir en sortie, il n'est pas éclairé, si? Tu peux peut-être essayer vite fait d'ajouter un spot en direction de la face (enfin, orienté vers la normale de la face).

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed