Light changes brightness depending on position

In my scene I have a base surface and one object in the origin (0, 0, 0) that I illuminate with one directional light and a camera (position = (0, 13.07, 149.42)) to look at it (the pictures below are taken with a different angle but the effect is the same)

Sadly the lighting in the scene is currently wrong: The brightness seems to depend on the position of the light. When the light is directly in front of the object, it is too bright (light position = (0, 17.43, 199.23))
buddha00001368-0-30-0-1

When it is behind, it’s too dank (actually no light).
buddha00002052-0-30-180-1

And when the light is at the left or the right next to the object, it seems comprehensible.
buddha00002394-0-30-270-1 buddha00001710-0-30-90-1

The light moves around the object with the same distance like on a hemisphere. To be sure that the position of the light is calculated correctly, I drew a red line everywhere on the hemisphere where my light put and the origin.

So the lightPos should be correctly. That means the error happens within the shaders where debugging sucks.

I calculate my lighting in the shaders in view space but it seems that I am messing up something between the world and the view space here.

Here is my Renderer.cpp where I pass the variables:

	glViewport(0, 0, window_width, window_height);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glm::mat4 view = observer_camera.getViewMatrix();
	glm::mat4 projection = observer_projection;

	model = glm::scale(glm::mat4_cast(parameter.globalRotation), glm::vec3(parameter.modelScalation));
	model = glm::rotate(glm::mat4(1.f), glm::radians(parameter.modelRotation), glm::vec3(0.f, 1.f, 0.f)) * model; 

	shader->use();
	//new 
	glUniform4fv(locs.ambientLight, 1, glm::value_ptr(parameter.ambientLight));
	glUniform4fv(locs.diffusLight, 1, glm::value_ptr(parameter.diffusLight));
	glUniform4fv(locs.spekularLight, 1, glm::value_ptr(parameter.specularLight));
	glUniform4fv(locs.ambientMaterial, 1, glm::value_ptr(parameter.ambientMaterial));
	glUniform4fv(locs.diffusMaterial, 1, glm::value_ptr(parameter.diffusMaterial));
	glUniform4fv(locs.spekularMaterial, 1, glm::value_ptr(parameter.spekularMaterial));
	glUniform1f(locs.shininessMaterial, parameter.shininessMaterial);
	glUniform1f(locs.brightnessFactor, parameter.brightnessFactor);

	glUniformMatrix4fv(locs.modelViewProjection, 1, GL_FALSE, glm::value_ptr(projection * view * model));
	glUniformMatrix4fv(locs.modelview, 1, GL_FALSE, glm::value_ptr(view * model));

	normal = glm::mat3(glm::transpose(glm::inverse(view * model)));
	glUniformMatrix3fv(locs.normalmatrix, 1, GL_FALSE, glm::value_ptr(normal));

	glm::mat4 lightsource_view = lightsource_camera.getViewMatrix();
	glUniformMatrix4fv(locs.biasedModelViewProjection, 1, GL_FALSE, glm::value_ptr(bias * lightsource_projection * lightsource_view * model));

	glUniform3fv(locs.lightPos, 1, glm::value_ptr(parameter.lightPos));
	//glUniform3fv(locs.lightPos, 1, glm::value_ptr(view * parameter.lightPos));
	//glUniform3fv(locs.lightPos, 1, glm::value_ptr(glm::inverse(view) * parameter.lightPos));
	glm::mat4 normView = glm::mat4(glm::transpose(glm::inverse(view)));
	//glUniform3fv(locs.lightPos, 1, glm::value_ptr(normView * parameter.lightPos));

	glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &locs.lightingVS);
	glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &locs.lightPhong);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, shadowmap->getTextureID());
	glBindSampler(0, shadowmap_sampler);
	glUniform1i(locs.shadowmap, 0);

	glBindVertexArray(basesurface.vao);
	glDrawArrays(GL_TRIANGLES, 0, basesurface.vertsToDraw);

	glBindVertexArray(object.vao);
	glDrawArrays(GL_TRIANGLES, 0, object.vertsToDraw);

My vertex shader:

struct Matrices
{
mat4 mvp;
mat4 mv;
mat4 mod;
mat3 normal;
mat4 bmvp;
};

struct Light
{
vec3 lightPos;
vec4 ambient;
vec4 diffus;
vec4 specular;
float brightnessFactor;

float near_cp;
float far_cp;
};

struct VertexOutput
{
vec3 normal;
vec3 lightDir;
vec3 viewDir;
vec4 FragPos;

vec4 shadow_coordinates;

vec2 TexCoords;
};

