Light in world coordinates

Hi,

I’m in the middle of creating a game which uses lighting (1 light, per fragment, ambient + diffuse for now) (I follow giles’ lessons: http://learningwebgl.com/blog/?page_id=1217).
I have camera which is set in well known way in every frame:

var lightPos = [50, 100, 0];
var frame = function() {
  ...
  loadIdentityMV();
  camera.lookAt(cameraPos, cameraTarget, cameraUp);
  // light
  gl.uniform3fv(ambientColorLoc, ambientColor);
  gl.uniform3fv(lightColorLoc, lightColor);
  gl.uniform3fv(lightPosLoc, lightPos));
  ...
}

Here are shaders’ code

/* vertex shader */
uniform mat4 uMVMatrix;
uniform mat4 uProjMatrix;
uniform mat4 uNormalMatrix;

attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;

varying vec2 vTextureCoord;
varying vec4 vPosition;
varying vec4 vNormal;

void main(void) {
    vPosition = uMVMatrix * vec4(aVertexPosition, 1.0);
    gl_Position = uProjMatrix * vPosition;
    vTextureCoord = aTextureCoord;
    vNormal = uNormalMatrix * vec4(aVertexNormal, 1.0);
}
/* fragment shader */
#ifdef GL_ES
precision highp float;
#endif

uniform vec3 uAmbientColor;
uniform vec3 uLightPos;
uniform vec3 uLightColor;
uniform sampler2D uSampler;

varying vec2 vTextureCoord;
varying vec4 vPosition;
varying vec4 vNormal;

void main(void) {
   vec3 lightDirection = normalize(uLightPos - vPosition.xyz);
   float diffuseFactor = max(dot(normalize(vNormal.xyz), lightDirection), 0.0);
   vec3 lightFactor = uAmbientColor + uLightColor * diffuseFactor;

    vec4 texColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
    gl_FragColor = vec4(texColor.rgb * lightFactor, texColor.a);
}

I don’t change light’s position, so it’s always expressed in eyes coordinates, right (or am I wrong)? Therefore when camera moves / rotates then the light follows the camera what is not what I want - in my case (and in 99% other games / apps) light should stay in one place (in world coordinates) independently to the camera.
So how (and when) to transform light’s position to have it in the world coordinates?
Is it multiplying lightPos by mvMatrix just after camera.lookAt(pos, target, up) ?

Thanks,
wglb (gliniak)

I am not sure the contents of your Camera code but typically Camera Views work backwards to how it appears they work. Normally the Camera is actually stationary and the rest of the world is shifted.

I am guessing that your Camera code does not shift the Light Source with the rest of the world and that is why the Light Source seems to follow the camera.

Let me see if I can clarify that a bit more. Your camera view shows the origin (0,0,0). When you move the camera say one in the X direction, what actually happens is that camera code moves the world (all objects) one in the negative X direction. This makes it look like the camera moved but actually the world moved. So consider that you have a Light Source that lights the origin (0,0,0). When the camera is moved, the camera code moves the world but forgets to move the light (at least this would be my guess). The world shifts one in the negative x direction to make it look like the camera moved. Since the camera code did not move the Light Source it still remains over the origin (0,0,0) thus making it look like the Light Source actually moved…but it did not.

To fix this, you would need to edit the camera.lookAt code. I am sure you will find that this basically ends up moving the world. In this code you need to make a modification which also adjusts the location of the Light Source.

BTW, also keep in mind that the lighting in Lesson 12 is fairly simplistic. It does not drop of over distance and does not get blocked by objects (since it just takes the angle between the fragment and the light source). As such if, for example, you put a second crate, in Lesson 12, just beyond the first crate (with respect to the light source) you would expect the second crate to be dark (being blocked by the first crate) but it will not display that way. It is still a great tutorial but if you are serious about lighting effects then you need to look at the more advanced examples (I have not yet had time to look at the other examples).