如何计算正常矩阵?

时间:2014-01-12 20:03:15

标签: opengl graphics 3d glsl

我的普通矩阵有些问题。

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吗?

2 个答案:

答案 0 :(得分:44)

法线矩阵是模型视图矩阵的转置逆。所以在GLSL中它将是

mat4 normalMatrix = transpose(inverse(modelView));

但是你应该 NOT 计算着色器中的正常矩阵。在着色器中执行此操作会浪费大量宝贵的GPU周期。矩阵求逆不是一个开始的廉价操作,并且在着色器中执行它会迫使GPU一次又一次地执行每个顶点的计算。在CPU上预先计算并将其作为制服传递。

答案 1 :(得分:0)

它也是GLSL中的默认制服。您可以这样声明

uniform mat3 normalMatrix;

See here.