Point light illuminating half of scene

Started by
3 comments, last by noobiedoobie 4 years, 3 months ago

My point light is illuminating only half of the scene on 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? I feel like I've tried everything but nothing helps.

Here's the shaders. I'm not doing anything out of the ordinary.

//
// VERT SHADER
//
#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);
}
 
 
//
// FRAG SHADER
//
#version 410 core
#define MAX_POINT_LIGHTS 4
#define DIST_FACTOR 1.1f
 
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;
vec3 normal;
 
float attenuate(float dist, const PointLight light) {
    dist *= DIST_FACTOR;
    return light.strength / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist);
}
 
//
// MAIN
//
void main()
{
  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);
}

Cheers.

Advertisement

The shader looks fine, aside from not using the light color. I would check to make sure you are passing the correct inputs. Visualize the normals and ensure they make sense.

Normal matrix gets inversed and transopsed aside the fact you use it as world matrix, which can happen to have translation data with it which is not correct. Store only rotation in normal matrix then rotate normals by it.

---

Didnt read attenuate function…

And the naming

vec3 lightDir = light.position - fWorldPos;

vector AB = B - A

So lightDir is reversed in your case

max(dot(normal, lightDir), 0.0);

First of all i dont think you neeed to renormalize normal anyway

Heres a thing if you change lightdir to be a light direction from light to world fragment position - then dot () < 0 means that light is facing the surface (fragment)

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!

This topic is closed to new replies.

Advertisement