Reconstruction of world position from depth (SDL3 GPU) [Solved]

Firs time poster, long time user!. :slight_smile:

I am banging my head against this bug in my project. I am using SDL3 GPU to write a deferred renderer and try to reconstruct the world positions in the scene from the depth pass. However, I can not get it to work.

Here is the albedo of the scene for reference:

KPV8ODF.th.png

Here is the raw depth, original world positions and the reconstructed world positions from the depth visualised:

KPV8wAP.th.png KPV8NN1.th.png KPV8jHB.th.png

Using this shader code to reconstruct the world positions:

// Reconstruct position from depth value
float3 ReconstructPosition(float2 texCoord, float depth, float4x4 invViewProj) {
    // Convert to NDC
    float4 clipSpace = float4(
        texCoord.x * 2.0 - 1.0,
        texCoord.y * 2.0 - 1.0,
        depth,
        1.0
    );
    
    // Transform to world space
    float4 worldSpace = mul(invViewProj, clipSpace);
    
    // Perspective divide
    return worldSpace.xyz / worldSpace.w;
}

As you can see above the reconstruction did not work. The original and reconstructed world position visualisations should be the same if correct.

Anyone got a clue where it goes wrong?

So after some step by step visual debugging I finally figured out what was wrong. Here is the updated code:

// Reconstruct position from depth value
float3 ReconstructPosition(float2 texCoord, float depth, float4x4 invViewProj) {
    // Convert to NDC
    float4 clipSpace = float4(
        texCoord.x * 2.0 - 1.0,
        1.0 - texCoord.y * 2.0,  //< Fixed here to flip the Y
        depth,
        1.0
    );

    // Transform to world space
    float4 worldSpace = mul(clipSpace, invViewProj); //< Reversed the order of multiplication
    
    // Perspective divide
    return worldSpace.xyz / worldSpace.w;
}

After flipping the Y and reversing the order of multiplication I got a satisfying result:

KsK7Hj2.th.png

There is a thread on Mastodon of me trying to figure it out.