UNITY_REVERSED_Z

HLSLSupport.cginc

#if defined(SHADER_API_D3D11) || defined(SHADER_API_PSSL) || defined(SHADER_API_XBOXONE) || defined(SHADER_API_METAL) || defined(SHADER_API_VULKAN) || defined(SHADER_API_SWITCH)
// D3D style platforms where clip space z is [0, 1].
#define UNITY_REVERSED_Z 1
#endif

在这里插入图片描述

在这里插入图片描述
摄像机:
在这里插入图片描述
投影矩阵:
在这里插入图片描述
程序输出:

Matrix4x4 proj = Camera.main.projectionMatrix;
Debug.LogError(proj);

在这里插入图片描述

Matrix4x4 proj = Camera.main.projectionMatrix;
Debug.LogError(proj);
Matrix4x4 view = Camera.main.worldToCameraMatrix;
Debug.LogError(proj * view);

在这里插入图片描述
在这里插入图片描述
不同,所以执行了:GL.GetGPUProjectionMatrix(proj, false);

Matrix4x4 proj = Camera.main.projectionMatrix;
Debug.LogError(proj);
Matrix4x4 view = Camera.main.worldToCameraMatrix;
Matrix4x4 proj2 = GL.GetGPUProjectionMatrix(proj, false);
Debug.LogError(proj2 * view);

在这里插入图片描述
反推矩阵红色矩阵:

在这里插入图片描述

Matrix4x4 proj = Camera.main.projectionMatrix;
Matrix4x4 view = Camera.main.worldToCameraMatrix;
Matrix4x4 proj2 = GL.GetGPUProjectionMatrix(proj, false);
Matrix4x4 D = proj2 * view;
Matrix4x4 m = proj.inverse * D * view.inverse;
Debug.LogError(m);

在这里插入图片描述
最终推导出这个矩阵为:
在这里插入图片描述
在这里插入图片描述
ok,这就推出了,对于透视矩阵的中变化的红色矩阵了。和正交投影有区别。

然后就是和unity的shader中对应起来:

// Z buffer to linear depth
inline float LinearEyeDepth( float z )
{
    return 1.0 / (_ZBufferParams.z * z + _ZBufferParams.w);
}

_ZBufferParams的定义:

   // Values used to linearize the Z buffer (http://www.humus.name/temp/Linearize%20depth.txt)
    // x = 1-far/near
    // y = far/near
    // z = x/far
    // w = y/far
    // or in case of a reversed depth buffer (UNITY_REVERSED_Z is 1)
    // x = -1+far/near
    // y = 1
    // z = x/far
    // w = 1/far
    float4 _ZBufferParams;

我们看的是or in case of a reversed depth buffer (UNITY_REVERSED_Z is 1)的情况:
所以LinearEyeDepth( float z ):
1.0 / (_ZBufferParams.z * z + _ZBufferParams.w);
带入之后,就和我们验算完全相同,got it。

扫描二维码关注公众号,回复: 10275055 查看本文章

在这里插入图片描述
如果是:

inline float Linear01Depth( float z )
{
	return 1.0 / (_ZBufferParams.x * z + _ZBufferParams.y);
}

在这里插入图片描述
则直接再除以最远的f即可,如上式。
而此时:

// or in case of a reversed depth buffer (UNITY_REVERSED_Z is 1)
// x = -1+far/near
// y = 1
// z = x/far
// w = 1/far
float4 _ZBufferParams;

带入x和y,正好和上式子吻合。到此,我们知道了这两个函数:Linear01Depth和LinearEyeDepth的推导全过程。
很有帮助。
总结:顶点着色器中,转换到的只是裁剪空间坐标,不是NDC坐标,在顶点着色器之后,片段着色器之前,硬件自动进行透视除法。
而保存在深度缓存中的深度,则是经过透视除法之后的深度,如果传入的透视矩阵没有z反转的话,则是在-1到1(opengl中),dx则是(0到1),而过经过反转,无论是dx还是opengl则是存储的是经过反转,还经过透视除法之后的深度值。
这点务必搞清楚,否则对这个深度理解不透彻,直接影响后处理等利用深度做文章的效果。

发布了646 篇原创文章 · 获赞 107 · 访问量 36万+

猜你喜欢

转载自blog.csdn.net/wodownload2/article/details/104874098
z
今日推荐