A point light is illuminating only a half of a scene in my small 3D renderer. It happens on every scene I've tried (conference room, cornell box, etc).

How do I go about debugging this? What could be wrong?

sponza scene

Here are the shaders. I'm not doing anything out of the ordinary. Light is positioned at (0, 1.0, 0) in world space.

#version 410 core

uniform mat4 M;
uniform mat4 V;
uniform mat4 P;

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec3 color;
layout (location = 3) in vec2 texCoords;

out vec3 fWorldPos;
out vec3 fNormal;
out vec3 fColor;
out vec2 fTexCoords;

void main()
    mat4 normalMatrix = transpose(inverse(M));

    fWorldPos = vec3(M * vec4(position, 1.0));
    fNormal = normal; // also tested multiplying with normal, M, and MV matrices
    fColor = color;
    fTexCoords = texCoords;

    gl_Position = P * V * M * vec4(position, 1);

#version 410 core

struct PointLight {
    float strength;
    vec3 position;
    vec3 color;
    vec3 attenuation;

struct Material {
    vec3 color;

uniform Material material;
uniform int totalPointLights;
uniform PointLight pointLights[MAX_POINT_LIGHTS];
uniform vec3 cameraPosition;

in vec3 fWorldPos;
in vec3 fNormal;
in vec3 fColor;
in vec2 fTexCoords;

out vec4 color;

float attenuate(float dist, const PointLight light) {
    return light.strength / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist);

void main()
  vec3 normal = normalize(fNormal);

  PointLight light = pointLights[0];

  vec3 lightDir = light.position - fWorldPos;
  float lightDst = length(lightDir);
  lightDir = lightDir / lightDst;

  float att = attenuate(lightDst, light);
  float diffuseFactor = max(dot(normal, lightDir), 0.0);

  color = vec4(material.color * diffuseFactor * att, 1);
  • $\begingroup$ is this a raytracer or something? If so can you try to disable shadows and see if it renders everything then? It happened with me once due to incorrect intersection testing and it was thinking that the lit surface was in shadow $\endgroup$ – gallickgunner Jan 21 at 19:33
  • $\begingroup$ @gallickgunner No, it's just a regular forward renderer. It loads a scene from an .obj -file and renders it using the shader above. There are no shadows yet. Thanks though. $\endgroup$ – Ohkomonkiainen Jan 21 at 19:50
  • $\begingroup$ Quick thought, it may be because of the diffuseFactor term or the att term going to zero. Did you try inverting the normals or the light direction and see how does it look then? You can also try to just set the material color and add terms one by one so as to figure out which factor is causing the problem $\endgroup$ – gallickgunner Jan 21 at 22:31
  • $\begingroup$ Wrong normals perhaps? Test with M == identity to see if that's the problem. You should transform the normal with the transpose of the inverse matrix. And then normalize it again. $\endgroup$ – Olivier Jan 22 at 1:56

The normals were indeed wrong. Which was crazy, because I had even checked in Blender that they were correct (and they were). Turns out, when loading the mesh, I was passing the normal as color and vice versa. Valletin's normal visualization shader was great (https://vallentin.dev/2015/02/16/visualizing-normals).

Thanks for your help!

enter image description here

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.