Advertisement Jump to content
Sign in to follow this  

GLSL light position troubles

This topic is 1652 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts


Solved...I'm apparently just an idiot :P The method I was using to create my sphere models and UV maps was inverting things (the normals I'm guessing) inadvertently. I was trying to avoid as much distortion in the texture as possible, but that method is apparently no good for this. Loading just a basic sphere instead solves the problem below. I'll leave this up on the off-chance it's helpful to someone else making the same mistake. But, mods, no hard feelings if you'd rather just delete it.



I've been learning opengl for a couple months now, and decided to start implementing shaders (probably rather late, I'd been avoiding them out of intimidation, and having my hands full with the rest of opengl) . Up until now I've simply been using the basic ones from the tutorials here:

However, somewhere, I'm doing something wrong as the light for the objects seems to coming from the opposite direction from where I thought it would, but only along the camera x/y axes. If the object is behind the light, it looks correct, or if it is in front, it is properly silhouetted. But, if the object is to the left or the right of the light, the lightsource appears to be on the wrong side of the object. 

#version 440 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;
layout(location = 2) in vec3 vertexNormal_modelspace;

// Output data ; will be interpolated for each fragment.
out vec2 UV;
out vec3 Position_worldspace;
out vec3 Normal_cameraspace;
out vec3 EyeDirection_cameraspace;
out vec3 LightDirection_cameraspace;

// Values that stay constant for the whole mesh.
uniform mat4 MVP;
uniform mat4 V;
uniform mat4 M;
uniform vec3 LightPosition_worldspace;

void main(){

	// Output position of the vertex, in clip space : MVP * position
	gl_Position =  MVP * vec4(vertexPosition_modelspace,1);

	// Position of the vertex, in worldspace : M * position
	Position_worldspace = (M * vec4(vertexPosition_modelspace,1)).xyz;

	// Vector that goes from the vertex to the camera, in camera space.
	// In camera space, the camera is at the origin (0,0,0).
	vec3 vertexPosition_cameraspace = ( V * M * vec4(vertexPosition_modelspace,1)).xyz;
	EyeDirection_cameraspace = vec3(0,0,0) - vertexPosition_cameraspace;

	// Vector that goes from the vertex to the light, in camera space. M is ommited because it's identity.
	vec3 LightPosition_cameraspace = ( V * vec4(LightPosition_worldspace,1)).xyz;
	LightDirection_cameraspace = LightPosition_cameraspace + EyeDirection_cameraspace;

	// Normal of the the vertex, in camera space
	Normal_cameraspace = ( V * M * vec4(vertexNormal_modelspace,0)).xyz; // Only correct if ModelMatrix does not scale the model ! Use its inverse transpose if not.

	// UV of the vertex. No special space for this one.
	UV = vertexUV;

#version 440 core

// Interpolated values from the vertex shaders
in vec2 UV;
in vec3 Position_worldspace;
in vec3 Normal_cameraspace;
in vec3 EyeDirection_cameraspace;
in vec3 LightDirection_cameraspace;

// Ouput data
out vec4 color;

// Values that stay constant for the whole mesh.
uniform sampler2D myTextureSampler;
uniform mat4 MV;
uniform vec3 LightPosition_worldspace;

void main(){

	// Light emission properties
	// You probably want to put them as uniforms
	vec3 LightColor = vec3(10,10,10);
	float LightPower = 100000.0f;

	// Material properties
	vec4 MaterialDiffuseColor = texture2D( myTextureSampler, UV );
	vec3 MaterialAmbientColor = vec3(.4,.4,.4) * MaterialDiffuseColor.rgb;
	vec3 MaterialSpecularColor = vec3(.2,.2,.2);

	// Distance to the light
	float distance = length( LightPosition_worldspace - Position_worldspace );

	// Normal of the computed fragment, in camera space
	vec3 n = normalize( Normal_cameraspace );
	// Direction of the light (from the fragment to the light)
	vec3 l = normalize( LightDirection_cameraspace );
	// Cosine of the angle between the normal and the light direction,
	// clamped above 0
	//  - light is at the vertical of the triangle -> 1
	//  - light is perpendicular to the triangle -> 0
	//  - light is behind the triangle -> 0
	float cosTheta = clamp( dot( n,l ), 0,1 );

	// Eye vector (towards the camera)
	vec3 E = normalize(EyeDirection_cameraspace);
	// Direction in which the triangle reflects the light
	vec3 R = reflect(-l,n);
	// Cosine of the angle between the Eye vector and the Reflect vector,
	// clamped to 0
	//  - Looking into the reflection -> 1
	//  - Looking elsewhere -> < 1
	float cosAlpha = clamp( dot( E,R ), 0,1 );

	color.rgb =
		// Ambient : simulates indirect lighting
		MaterialAmbientColor +
		// Diffuse : "color" of the object
		MaterialDiffuseColor.rgb * LightColor * LightPower * cosTheta / (distance*distance) +
		// Specular : reflective highlight, like a mirror
		MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance*distance);
	color.a = MaterialDiffuseColor.a;

//ModelMatrix generation

//set newPosition, value used for collision. objVec[i]->rotation is quaternion.
objVec[i]->newPosition = objVec[i]->ObjectToOrbit + (objVec[i]->rotation * ( objVec[i]->origPosition -objVec[i]->ObjectToOrbit));

//translate ModelMatrix. planetRotation is object spin.
objVec[i]->ModelMatrix =   glm::translate( objVec[i]->newPosition) *
                                    glm::rotate(objVec[i]->planetRotation, glm::vec3(0,1,0))* glm::scale(glm::vec3(objVec[i]->Pscale,
                                    objVec[i]->Pscale, objVec[i]->Pscale)) ;
//set light source before sending to GLSL
else if(type == planet)
        lightPos =  ObjectToOrbit;//position of lightsource in world coordinates
        glUniform3f(LightID, lightPos.x, lightPos.y, lightPos.z);

I thought initially I'm messing up the position in worldspace during rotation, and therefore glsl thinks that the planet is rotating in the wrong direction. However, collision, raytracing, and everything else looks accurate, so I'm unsure if that's the issue.


Then, I thought since I'm scaling the object, that perhaps I needed to use the transpose/inverse of the object. But, my implementations of it did not turn out right(it's possible I was doing it incorrectly). I would create a new mat4 for the inverted model matrix, calculate it by "glm::transpose(glm::inverse(ModelMatrix))" and then pass it into GLSL and change the vertex shader to look like:

