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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .