I have implemented a simple Phong shader without specular highlights for now (just ambient + diffuse components)

The problem however, is that the calculations seem to be done in camera space; as I move the camera around, the light source seems to move along with it. This is evident by me not being able to see the dark side of the models

(Note: Image is a gif, if it is not animating, open in a new tab) Light following around gif

My light is a point light, that I would like to have fixed somewhere in the world. It has a defined position. To my shader, I also pass in the M, V, P matrices, as well as the normal matrix, which is the inverse transpose of the MV matrix

glm::vec3 cameraDirection=glm::normalize(cameraPosition-cameraTarget);
cameraRight=glm::cross(cameraDirection, cameraUp);
view=glm::lookAt(cameraPosition, cameraTarget, cameraUp);
glm::mat4 model_view = view * modelMatrix;
glm::mat4 normal_matrix = glm::transpose(glm::inverse(model_view));

The following is my shader code

attribute vec3 vertex_position;
attribute vec3 vertex_colour_in;
attribute vec3 vertex_normal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 normal_matrix;
uniform vec3 ambient_light_colour_in;
uniform vec3 light_position_in;

varying vec4 fragment_colour;

void main(void){
  gl_Position = projection * view * model * vec4(vertex_position, 1.0);

  //ambient colour
  vec3 ambient_colour = ambient_light_colour_in * vertex_colour_in;

  //diffuse colour
  vec3 normal = normalize(vec3(normal_matrix * vec4(vertex_normal, 0.0)));
  vec4 pos4 = view * model * vec4(vertex_position, 1.0);
  vec4 lightPos4 = vec4(light_position_in, 1.0);
  vec3 lightDirection = normalize((lightPos4 - pos4).xyz);
  vec3 diffuse_colour = vertex_colour_in * max(0.0, dot(normal, lightDirection));

  fragment_colour.rgb = ambient_colour + diffuse_colour;

As far as I understand, the problem is that these lighting calculations are done in Camera space, and hence change when the camera changes position. So, my question is How would I change that to get the light to be at a fixed position, ie: do the light calculations in World space


You're multiplying your vertex position and normal by the view matrix, change it to only use the model matrix.

vec4 pos4 = model * vec4(vertex_position, 1.0);

Change the normal_matrix to just be the inverse transpose of the model matrix only.

glm::mat4 normal_matrix = glm::transpose(glm::inverse(modelMatrix));
  • \$\begingroup\$ I removed the view multiplication, but it is still having the same behaviour \$\endgroup\$ – codemonkey Mar 23 '14 at 20:17

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.