Deferred PointLight in view space

I got some problems getting my pointlight to work for my deferred shader.
I’m computing the viewspace position of the pixels from my depth-buffer:

float DepthToZPosition(in float depth) {
    return -cameraRange.x / (cameraRange.y - depth * (cameraRange.y - cameraRange.x)) * cameraRange.y;

linearDepth = DepthToZPosition( depth );

screencoord = vec3(((gl_FragCoord.x/bufferSize.x)-0.5) * 2.0,((-gl_FragCoord.y/bufferSize.y)+0.5) * 2.0  ,linearDepth);
screencoord.x *= -screencoord.z * adjustXY.x;
screencoord.y *= screencoord.z * adjustXY.y;

lightdir = -;

where cameraRange is the Near+Far plane of my camera.
I’m drawing a fullscreen quad, with texcoord [ 0 , 1 ]

When rendering just the length of lightdir/some factor, i get some strange results (i think the depth is not computed correctly, as when i pan the camera towards the ground it is lit (where it shouldn’t), but not where it should…
And also, when rotating the camera on the y-axis the light moves to the left and to the right, but doesn’t stay where it should

In my C++ code:

float top = c->getNearRange() * tan(c->getFOV()*PIOVER180);float right = top * c->getAspectRatio();
glm::vec4 v = (c->getViewMatrix() * getGlobalMatrix()) * glm::vec4(0,0,0,1);

_shader->setVec3(_lightPositionLocation, glm::vec3(v));
_shader->setVec2(_adjustLocation, glm::vec2(right, top));

where globalMatrix is the modelMatrix for the light (usually only translations)

This is the classic “position from depth” problem, and there’s a bunch of stuff our there on the net (just websearch for it). Matt Pettineo for instance has some good blog posts on this. If you don’t want to just re-derive it, compare your solution to what they’re doing.

Here’s one GLSL solution of many: see the PositionFromDepth_DarkPhoton() function listed at the bottom of this forum post: Re: View Space Light Position Moving…. It assumes standard perspective projection and standard 0…1 depth range. widthInv = 1/res.x and heightInv = 1/res.y.

I now implemented your PositionFromDepth- function, but still got the same problem.

The light is positioned directly under the duck.

Here’s my code:

vec3 PositionFromDepth(in float depth)
  vec2 ndc;             // Reconstructed NDC-space position
  vec3 eye;             // Reconstructed EYE-space position
  eye.z = cameraRange.x * cameraRange.y / ((depth * (cameraRange.y - cameraRange.x)) - cameraRange.y);
  ndc.x = ((gl_FragCoord.x * (1.0/bufferSize.x)) - 0.5) * 2.0;
  ndc.y = ((gl_FragCoord.y * (1.0/bufferSize.y)) - 0.5) * 2.0;
  eye.x =  (-ndc.x * eye.z) * adjustXY.x/cameraRange.x;
  eye.y =  (-ndc.y * eye.z) * adjustXY.y/cameraRange.x;
  return eye;

screencoord = PositionFromDepth(depth);
lightdir = -;
lightdirlen = length(lightdir );

And the passed parameters are still the same as from the first post.

float top = c->getNearRange() * tan(c->getFOV()*PIOVER180);float right = top * c->getAspectRatio();glm::vec4 v = (c->getViewMatrix() * getGlobalMatrix()) * glm::vec4(0,0,0,1);  _shader->setVec3(_lightPositionLocation, glm::vec3(v));_shader->setVec2(_adjustLocation, glm::vec2(right, top));

I’m using widthInv = 1/buffersize.x, as I’m rendering a fullscreen-quad in my fullscreen-buffer.

What am I doin wrong?

Maybe you should try this example from the wiki. This formula doesn’t make assumptions about the depth range, and it only makes the minimal assumptions about the nature of your perspective projection matrix.

uniform mat4 persMatrix;
uniform mat4 invPersMatrix;
uniform vec4 viewport;
uniform vec2 depthrange;
vec4 CalcEyeFromWindow(vec3 windowSpace)
        vec3 ndcPos;
        ndcPos.xy = ((2.0 * windowSpace.xy) - (2.0 * viewport.xy)) / ( - 1;
        ndcPos.z = (2.0 * windowSpace.z - depthrange.x - depthrange.y) /
    (depthrange.y - depthrange.x);
        vec4 clipPos;
        clipPos.w = persMatrix[3][3] / (ndcPos.z - (persMatrix[4][3] / persMatrix[3][4])); = ndcPos * clipPos.w;
        vec4 eyePos = invPersMatrix * clipPos;

I haven’t used it, so I can’t promise that it’ll work. But the math seems sound.