6

我有一个场景,其中包含多个具有单独位置和旋转的模型。给定法线,着色器对每个像素应用简单的双向光照。

那是我的顶点着色器。

#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;,但这会将旋转和变换都应用于法线。

那么在将法线发送到片段着色器进行照明之前,如何在顶点着色器中旋转法线?什么是常用方法?

4

2 回答 2

5

You do need to transform the normals, by the upper 3 rows/cols of the model-view-projection matrix. (If you are performing any scaling though, you need to use the inverse transpose of this matrix. See this article).

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));

In your fragment shader, you need to calculate the distance from your light source to your fragment and normalize. Find the dot product of the normal and the light vector and multiply this by the light color.

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);

There is definitely room for optimization in my code.

I recommend this book OpenGL 4.0 Shading Language Cookbook.

于 2013-01-07T14:27:08.380 回答
0

以下解决方案适用于我的模型,但我对其背后的数学没有很深的了解。这是我的来源:添加深度和真实感 - 表面法线

您需要应用于法线向量的变换表示为: N' = N * (M -1 ) T

基本上,这意味着您将法线 (N) 乘以 ModelView 矩阵 (M) 的反转置。如果您的 M 矩阵是 4x4,您应该只使用 (M -1 ) T生成的 3x3 左上象限进行正常乘法。

同样,这对我有用,但我不能很好地解释数学。

于 2013-01-07T13:57:35.303 回答