Clip to world space using depth
Operating System: Windows 10
Render System: Direct3D11
Hello!
I have had a bit of trouble converting depth value to a world position in a shader, I have attempted to do it for 30+ hours now without success.
This problem literally haunts my dreams.
The depth buffer itself is fine, since I am using it for many other shaders. Visualizing it shows nothing wrong with it.
The compositor shader I am using is trying to convert a UV coordinate to a world position using the depth of the UV.
I want it to be able to sample any pixel on the screen and be able to get that pixels world position, even if that pixel is not the current one.
All solutions I have found on this forum is by doing a vertex texcoord that holds the corner of the quad, but that only works for the current pixel in the pixel shader (because interpolations of the texcoord only do that specific pixel).
Correct me if I am wrong, but that means that it is impossible to calculate a world space position for other pixels than the one that was sent in using a different UV, using that clever vertex shader technique.
The named constants I am sending into the shader gets updated. I set them for both the base material and the copy of the material that the compositor creates internally.
How I know that they are getting updated is because half of the frames I set a value to multiply the output pixel color by either 0 or 1, which makes the entire screen flash, which works.
Since you cannot get matrices from the "param_named_auto" for compositors, I do it myself in code by doing something like this (I have tried more than 50 different kind of ways of calculating all the matrices):
Code: Select all
Affine3 tmpView = m_Camera->getViewMatrix(true);
if (m_SceneManager->getCameraRelativeRendering()) // I toggle this each attempt to see if it works or not
tmpView.setTrans(Vector3::ZERO);
Affine3 tmpInvView = tmpView.inverse();
gpuParam->setNamedConstant("invView", tmpInvView);
Code: Select all
float clipDistance = cFarClipDistance - cNearClipDistance;
return float4((length(iViewPos) - cNearClipDistance) / clipDistance, 1, 1, 1);
From what I have read, it seems to be something like this:
Code: Select all
float3 WSPositionFromDepth(float2 uv, float depth)
{
float4 clipSpacePosition = float4(uv.x * 2.0 - 1.0,
(1.0 - uv.y) * 2.0 - 1.0,
depth, // Sending in "sSceneDepthSampler.Sample(sSceneDepthSampler_state, uv).r"
1.0); // I have tried the depth with and without "* 2.0 - 1.0" also
float4 viewSpacePosition = mul(invProj, clipSpacePosition);
//viewSpacePosition.xyz /= viewSpacePosition.w; // I tried it with and without this in many attempts
float4 worldSpacePosition = mul(invView, viewSpacePosition);
return worldSpacePosition.xyz;
}
After a while I tried to skip matrices as far as I could and came up with this (with inspiration of the vertex texcoord solution):
Code: Select all
float3 ray = lerp(topLeftCorner, bottomLeftCorner, fragmentTC.y);
ray = lerp(ray, float3(topRightCorner.x, ray.y, ray.z), fragmentTC.x);
ray = normalize(ray);
//ray = mul(view, float4(ray, 1)); // I tried it with and without this in many attempts
float3 worldSpacePosition = cameraPosition + // cameraPosition is sent in manually in world space, no auto param
(ray * (sSceneDepthSampler.Sample(sSceneDepthSampler_state, fragmentTC).r * clipDepth));
I converted my shader code to Direct3D11 to be able to use the Visual Studio 2017 Graphics Debugging, and I have been debugging the shader code quite a lot, which helps, but I have still not succeeded even with that help.
I realize that the easy way would be to use a position buffer, but I really do not want to do that as I already have the depth buffer which should (?) be sufficient to get world positions.
I also realize that I can make my calculations in view-space instead, but at this point I just do not understand why it is so complex to convert a clip space/screen space position to a world position.
Has anyone else encountered this problem and fixed it?
Any input would be helpful at this point.
Some posts that has similar problems but still did not help me:
viewtopic.php?t=92173
viewtopic.php?t=42835
viewtopic.php?f=2&t=78348
viewtopic.php?f=2&t=72294
https://stackoverflow.com/questions/322 ... ffer-value
https://www.gamedev.net/forums/topic/47 ... rom-depth/
https://mynameismjp.wordpress.com/2009/ ... rom-depth/