web-dev-qa-db-fra.com

Comment calculer la matrice normale?

J'ai des problèmes avec ma matrice normale.

vsglsl

#version 440

in vec3 vPosition;
in vec3 vNormal;

out vec4 eyeCordFs;
out vec4 eyeNormalFs;

uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;

void main()
{   
    mat4 modelView = view * model;
    mat4 normalMatrix = view * transpose(inverse(model));
    vec4 eyeNorm = normalize(normalMatrix * vec4(vNormal, 0.0));
    vec4 eyeCord= modelView * vec4(vPosition, 1.0);

    eyeCordFs = eyeCord;
    eyeNormalFs = eyeNorm;

    gl_Position = proj * modelView * vec4( vPosition,1.0);
}

fs.glsl

#version 440

in vec4 eyeCordFs;
in vec4 eyeNormalFs;

out vec3 outputColor;

uniform vec4 lightPos;

void main()
{
    vec4 s = normalize(lightPos - eyeCordFs) ;
    vec4 r = reflect(-s,eyeNormalFs);
    vec4 v = normalize(-eyeCordFs);
    float spec = max( dot(v,r),0.0 );
    float diff = max(dot(eyeNormalFs,s),0.0);

    vec3 diffColor = diff * vec3(1,0,0);
    vec3 specColor = pow(spec,3) * vec3(1,1,1);
    vec3 ambientColor = vec3(0.1,0.1,0.1);

    outputColor =  diffColor + 0.5 * specColor + ambientColor; 
}

La sortie de ceci ressemble à enter image description here

Ce qui me semblait un peu étrange. Mais je savais que je ne modifiais rien, alors j'ai pensé que je pouvais utiliser la matrice modelView pour transformer mes normales.

J'ai donc changé de ligne

vec4 eyeNorm = normalize(normalMatrix * vec4(vNormal, 0.0));

à

vec4 eyeNorm = normalize(modelView * vec4(vNormal, 0.0));

Et la sortie ressemble maintenant à ceci

enter image description here

qui semble correct. Suis-je en train de calculer mon normalMatrix dans le mauvais sens?

17
Maik Klein

La matrice normale est l'inverse de transposition de la matrice de visualisation du modèle. Donc, dans GLSL, ce serait

mat4 normalMatrix = transpose(inverse(modelView));

Cependant, vous devez PAS calculer la matrice normale dans le shader. Faire cela dans le shader gaspille beaucoup de précieux cycles GPU. L'inversion de matrice n'est pas une opération bon marché au départ et le faire dans le shader oblige le GPU à effectuer le calcul pour chaque sommet encore et encore. Précalculez-le sur le CPU et passez-le comme uniforme.

48
datenwolf

Il s'agit également d'un uniforme par défaut dans GLSL. Vous pouvez simplement le déclarer comme tel

uniform mat3 normalMatrix;

Voir ici.

0
nequalstim