Unity3D Linear01Depth & LinearEyeDepth 函数深度解析

UnityCG.cginc中原函数如下:

// Z buffer to linear 0..1 depth (0 at eye, 1 at far plane)
inline float Linear01Depth( float z )
{
return 1.0 / (_ZBufferParams.x * z + _ZBufferParams.y);
}
// Z buffer to linear depth
inline float LinearEyeDepth( float z )
{
return 1.0 / (_ZBufferParams.z * z + _ZBufferParams.w);
}
其中_ZBufferParams的定义如下:
double zc0, zc1;
// OpenGL would be this:
// zc0 = (1.0 - m_FarClip / m_NearClip) / 2.0;
// zc1 = (1.0 + m_FarClip / m_NearClip) / 2.0;
// D3D is this:
zc0 = 1.0 - m_FarClip / m_NearClip;
zc1 = m_FarClip / m_NearClip;
// now set _ZBufferParams with (zc0, zc1, zc0/m_FarClip, zc1/m_FarClip);

参考资料链接:http://forum.unity3d.com/threads/_zbufferparams-values.39332/

经过透视投影变换时,Z值的计算方式如下:
Z’ = f*n/[(n-f)*z] + f/(f-n);
可以简单的理解为将z值的倒数进行插值计算,映射到[0, 1](d3d)空间中。
将上式带入Linear01Depth中,可得最后计算结果为z/f;
就是说,是将[0, f]映射到[0, 1]空间,若要映射[n, f]到[0, 1]则是(z-n)/(f-n)。
将上式带入LinearEyeDepth中,可得最后计算结果为z。很明显,LinearEyeDepth是将经过透视投影变换的深度值还原了。
至于在透视投影变换中为什么要用公式Z’ = f*n/[(n-f)*z] + f/(f-n);这个说起来比较麻烦,简单来说是为了将深度值映射到[0, 1]空间方便裁剪,以及x’和y’与1/z成线性关系(这是为了光栅化时的透视纹理映射所做的准备),读者可以参考下面链接http://wenku.baidu.com/link?url=GoxRM0e3Neo121CPWVdh7RRYZpN1Gj7xkfNeGxNN92bo-RULSAyEZv_odGdrteg8sBUd7MuX2ihlrBaAcqxRwVop-S3DI2pkKL5rBXlrTvO
注意链接中是以Opengl作为例子进行讲解,其z值的映射空间为[-1, 1]。
关于为什么x’要与1/z成线性关系可参考下面链接:http://blog.csdn.net/popy007/article/details/5570803

你可能感兴趣的:(Unity3D Linear01Depth & LinearEyeDepth 函数深度解析)