Question

J'écris un petit test d'ombrage de Phong et je me cogne la tête contre un mur de briques en essayant de faire fonctionner le composant spéculaire.Cela semble fonctionner correctement, sauf que la lumière spéculaire est appliquée à la fois à l'avant et à l'arrière de l'objet.(L'objet lui-même est transparent, avec des faces triées manuellement côté CPU.)

Notez que le composant diffus fonctionne parfaitement (n'apparaît que sur le côté faisant face à la source lumineuse) – ce qui semblerait exclure un problème avec les normales arrivant au fragment shader, je pense.

Si je comprends bien, la composante spéculaire est proportionnelle au cos de l'angle entre le vecteur œil et le vecteur lumière réfléchie.

Pour garder les choses ultra simples, mon code de test essaie de le faire dans l'espace mondial.La position de la caméra et le vecteur de lumière sont codés en dur (désolé) comme (0,0,4) et (-0.707, 0, -0.707) respectivement.Le vecteur œil est donc (0,0,4) - fragPosition.

Puisque la matrice modèle effectue uniquement la rotation, le vertex shader transforme simplement le sommet normal par la matrice modèle.(Note: ce n'est pas une bonne pratique car de nombreux types de transformation ne préservent pas l'orthogonalité normale.Généralement pour la matrice normale, Tu devrais utiliser la transposition inverse du 3x3 supérieur gauche de la matrice du modèle.) Pour garder les choses simples, le fragment shader fonctionne sur un seul canal de couleur flottant et ignore l'exposant spéculaire (/utilise un exposant de 1).

Shader de sommet :

#version 140

uniform mat4 mvpMtx;
uniform mat4 modelMtx;

in vec3 inVPos;
in vec3 inVNormal;

out vec3 normal_world;
out vec3 fragpos_world;

void main(void) {
  gl_Position = mvpMtx * vec4(inVPos, 1.0);
  normal_world = vec3(modelMtx * vec4(inVNormal, 0.0));
  fragpos_world = vec3(modelMtx * vec4(inVPos, 1.0)); 
}

Nuancier de fragments :

#version 140

uniform float
    uLightS,
    uLightD,
    uLightA;

uniform float uObjOpacity;

in vec3 normal_world, fragpos_world;
out vec4 fragOutColour;

void main(void) {

    vec3 vN = normalize(normal_world);
    vec3 vL = vec3(-0.707, 0, -0.707);

    // Diffuse:
    // refl in all directions is proportional to cos(angle between -light vector & normal)
    // i.e. proportional to -l.n
    float df = max(dot(-vL, vN), 0.0);

    // Specular:
    // refl toward eye is proportional to cos(angle between eye & reflected light vectors)
    // i.e. proportional to r.e
    vec3 vE = normalize(vec3(0, 0, 4) - fragpos_world);
    vec3 vR = reflect(vL, vN);
    float sf = max(dot(vR, vE), 0.0);

    float col = uLightA + df*uLightD + sf*uLightS;

    fragOutColour = vec4(col, col, col, uObjOpacity);

}

Je ne trouve pas d'erreur ici ;Quelqu'un peut-il expliquer pourquoi la composante spéculaire apparaît à l'arrière ainsi que sur le côté orienté vers la lumière de l'objet ?

Merci beaucoup.

Était-ce utile?

La solution

Votre contribution spéculaire sera en fait la même pour les faces recto et verso car GLSL reflect est insensible au signe de la normale.Depuis cette référence:

reflect(I, N) = I - 2.0 * dot(N, I) * N

donc inverser le signe de N introduit deux signes moins qui s'annulent.En mots, quoi reflect ce que fait est d'inverser le signe de la composante de I qui est sur le même axe que N.Cela ne dépend pas de la manière dont N fait face.

Si vous souhaitez supprimer le composant spéculaire de vos faces arrière, je pense que vous devrez vérifier explicitement votre dot(vE,vN).

Autres conseils

Essayez de changer

fragpos_world = vec3(modelMtx * vec4(inVPos, 0.0)); 

à

fragpos_world = vec3(modelMtx * vec4(inVPos, 1.0)); 

parce que http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/#Homogeneous_coordonnées

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top