   per-pixel lighting problems
  I've been having some trouble implementing per-pixel lighting with deferred rendering. The problem seems to be when I move my view position my lighting changes. Here are some screens that will probably show it better than I can explain it:view 1 seems okay but when I rotate the camera down the light fadesThe same happens when you just move the light. link1 link2I'm not really sure what's going on. I suspect it might be computing the fragment's position. I think my light position is okay. (All lighting is done in view space)When filling the gbuffer I store diffuse, normal and distance textures. The distance texture stores a fragment's linear depth.To determine a fragment's position when doing my lighting I use the following information:1. the fragment's depth, stored as linear values between 0 and 1 (1 being the far clipping plane).2. a vector that goes from the view space origin to the far clipping plane. this vector is computed at each corner of the frustum and interpolated before being passed to the fragment shader.The fragment shader can then determine a fragment's position by scaling the incoming view vector by the fragment's linear z position.Any help is much appreciated!Here's my code to do all this:Vertex shader to fill gbuffer:varying vec3 norm;varying float posz;uniform float zfar;void main(){    norm = gl_NormalMatrix * gl_Normal;    gl_TexCoord[0] = gl_MultiTexCoord0;    //right hand coordinate system so negate z    posz = -(gl_ModelViewMatrix * gl_Vertex).z / zfar;    gl_Position = ftransform();}Fragment shader to fill gbuffer:varying vec3 norm;varying float posz;uniform sampler2D tex;void main(){    gl_FragData[0] = vec4(norm*0.5+0.5, 1.0f);    gl_FragData[1] = texture2D(tex, gl_TexCoord[0].xy);    gl_FragData[3] = packFloat(posz);}Vertex shader for lighting:varying vec3 view_vec;void main(){    gl_Position = ftransform();    gl_TexCoord[0] = gl_MultiTexCoord0;    view_vec = gl_Normal; //frustum vectors are passed in as normals}Fragment shader to do lighting:uniform sampler2D dist_tex, normal_tex, diffuse_tex;//light position is stored in xyz and its radius in wuniform vec4 light_pos_rad;uniform vec3 light_col;//interpolated vector to the far clipping planevarying vec3 view_vec;void main(){    vec3 norm = normalize(texture2D(normal_tex, gl_TexCoord[0].xy).rgb - 0.5);    vec3 frag_pos = view_vec * unpackFloat(texture2D(dist_tex, gl_TexCoord[0].xy));    vec3 ldir = light_pos_rad.xyz - frag_pos;    float dist = length(ldir);    ldir = normalize(ldir);    float ndot = dot(norm, ldir);    if(ndot > 0.0)    {   vec3 diffuse = texture2D(diffuse_tex, gl_TexCoord[0].xy).rgb;   float atten = clamp(1.0 - dist/light_pos_rad.w, 0.0, 1.0);   vec3 color = atten * (light_col * diffuse * ndot);   gl_FragColor = vec4(color, 1.0);    }    else   discard;}Application code to compute the frustum vectors:    vec3 frustum_vecs[4];    float ratio = (float)render->getWidth() / (float)render->getHeight();    float fary = tan(render->getFOV() / 2.0f) * render->getZFar();    float farx = fary * ratio;    float farz = -render->getZFar();    //top left    frustum_vecs[0].x = -farx;    frustum_vecs[0].y = fary;    frustum_vecs[0].z = farz;    //bottom left    frustum_vecs[1].x = -farx;    frustum_vecs[1].y = -fary;    frustum_vecs[1].z = farz;    //bottom rightfrustum_vecs[2].x = farx;    frustum_vecs[2].y = -fary;    frustum_vecs[2].z = farz;    //top right    frustum_vecs[3].x = farx;    frustum_vecs[3].y = fary;    frustum_vecs[3].z = farz;For now I render a fullscreen quad on each lighting pass. This is rendered using an 2D orthographic projection with the origin at the top left of the window. I pass in the frustum vectors as normals to my shader. GL_TEXTURE0 is my linear depth buffer.   Matrix4 lview_mat = l->getTransform() * view_matrix;   vec3 vpos = lview_mat.toTranslationVec();   float pos[] = {vpos.x, vpos.y, vpos.z, 100.0f}; //light radius in w component   glUniform4fv(shaders[SHADER_LIGHT].uniforms["light_pos_rad"], 1, pos);   float x = 0.0f, y = 0.0f, width = render->getWidth(), height = render->getHeight();   glBegin(GL_QUADS);  //top left  glMultiTexCoord2f (GL_TEXTURE0, 0.0f, 1.0f);  glNormal3fv(&frustum_vecs[0][0]);  glVertex3f(x, y, 0.0f);  //bottom left  glMultiTexCoord2f (GL_TEXTURE0, 0.0f, 0.0f);  glNormal3fv(&frustum_vecs[1][0]);  glVertex3f(x, y+height, 0.0f);  //bottom right  glMultiTexCoord2f (GL_TEXTURE0, 1.0f, 0.0f);  glNormal3fv(&frustum_vecs[2][0]);  glVertex3f(x+width, y+height, 0.0f);  //top right  glMultiTexCoord2f (GL_TEXTURE0, 1.0f, 1.0f);  glNormal3fv(&frustum_vecs[3][0]);  glVertex3f(x+width, y, 0.0f);   glEnd();