//T is the transposed/inverted ModelMatrix

Normal_cameraspace = ( V * T * vec4(vertexNormal_modelspace,0)).xyz; 

This is probably the wrong way to do it. Though, I can remove the scaling entirely, negating the need to invert and I still have the lighting on the wrong side.

The problem persists regardless of how I roll/rotate/move the camera.
Edit* I'm leaning towards some sort of ViewMatrix/normals problem. It doesn't appear to be a world-coordinate or rotation problem. It seems to be tied to the ViewMatrix. If I inverse the "Normal_cameraspace" value in the fragment shader, the problem sort of goes away (not really). The light is then correct everywhere except when it's in front or behind the camera, instead of the opposite being true. But, this seems to rule out other problems. I could probably just use a workaround where I inverse the X/Y but not the z-values, but this seems messy, and I'd like to figure out why it's doing this. Am I computing my normals incorrectly in the vertex shader? Though, I should note that rotating or moving the camera left/right/up/down doesn't seem to change anything while in-game, so....iunno.
Anyhow, I'm a little stumped. Anyhow, I would truly appreciate any insights, or even just a pointer to the general direction where I'm going wrong. Let me know if you need any additional information. Thank you in advance smile.png
Here's a picture of the issue. You can see the planet is lit from the wrong side. I'm only passing in one lightsource for each object (the star its rotating around) so the light isn't coming from other places.
And, ugh, please forgive the awfulness of everything tongue.png Values are turned up way high just for testing, there's no flat shading, and the models are all just placeholder still smile.png Also, ignore the lighting on the ship, It's not the problem. I'm not passing in the same information to it at the moment, and its viewmatrix is totally different from the rest of the objects.
Edited by Misantes

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!