openGL -将非线性深度缓冲转换为线性深度缓冲

vdgimpew  于 2022-12-12  发布在  其他
关注(0)|答案(1)|浏览(128)

According to the thread on this page,用于计算深度缓冲器的公式:

F_depth = 1/z - 1/n/(1/f - 1/n)

是非线性的,因为透视分割。(请注意,这是从视图空间z坐标到窗口坐标的直接组合)
所以,根据我的理解:
要将其转换为线性深度缓冲区,我们唯一要做的就是删除透视除法(?),然后执行此处给出的glDepthRange(a,b)
在这种情况下,方程式如下:

z_linear = z_NDC * W_clip = -(f+n)/(f-n)*z_eye + ( 2fn/(f-n) )

以及,利用深度范围变换:

z_[0,1] = ( z_linear + 1 ) /2
= ( (f+n)*z_eye - 2fn + f - n )/ ( 2(f-n) )

但是在learnopenGL site for depth testing中,这样做:
首先,我们将深度值转换为NDC,这并不太困难:

float ndc = depth * 2.0 - 1.0;

然后,我们取所得的ndc值并应用逆变换来检索其线性深度值:

float linearDepth = (2.0 * near * far) / (far + near - ndc * (far - near)

如何计算非线性到线性深度缓冲区?(即形成方程)?

r8uurelv

r8uurelv1#

在右手系统中使用glm,我发现了以下从ndc深度[-1,1]转换为眼睛深度[0-far]的解决方案。
透视投影:

float screen_to_eye_depth_perspective(float d, float zNear, float zFar)
{
    // [0; 1] -> [-1; 1]
    float depth = d * 2.0 - 1.0;
    return  (2.0 * zNear * zFar) / (zFar + zNear - depth * (zFar - zNear));
}

正投影:

float screen_to_eye_depth_ortho(float d, float zNear, float zFar)
{
    // [0; 1] -> [-1; 1]
    float depth = d * 2.0 - 1.0;
    return (depth * (zFar - zNear) + (zFar + zNear)) / 2.0;
}

我建议你用自己的远近值来测试,以检查最终的结果。

n = 10;
f = 100;
// -------------
z = 2 * f * n  / (f + n) - ndc * (f - n);
z = 2000 / (110 - ndc * 90);
// -------------
ndc = -1;
z = 2000 / (110 + 90) = 10;
ndc = 1;
z = 2000 / (110 - 90) = 100;

相关问题