I want to add directional light to my scene using OpenGL and GLSL. The problem is that the theoretically correct way to do so has the wrong results.
In the vertex shader I do the following:
The direction of the light is given in world-coordinates and transformed using the viewMatrix to camera-coordinates. The normal of the vertex is transformed using the normal-matrix to camera-coordinates.
void main () {
vary_textureCoord = attribute_textureCoord;
vary_normal = mat3(normalMatrix) * attribute_normal;
vary_directionalLight_direction = viewMatrix * vec4(lightDir, 1.0);
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(attribute_position, 1.0);
}
So both vectors are in camera-coordinates and passed to the fragment shader. The fragment shader calculates the light intensity using the normal and the direction of the light.
void main () {
vec3 normalizedNormal = normalize(vary_normal);
vec4 color = texture(tex, vary_textureCoord);
float directionalLightIntensity = max(0.0, dot(normalizedNormal, normalize(-vary_directionalLight_direction.xyz)));
out_color = color * directionalLightIntensity;
}
This shader leads to the result that the light is not static but moves along with the camera. Changing the vertex shader using this line instead:
vary_directionalLight_direction = transpose(inverse(viewMatrix)) * vec4(lightDir, 1.0);
has the desired results. So what am I doing wrong or where do I have a misunderstanding?
Here the full shader codes:
Vertexshader:
# version 330
layout(location = 0) in vec3 attribute_position;
layout(location = 2) in vec2 attribute_textureCoord;
layout(location = 3) in vec3 attribute_normal;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
uniform mat4 normalMatrix;
uniform vec3 lightDir;
out vec2 vary_textureCoord;
out vec3 vary_normal;
out vec4 vary_directionalLight_direction;
void main () {
vary_textureCoord = attribute_textureCoord;
vary_normal = mat3(normalMatrix) * attribute_normal;
vary_directionalLight_direction = viewMatrix * vec4(lightDir, 1.0);
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(attribute_position, 1.0);
}
Fragmentshader:
# version 330
in vec2 vary_textureCoord;
in vec3 vary_normal;
in vec4 vary_directionalLight_direction;
uniform sampler2D tex;
out vec4 out_color;
void main () {
vec3 normalizedNormal = normalize(vary_normal);
vec4 color = texture(tex, vary_textureCoord);
float directionalLightIntensity = max(0.0, dot(normalizedNormal, normalize(-vary_directionalLight_direction.xyz)));
out_color = color * directionalLightIntensity;
}