旋转着色法线(Rotate Normals in Shader)

2019-08-05 21:50发布

我有一个场景几款车型与个别位置和旋转。 由于法线,着色器将简单的双向照明到每个像素。

这是我的顶点着色器。

#version 150

in vec3 position;
in vec3 normal;
in vec2 texcoord;

out vec3 f_normal;
out vec2 f_texcoord;

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

void main()
{
    mat4 mvp = proj * view * model;

    f_normal   = normal;
    f_texcoord = texcoord;

    gl_Position = mvp * vec4(position, 1.0);
}

这里是片段着色器。

#version 150

in vec3 f_normal;
in vec2 f_texcoord;

uniform sampler2D tex;

vec3 sun = vec3(0.5, 1.0, 1.5);

void main()
{
    vec3 light = max(0.0, dot(normalize(f_normal), normalize(sun)));

    gl_FragColor = texture(tex, f_texcoord) * vec4(light, 1.0);
}

对于没有旋转物体能正常工作。 但对于旋转的模型照明旋转以及其中,当然,不应该是这样的。

其原因在于,法线不旋转。 我已经尝试过f_normal = model * normal; 但是,这适用于旋转和变换的法线。

所以,我怎么能旋转法线在顶点着色器之前,我把它们发送到片段着色器的照明? 什么是常见的做法?

Answer 1:

你需要变换法线,由模型 - 视图 - 投影矩阵的上3行/ COLS。 (如果您虽然执行任何缩放,您需要使用这个矩阵的逆转。 请参阅此文章 )。

mat3 normalMatrix = mat3(mvp);
normalMatrix = inverse(normalMatrix);
normalMatrix = transpose(normalMatrix);
f_normal = normalize(normal * normalMatrix);
// You should also send your tranformed position to the fragment shader
f_position = vec3(mvp * vec4(position, 1.0));

在您的片段着色器,你需要从光源计算到你的片段和规范的距离。 找到正常的点积和光矢量和光色乘这一点。

vec3 light = normalize(sun - f_position);
light = max(dot(f_normal, light), 0.0) * vec3(1.0, 1.0, 1.0);
gl_FragColor = texture(tex, f_texcoord) * vec4(light, 1.0);

肯定是有空间在我的代码优化。

我推荐这本书的OpenGL 4.0着色语言食谱 。



Answer 2:

以下解决方案可与我的模型,但我没有它背后的数学非常深刻的理解。 这是我的源: 增加深度和现实主义-表面法线

变换你需要申请到正常的载体是通过记:N” = N *(M-1)

基本上,这意味着你通过您的模型视图矩阵(M)的逆转置相乘的法线(N)。 如果你的M矩阵为4x4,你应该只使用(M-1)T的3×3导致左上象限的正常繁殖。

同样,这对我的作品,但我无法解释的数学太清楚。



文章来源: Rotate Normals in Shader