IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

[GLSL] Position et direction d'une lumière


Sujet :

OpenGL

  1. #1
    Membre très actif
    Profil pro
    Dev
    Inscrit en
    Mai 2009
    Messages
    257
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Mai 2009
    Messages : 257
    Par défaut [GLSL] Position et direction d'une lumière
    Bonsoir, je viens récemment de mettre en oeuvre le chargement de shaders dans une application OpenGL

    Et bien sûr j'ai voulu tester immédiatement avec une émulation du pipeline fixe : l'éclairage Phong

    Dans le code de l'application j'opère tous les calculs de matrices moi-même à l'aide de la librairie de maths GLM, donc aucun appel à la pile de matrices d'OpenGL, je gère le lookat et les transformations tout seul

    Puis je passe les matrices de projection, modelview, normalmatrix ainsi que la position d'une lumière (LightPos) au shader phong via des variables uniform

    Résultat sur un cube, cela me semble correct, à un détail près, la position de la lumière est "collée" à celle de la caméra
    Après quelques recherches j'apprends que la position de la lumière doit être transposée de l'espace world à l'espace caméra (ou bien l'inverse j'ai pas trop compris )

    il me faudrait donc appliquer la variable LightPos une multiplication de matrice
    j'ai essayé avec modelview, positionMatrix, normalMatrix, rien ne change à quelques détails près

    je sais que c'est que c'est dans le vertex shader que je dois ajouter ou corriger quelque chose mais je suis bloqué, là

    Voici le code du shader :

    VERTEX_SHADER

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    uniform vec4 LightPos;
    uniform mat4 ModelViewMatrix;
    uniform mat4 ProjectionMatrix;
    uniform mat3 NormalMatrix;
    varying vec3 normal, lightDir, eyeVec;
     
     
    //attribute vec3 tangent;
     
    void main()
    {	
    	//vec3 lightposition = vec3(ModelViewMatrix * vec4(0.0, 0.0, 45.0,0.0));
     
    	normal = NormalMatrix * gl_Normal;
    	//normal = gl_NormalMatrix * gl_Normal;
     
    	vec3 vVertex = vec3(ModelViewMatrix * gl_Vertex);
    	//vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
     
    	//lightDir = vec3(gl_LightSource[0].position.xyz - vVertex);
    	lightDir = normalize(LightPos.xyz - vVertex);
    	//lightDir = normalize(lightposition - vVertex);
    	eyeVec = normalize(-vVertex);
     
    	gl_Position = ProjectionMatrix*ModelViewMatrix*gl_Vertex;
    	//gl_Position = gl_ProjectionMatrix*gl_ModelViewMatrix*gl_Vertex;
    }
    FRAGMENT_SHADER

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    varying vec3 normal, lightDir, eyeVec;
     
    void main (void)
    {
    	vec4 final_color = 
    	(gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) + 
    	(gl_LightSource[0].ambient * gl_FrontMaterial.ambient);
     
    	vec3 N = normalize(normal);
    	vec3 L = normalize(lightDir);
     
    	float lambertTerm = dot(N,L);
     
    	if(lambertTerm > 0.0)
    	{
    		final_color += gl_LightSource[0].diffuse * 
    		               gl_FrontMaterial.diffuse * 
    					   lambertTerm;	
     
    		vec3 E = normalize(eyeVec);
    		vec3 R = reflect(-L, N);
    		float specular = pow( max(dot(R, E), 0.0), 
    		                 gl_FrontMaterial.shininess );
    		final_color += gl_LightSource[0].specular * 
    		               gl_FrontMaterial.specular * 
    					   specular;	
    	}
     
    	gl_FragColor = final_color;			
    }
    (je récupère les paramètres ambient, diffuse depuis une glLight built-in, je ne pense pas que ça change quoique ce soit)

    Et voici une capture du "phénomène" :

    le cube au centre est l'objet éclairé et la "boîte" bleue représente la position de la lumière, on voit sur la fin que la tâche spéculaire "suit" le mouvement de la caméra
    (la vidéo est super rapide , j'ai pas fait dans le détail)


  2. #2
    Membre éprouvé Avatar de Robxley
    Homme Profil pro
    Docteur ingénieur traitement d'image
    Inscrit en
    Mai 2009
    Messages
    158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Docteur ingénieur traitement d'image

    Informations forums :
    Inscription : Mai 2009
    Messages : 158
    Par défaut
    Salut,

    Je pense qu'il faut que tu multiplies aussi la position de la lumière par ta matrice LookAt.


    En vite fais dans ton cas, tu as pour un vertex M.

    LOOKAT * TRANSFORMATION*M = M'
    L = L'
    DIRECTION = M'-L' (sauf que M' et L' pas dans le même espace).

    (ps : MODELVIEW = LOOKAT * TRANSFORMATION)

    Pour ton objet tu le transformes dans l'espace de la caméra (LOOKAT).
    Par contre pour ta lampe tu la laisses dans l'espace d'origine donc inchangé par rapport à la camera.

    En reprenant ton code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    void main()
    {	
     
    	normal = NormalMatrix * gl_Normal;
     
            //Vertex dans l'espace camera.
    	vec3 vVertex = vec3(ModelViewMatrix * gl_Vertex); 
     
            //Opération de 2 vecteurs dans 2 espaces différents !!!!
    	lightDir = normalize(LightPos.xyz - vVertex); 
     
    	eyeVec = normalize(-vVertex);
    	gl_Position = ProjectionMatrix*ModelViewMatrix*gl_Vertex;
     
    }
    Il faut que tu fasses tes calculs de lumière et vertex dans le même espace, si non ça n'a pas trop de sens sauf si tu veux faire des effets bizarres.

    Il suffit donc de rajouter la transformation de la position de ta lumière dans le même espace que ton vertex en la multipliant par la matrice de lookat:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    void main()
    {	
     
    	normal = NormalMatrix * gl_Normal;
     
    	vec3 vVertex = vec3(ModelViewMatrix * gl_Vertex); //Vertex dans l'espace camera.
            vec3 vLightPos = vec3(LookAt* LightPos); //Vertex dans l'espace camera 
     
     
    	lightDir = normalize(vLightPos - vVertex); //Ils sont dans le même espace !!!
    	eyeVec = normalize(-vVertex);
    	gl_Position = ProjectionMatrix*ModelViewMatrix*gl_Vertex;
     
    }
    Attention ici ta matrice ModelViewMatrix contient LookAt + transformation de ton objet surement (rotation translation), donc qui seront aussi appliquées à ta lumière.
    Si tu as des "pré-transformation" de translation / rotation sur tes objets. Il faudra que tu passes la matrice LookAt à ton shader pour multiplier la position de ta lumière que par LookAt et non ModelView qui contient en plus de LookAt les pré-transformations de ton objet.

    Gna !!!
    J'espere avoir été un minimum compréhensible.
    En espérant que ce soit ça.

  3. #3
    Membre très actif
    Profil pro
    Dev
    Inscrit en
    Mai 2009
    Messages
    257
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Mai 2009
    Messages : 257
    Par défaut
    j'ai essayé ta solution, en récupérant la matrice de lookat juste après le lookat, ça n'a rien changé

    par contre j'ai essayé en multipliant par la matrice des normales (NormalMatrix)
    :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    uniform vec4 LightPos;
    uniform mat4 ModelViewMatrix;
    uniform mat4 ProjectionMatrix;
    uniform mat3 NormalMatrix;
    uniform mat4 LookatMatrix;
    varying vec3 normal, lightDir, eyeVec;
     
     
    //attribute vec3 tangent;
     
    void main()
    {	
     
    	vec3 lightposition = vec3(NormalMatrix * LightPos.xyz);
    	//vec3 lightposition = vec3(LookatMatrix * LightPos);
    	//vec3 lightposition = LightPos.xyz;
     
    	normal = NormalMatrix * gl_Normal;
    	//normal = gl_NormalMatrix * gl_Normal;
     
    	vec3 vVertex = vec3(ModelViewMatrix * gl_Vertex);
    	//vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
     
    	//lightDir = normalize(lightposition);
    	lightDir = normalize(lightposition - vVertex);
    	eyeVec = normalize(-vVertex);
     
    	gl_Position = ProjectionMatrix*ModelViewMatrix*gl_Vertex;
    	//gl_Position = gl_ProjectionMatrix*gl_ModelViewMatrix*gl_Vertex;
    }
    rien changé non plus, mais si j'active la ligne lightDir = normalize(lightposition), j'obtiens ceci :



    j'ai essayé sur d'autres modéles et ça m'a l'air correct (le cube n'est pas très parlant)
    certains proposent cette solution sur le net

    qu'en penses-tu ?

  4. #4
    Membre émérite

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2006
    Messages
    450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2006
    Messages : 450
    Par défaut
    Ce que tu fais la c'est juste la direction est egale a la direction entre la position de ta lumiere et le centre du repere OpenGL. Si tu veux avoir une direction fixe par rapport au monde, il faut que tu appliques la normal matrix directement sur cette direction definie en repere monde en n'oubliant pas de mettre le w de la direction a 0. Et pense a renormaliser par la suite...

  5. #5
    Membre très actif
    Profil pro
    Dev
    Inscrit en
    Mai 2009
    Messages
    257
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Mai 2009
    Messages : 257
    Par défaut
    donc multiplication par LookAt (même si ça ne change rien) puis multiplication par NormalMatrix

    le résultat dans la vidéo est correct ou pas ?

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    318
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 318
    Par défaut
    j'ai eu le même problème que toi.

    regarde ici: http://www.developpez.net/forums/d90...x-shader-glsl/

    ça été résolue en séparant gl_ModelViewMatrix en ModelMatrix et ViewMatrix

Discussions similaires

  1. Détection position des yeux dans une image
    Par Morvan Mikael dans le forum Traitement d'images
    Réponses: 16
    Dernier message: 24/12/2008, 23h09
  2. Position d'une lumière
    Par JoeBlack dans le forum OpenGL
    Réponses: 7
    Dernier message: 11/12/2008, 09h28
  3. la position des pixels dans une direction
    Par kaiseresis dans le forum Traitement d'images
    Réponses: 4
    Dernier message: 05/12/2008, 09h17
  4. Ecrire directement avec une autre langue???
    Par touhami dans le forum API, COM et SDKs
    Réponses: 2
    Dernier message: 21/02/2005, 21h57
  5. Obtenir la position du curseur dans une Image
    Par bastoune dans le forum Composants VCL
    Réponses: 6
    Dernier message: 14/11/2003, 21h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo