First, I will describe the inputs:
- winPos - Pixel position (from gl_FragCoord.xy).
- winSize - Size of window in pixels.
- depthSample - Raw depth value from the depth texture (should be in the range of [0, 1]).
- nearFar - Distances of the near and far planes.
- u_top, u_right - Top and right limits of the near plane.
For u_top and u_right, I derive it from my vertical field of view angle and aspect ratio (width / height) like so (C++):
m_top = m_near * Math::tan(0.5f * m_verticalFov);
m_right = m_top * m_display->aspectRatio();
Given all that, here is the GLSL function that will return the view space position for the given pixel position:vec3 viewSpacePos(vec2 winPos, vec2 winSize, vec4 depthSample, vec2 nearFar)
{
vec3 position;
float depth = depthSample.x;
position.z = -nearFar.x / (nearFar.y - (depth * (nearFar.y - nearFar.x))) * nearFar.y;
position.x = (((winPos.x / winSize.x) * 2.0) - 1.0) * u_right;
position.y = (((winPos.y / winSize.y) * 2.0) - 1.0) * u_top;
float scale = -position.z / nearFar.x;
position.x *= scale;
position.y *= scale;
return position;
}
Hope this helps someone out there! It might be best you try derive it yourself too, so you can debug it (if you ever need to)... :)UPDATE: Made small correction to how scale was calculated. Oops!