Как рассчитать нормальную матрицу?

У меня есть некоторые проблемы с моей нормальной матрицей.

vs .glsl

#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; 
}

Результат этого выглядит так: enter image description here

Это показалось мне немного странным. Но я знал, что я не масштабирую ничего, поэтому я думал, что смогу использовать матрицу modelView для преобразования моих нормалей.

Итак, я изменил строку

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

к

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

И теперь результат выглядит так:

enter image description here

который выглядит правильно. Я исчисляю свой normalMatrix неправильный путь?

Ответы

Ответ 1

Нормальная матрица - это транспонирование, обратная матрице вида. Поэтому в GLSL это будет

mat4 normalMatrix = transpose(inverse(modelView));

Однако вы должны НЕ вычислить нормальную матрицу в шейдере. Выполнение этого в шейдере тратит много драгоценных циклов GPU. Матричная инверсия - это не дешевая операция, чтобы начать с нее и сделать ее в шейдерном режиме, заставляя графический процессор выполнять вычисления для каждой и каждой вершины снова и снова. Предварительно расчитайте его на CPU и передайте его как единое целое.