Moving a Light Source

Hello all,

I’ve been browsing the forums for a while and I’ve found some useful stuff, so I thought I’d ask a few questions of my own.

My first question pertains to how I would go about moving a light source. I want the camera position to stay constant, but I’d like to be able to use the keyboard to move where the light is shining from and update my shading accordingly. Here’s how I’m currently doing it, to no avail:
I have a handler in my main source file which takes three vertices where the light should be positioned.


//from main

//declaring the handler
GLint h_aLight;

//globals for light position
float lightX = 5;
float lightY = 5;
float lightZ = 5;

//inside my function to install the shaders
h_aLight = safe_glGetAttribLocation(ShadeProg, "aLight");

//inside my draw function, after I've done the appropriate model transforms
//set the light position in the shader
      glUniform3f(h_aLight, lightX, lightY, lightZ);

I’m not worrying about applying the transforms yet, I know I need to multiply the model matrix by the normals, but that’s a problem for later. Those values are passed off to a variable in my vertex shader, which is used to calculate the direction of the light by created by subtracting the position of the object from the points passed to my light handler to create a vector.


//vertex shader

//declaring the variable
varying vec3 lightPos;

void main(){
//...

//creating the vector
lightPos = vec3(aLight.x - vPosition.x, aLight.y - vPosition.y, aLight.z - vPosition.z);

//shading calculations based on the light vector
}

Because my light direction is updated here and all the shading calculations are done AFTER this point, I would assume that updating the values passed to the light handler would result in a new light direction vector that my calculations would use for brand new calculations. However, I don’t see any difference in the picture at all. I make sure that the global variables are getting updated with a printf() right after glUniform3f(h_aLight, lightX, lightY, lightZ); that displays the values of lightX, lightY, and lightZ.

Any help would be appreciated :slight_smile:

Your light is just a uniform. The light position will not change unless you transform it. The specified light position will be in the space in which you use it for your relative position.

In your case you are calculating your light position in object space.

If you want your light to be in world space relative to the object then transform vPosition through the object matrix first.

If you want eye space then transform vPosition through the modelview.

A common convention if to transform vPosition through your modelview matrix and to manually transform your light into eyespace in your application. This matches OpenGL’s fixed function pipeline convention but does not impose a split modelview matrix nor a retransformation of the light per vertex.

So:

  1. transform light to eyespace then set the light position uniform.
  2. calculate the modelview matrix and specify it as a uniform matrix
  3. in the vertex shader transform vPosition through the modelview matrix THEN perform the lighting relative position subtraction.

[QUOTE=dorbie;1244212]

  1. transform light to eyespace then set the light position uniform.
  2. calculate the modelview matrix and specify it as a uniform matrix
  3. in the vertex shader transform vPosition through the modelview matrix THEN perform the lighting relative position subtraction.[/QUOTE]

I’ve already done steps 2 and 3. In my shader I already have three uniform matrices declared, the ModelMatrix, ViewMatrix, and ProjectionMatrix.


//declaring the matrices in my VS
uniform mat4 uProjMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uModelMatrix;

//inside main
vPosition = uModelMatrix* vec4(aPosition.x, aPosition.y, aPosition.z, 1);
vPosition = uViewMatrix* vPosition;

It’s after this that I do the subtraction to get the light vector. I feel like my only problem is transforming light to eyespace. Following what it sounded like you were saying, I transformed light to eyespace in my main source file. I multiplied it by the ModelView to get it in eyespace in the same manner as vPosition.


//in my main source file

//globals for light position
float lightX = 5;
float lightY = 5;
float lightZ = 5;
float homo = 0;
glm::vec4 eyeLight = glm::vec4(lightX,lightY,lightZ, homo);
glm::mat4 ModelMat; //holds value of ModelMatrix
glm::mat4 ViewMat; //holds value of ViewMatrix
glm::mat4 ProjMat; //holds value of ProjectionMatrix

//in my draw function, after model transforms, but before i pop the matrix
//set the light position in the shader
      eyeLight = ModelMat * eyeLight;
      eyeLight = ViewMat * eyeLight;
      glUniform4f(h_aLight, eyeLight[0], eyeLight[1], eyeLight[2], eyeLight[3]);

Now lighting kinda works… it at least responds to where I initially set it. If I move the camera or try to rotate the object, the lighting changes, but it looks like it circulates between 5 different stages of light movement before it starts the loop over, no matter how I move the object. Another issue I notice is that no matter how I move the camera, whether it’s in a circle or just forward or backward, this loop continues. This problem also happens when I simply translate or scale the object. Also, I still can’t change the position of the light using key presses like I wanted :frowning:

After a bunch of reading, I figured it out, and it now works as intended :slight_smile:

The problem was just that I was doing the transformation to eyespace inside my main source file rather than my shader…and to think I originally thought I needed to calculate it in the shader anyway.

Thanks for the help!