So I was trying to implement basic diffuse lighting using OpenGL. I wrote a simple shader that would take a normal vector and a light vector and calculate the brightness of a pixel using the dot product of said vectors. Here are my outputs:
- Light coming from the left ([1, 0, 0] as light vector)
- Light coming down ([0, -1, 0] as light vector)
- Light coming from behind ([0, 0, 1] as light vector)
As you can see, it works just fine for the first two cases, but it completely breaks for the third. By the way, [0, 0, -1] doesn't work either and [0, 1, 1] gives the same output as if the light was coming up ([0, 1, 0]). Here are my shaders :
- Vertex shader:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform vec3 lightDirection;
out vec3 normal;
out vec3 lightDir;
void main()
{
normal = normalize(aNormal);
lightDir = normalize(lightDirection);
gl_Position = projection * view * model * vec4(aPos, 1.0f);
}
- Fragment shader:
#version 330 core
in vec3 normal;
in vec3 lightDir;
out vec4 FragColor;
void main()
{
float grey = max(dot(-lightDir, normal), 0.0f);
FragColor = vec4(grey, grey, grey, 1.0f);
}
I assume the issue has something to do with the dot product, but I can't find why.
CodePudding user response:
The diffuse light is calculated using the formula max(dot(-lightDir, normal), 0.0f);
. So if dot (-lightDir, normal)
is less than 0, the scene is completely black.
The Dot product of 2 Unit vector is the cosine of the angle between the 2 vectors. Hence, if the angle is > 90° and < 270° the result is less than 0.
This means, that when the object is lit at the back, it will appear completely black.
The light direction is a vector in world space. dot(-lightDir, normal)
only makes sense if normal is also a vector in world space.
Transform normal
from model space to world space:
normal = inverse(transpose(mat3(model))) * normalize(aNormal);
(Why transforming normals with the transpose of the inverse of the modelview matrix?)