Linearize depth
Asked Answered
N

1

8

In OpenGL you can linearize a depth value like so:

float linearize_depth(float d,float zNear,float zFar)
{
    float z_n = 2.0 * d - 1.0;
    return 2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear));
}

(Source: https://mcmap.net/q/279926/-getting-the-true-z-value-from-the-depth-buffer)

However, Vulkan handles depth values somewhat differently (https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/). I don't quite understand the math behind it, what changes would I have to make to the function to linearize a depth value with Vulkan?

Nineveh answered 29/6, 2018 at 19:56 Comment(1)
see How to correctly linearize depth in OpenGL ES in iOS? that solution is invariant on the projection depth distortion as it bypass projection matrix and perspective division so it is also much much more accurate.Appropriate
E
13

The important difference between OpenGL and Vulkan here is that the normalized device coordinates (NDC) have a different range for z (the depth). In OpenGL it's -1 to 1 and in Vulkan it's 0 to 1.

However, in OpenGL when the depth is stored into a depth texture and you read from it, the value is further normalized to 0 to 1. This seems to be the case in your example, since the first line of your function maps it back to -1 to 1.

In Vulkan, your depth is always between 0 and 1, so the above function works in Vulkan as well. You can simplify it a bit though:

float linearize_depth(float d,float zNear,float zFar)
{
    return zNear * zFar / (zFar + d * (zNear - zFar));
}
Epiphenomenon answered 2/7, 2018 at 13:49 Comment(2)
Great answer! I also wanted to mention for completeness it's possible to rewrite this ever so slightly so it's a little closer to the original. zNear * zFar / (zFar - d * (zFar - zNear)) (by switching zNear - zFar to zFar - zNear, we can then subtract the last part as we do in the snippet from the original question). The two expressions are equivalent, it's just seeing this version helped me see how closely they are related.Kana
I also made this little Desmos example for reference - desmos.com/calculator/3zdxojy1u5. It doesn't plot anything, but it's useful to play around with the sliders and see how the near/far values (or ndc values) are calculated.Kana

© 2022 - 2024 — McMap. All rights reserved.