I have for a long time put off fixing up the lighting in a project i am working on in OpenTK. The problem basically is that when i rotate the camera, lighting displayed on the terrain i am showing also rotates.
Here’s a snippet of my onRenderFrame code:
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
float dist = (float)Math.Sin(Math.PI / 3) * camZoom;
Matrix4 view = Matrix4.LookAt(new Vector3(-(float)Math.Cos(camRot) * dist, dist, -(float)Math.Sin(camRot) * dist) + camPos, camPos, new Vector3(0, 1, 0));
//Note: camPos isn't actually the position of the camera, rather the target of it. The actual camera position is calculated above.
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref view);
float tx = 50;
float ty = 20;
float tz = -15;
GL.Light(LightName.Light0, LightParameter.Position, new float[] { tx, ty, tz});
GL.Begin(BeginMode.Lines);
DrawBox(tx - 2, tx + 2, ty - 2, ty + 2, tz - 2, tz + 2);
GL.End();
… Drawing of terrain is here
I used my quick DrawBox function to draw a simple box around the location of the light. It is working fine, i even implemented some movement such as a sun around the earth. While the camera hadn’t been moved, this was working great. But once i turned the camera, the lighting no longer showed what it should have, it seemed to have ‘moved’ the light, without actually moving it (the box drawn wasn’t moved, only the effect of the light).
According to the OpenGL spec for glLight with the GL_POSITION parameter:
You only pass in three floats. I can’t be certain what OpenTK uses as the fourth (w) component, but I would guess it makes any unspecified parameters 0, thereby making your light directional and ignoring the position you give. I would try adding a 1.0 to the end of the array you pass in and see if that fixes things.