Reconstructing Position From Depth
Matt posted an excellent article about reconstructing position from depth. Check out his article here: http://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/
He has the following function to reconstruct View Space Position from Post Clip Space Position:
// Function for converting depth to view-space position // in deferred pixel shader pass. vTexCoord is a texture // coordinate for a full-screen quad, such that x=0 is the // left of the screen, and y=0 is the top of the screen. float3 VSPositionFromDepth(float2 vTexCoord) { // Get the depth value for this pixel float z = tex2D(DepthSampler, vTexCoord); // Get x/w and y/w from the viewport position float x = vTexCoord.x * 2 - 1; float y = (1 - vTexCoord.y) * 2 - 1; float4 vProjectedPos = float4(x, y, z, 1.0f); // Transform by the inverse projection matrix float4 vPositionVS = mul(vProjectedPos, g_matInvProjection); // Divide by w to get the view-space position return vPositionVS.xyz / vPositionVS.w; }The basic idea is that if we have a matrix that transfoms from View Space to Clip Space, we just take the inverse of that matrix and multiply it with the clip space position we should be able to get back the view space position. But my biggest question was why did we need to divide-by-w (in view space) at the end? I thought the order is like this:
PosInClipSpace = PosInViewSpace * ProjMtx; PosInPostClipSpace = PosInClipSpace / PosInClipSpace.w;so, if we want to get back from PosInPostClipSpace to PosInViewSpace, we need to do this:
PosInClipSpace = PosInPostClipSpace * PosInClipSpace.w; PosInViewSpace = PosInClipSpace * ProjMtx_INVERSE;so, somehow we need to save the w in order to get back the position in View Space. Out of curiosity, I did the Inverse of Projection Matrix MANUALLY and work out the following:
PosInViewSpace0 = PosInPostClipSpace * ProjMtx_INVERSE; PosInViewSpace = PosInViewSpace0 / PosInViewSpace0.w;It turns out the MATH WORKS OUT! I can't see why this is happening logically, but mathematically it's correct! It's amazing, I learned a new thing today! My next question is, if I want to bring it to World Space instead of View Space, do I need 2 matrix multiplication steps such as the following:
PosInViewSpace0 = PosInPostClipSpace * ProjMtx_INVERSE; // First Mtx Mult PosInViewSpace = PosInViewSpace0 / PosInViewSpace0.w; PosInWorldSpace= PosInViewSpace * ViewMtx_INVERSE; // Second Mtx MultIt turns out, I don't need that. I can just multiply with ViewProjMtx_INVERSE and divide-by-w at the end, i.e.:
PosInWorldSpace0 = PosInPostClipSpace * ViewProjMtx_INVERSE; PosInWorldSpace = PosInWorldSpace0 / PosInWorldSpace0.w;This works because if you pay attention to ViewMtx_INVERSE, the fourth column is actually (0, 0, 0, 1) which basically doesn't modify the w. That's why you can do divide-by-w at the end and still get the correct result!
Comments