View Full Version : Deferred PointLight in view space

04-18-2013, 05:34 AM
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 = screencoord.xyz - lightPosition.xyz;

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)

Dark Photon
04-18-2013, 09:20 AM
I'm computing the viewspace position of the pixels from my depth-buffer... i get some strange results (i think the depth is not computed correctly

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... (http://www.opengl.org/discussion_boards/showthread.php/173019-View-Space-Light-Position-Moving?p=1212628&viewfull=1#post1212628). It assumes standard perspective projection and standard 0..1 depth range. widthInv = 1/res.x and heightInv = 1/res.y.

04-22-2013, 04:09 AM
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 = screencoord.xyz - lightPosition.xyz;
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?

Alfonse Reinheart
04-22-2013, 04:59 AM
Maybe you should try this example from the wiki (http://www.opengl.org/wiki/Compute_eye_space_from_window_space#From_XYZ_of_gl _FragCoord). 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)) / (viewport.zw) - 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]));
clipPos.xyz = 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.