dan*_*jar 5 shader lighting glsl normals vertex-shader
我有一个场景,有几个模型,有个别位置和旋转.给定法线,着色器将简单的双向照明应用于每个像素.
那是我的顶点着色器.
#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);
}
Run Code Online (Sandbox Code Playgroud)
这是片段着色器.
#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);
}
Run Code Online (Sandbox Code Playgroud)
对于没有旋转的对象,这很好.但是对于旋转模型,照明也是旋转的,当然不应该是这种情况.
原因是法线不旋转.我已经尝试了,f_normal = model * normal;但这适用于法线的旋转和变换.
那么在将它们发送到片段着色器进行照明之前,如何在顶点着色器中旋转法线呢?什么是常用方法?
您确实需要通过模型-视图-投影矩阵的上 3 行/列来转换法线。(如果您正在执行任何缩放,则需要使用此矩阵的逆转置。请参阅此文章)。
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));
Run Code Online (Sandbox Code Playgroud)
在片段着色器中,您需要计算从光源到片段的距离并进行标准化。找到法线和光向量的点积,然后乘以光的颜色。
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);
Run Code Online (Sandbox Code Playgroud)
我的代码肯定有优化的空间。
我推荐这本书OpenGL 4.0 Shading Language Cookbook。