how can I restore world coordinates in hlsl by depth value and screen space coordinates?

Started by
1 comment, last by MJP 2 years ago

What I'm going to do is port this(shaders/volumetric.frag · master · Tomas / 100_procent_more_volume · GitLab) code to hlsl.

But here's the problem.

Since the screen coordinate system of dx12 and the screen coordinate system of opengl are different, the contents of the fragmentWorldPos function of the shader are also different, but I'm not sure how to fix the formula.

Here's what I've tried:


float3 PixelWorldPos(float depthValue, int2 pixel)
{
    uint width, height;
    inputTexture.GetDimensions(width, height);
    
    float4 ndcCoords = float4(
        pixel.x / width * 2 - 1,
        pixel.y / height * (-2) + 1,
        depthValue * 2 - 1,
        1.0);

    float4 worldCoords = mul(ndcCoords, gInvViewProj);
    
    return worldCoords.xyz / worldCoords.w;
}

and this is what glsl shader do :

vec3 fragmentWorldPos(float depthValue) {
    vec4 ndcCoords = vec4(
        2.0*(gl_FragCoord.x / screenWidth) - 1.0,
        2.0*(gl_FragCoord.y / screenHeight) - 1.0,
        2.0*depthValue - 1.0,
        1.0);

    vec4 worldCoords = projectionToWorld * ndcCoords;
    return worldCoords.xyz / worldCoords.w;
}

Advertisement

If you are trying to reconstruct position from depth, there are articles on the internet on this topic.

I used a method which involves sending the corners of the viewing frustum to the shaders (I can't post details now).

I think @mjp wrote an article on how to reconstruct position from depth, search around the web.

You do not need to multiple depth by 2 and subtract one for D3D, just leave it as-is before multiplying with the inverse of your ViewProj matrix.. With D3D (and Vulkan) depth is in the [0, 1] range, not the [-1, 1] range used for OpenGL. The rest of what you have looks fine.

This topic is closed to new replies.

Advertisement