subroutine void VertexProgram();

layout(location = 0) in vec4 vertex;
layout(location = 1) in vec3 normal;

uniform Matrices matrices;

uniform Light light;

subroutine uniform VertexProgram vertexprogram;

layout(location = 0) out VertexOutput Output;


subroutine (VertexProgram) void verts_and_normals()
{
gl_Position = matrices.mvp * vertex; //clip space

Output.normal = matrices.normal * normal; // view space 

vec4 h = matrices.mv * vertex; // view space
vec3 mvPos = h.xyz / h.w; // view space
Output.viewDir = -mvPos; // view space

//Output.lightDir = normalize(light.lightPos - mvPos); //  == point light
Output.lightDir = light.lightPos; // == directional light // word space  


Output.shadow_coordinates = matrices.bmvp * vertex; //clip space
}

My fragment shader:

struct Matrices
 {
mat4 mvp;
mat4 mv;
mat4 mod;
mat3 normal;
mat4 bmvp;
};


 struct Light
{
vec3 lightPos;
vec4 ambient;
vec4 diffus;
vec4 specular;
float brightnessFactor;

float near_cp;
float far_cp;
};

struct Material 
{
vec4 ambient;
vec4 diffus;
vec4 specular;
vec4 emissiv;
float shininess;
};


struct FragmentInput
{
vec3 normal;
vec3 lightDir;
vec3 viewDir;
vec4 FragPos;

vec4 shadow_coordinates;

vec2 TexCoords;
};

struct Normalized
{
vec3 normal;
vec3 lightDir;
vec3 viewDir;
};

...

layout (index = 3) subroutine (FragmentProgram) void phongWithLambert()
{


Normalized n;
n.viewDir = normalize(Input.viewDir); // view space
n.lightDir = normalize(Input.lightDir); //world space
n.normal = normalize(Input.normal); // view space
// --------- Phong ---------

// Ambient light
vec4 ambient = light.ambient * material.ambient; 

// Diffuse light
float d = max(dot(n.normal, n.lightDir), 0.0f);
vec4 diffus = d * light.diffus * material.diffus;

// Specular
vec4 specular = vec4(0.f, 0.f, 0.f, 1.f);
if (d > -0.001f)
{
	vec3 r = reflect(-n.lightDir, n.normal);
	specular = pow(max(dot(normalize(r), n.viewDir), 0.f), material.shininess) * light.specular * material.specular;
}

// --------- Shadows ---------
vec3 shadow_coordinates = Input.shadow_coordinates.xyz / Input.shadow_coordinates.w;
float min_shadow_darkness = 1.f, max_shadow_darkness = .0f; //.35f;

float shadowsample = clamp(texture(tex.shadowmap, shadow_coordinates), max_shadow_darkness, min_shadow_darkness);


// --------- Result --------- 

out_color =(shadowsample * (specular + diffus) + ambient);
out_color.a = 1.f;

What am I doing wrong?

Is my classification in world/view/clip space in the vertex shader right?

I tried all to pass the light position in the Renderer with all the possibilities that are written as comment but nothing worked. It even became worse.

When I change in the vertex shader from
Output.lightDir = light.lightPos;
to
Output.lightDir = -light.lightPos;
it gets worse, too.

I thinks for someone with experience this is a easy one but I could not fine my mistake.

Many thanks in advance!

I have no idea. You aren’t showing either the position attribute or the gl_Position output, or anything in between.

It seems that you’re transforming the normals to eye space, so everything else in the lighting calculations needs to be in eye space (i.e. transformed by view * model).

Also, you shouldn’t need to be dividing by W because eye-space coordinates should always have W=1; the lighting calculations won’t work in a coordinate system with a projective transformation.

hi MolineraNegra,
A quick look suggests that nothing is wrong. That’s not helpful.

doesn’t that suggest in it’s own right that the ambient component is too vague?
How are the ‘surface’ placed, relative to the model ? If the light is in-between the model and surface, they should light up differently.

Am I off course when suggesting that viewDir in view-space is down z-axis … it’s probably a foul comment you add but it pops up in the fragment-shader too …
I’m not proficient enough to comment on the light-model itself. A quick googl suggests that ambiance and diffuse ‘means’ the same thing.

Many thanks to both of you! You have given me a new food for thought that has solved my problem.

Passing the lightPos modified like this solved the problem:

glm::mat4 normView = glm::mat4(glm::transpose(glm::inverse(view)));
glUniform3fv(locs.lightPos, 1, glm::value_ptr(normView * parameter.lightPos));

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.