Home > Net >  Trouble with GLSL dot product
Trouble with GLSL dot product

Time:10-11

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) 1 0 0
  • Light coming down ([0, -1, 0] as light vector) 0 -1 0
  • Light coming from behind ([0, 0, 1] as light vector) 0 0 1

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

  • Related