深度
在unity当中所有的不透明物体都需要使用深度(Zbuffer)做深度剔除:ZWtire ZTest
深度信息保存在一张高精度的纹理当中。
Note: On DX11/12, PS4, XboxOne and Metal, the Z buffer range is 1–0 and UNITY_REVERSED_Z is defined. On other platforms, the range is 0–1.(在一些平台,深度纹理从近到远是从1到0,并且定义了一个宏UNITY_REVERSED_Z ,在其他平台是从0到1)
当shader打开ZWrite的时候,默认会 向Zbuffer写入内容,会通过特殊的编码,保证近处的精确度更高。范围在[0,1]之间。描述了远近剪裁面之间。
注:有一个Linear01Depth宏,他会把深度从Zbuffer中的非线性[0,1](或[1,0])变成线性的[0,1].
COMPUTE_EYEDEPTH(i):宏会计算观察空间的坐标,实际上就是观察空间的z值(原本是负数,输出之前进行了取反操作)输出到i。(只能在顶点程序中使用,内部使用的顶点shader的输入变量v.vertex)。
COMPUTE_DEPTH_01: 这个宏的结果就是一个0到1的深度变化,等于上一个宏 * _ProjectionParam.w(1/ far)。(也就是除了个远剪裁面)
上面两个宏,针对的是当前顶点的局部坐标(v.vertex).
LinearEyeDepth(i): 将Zbuffer(深度贴图)中的值转换到观察空间。
Linear01Depth(i):将深度贴图的值转化到线性01范围。
上面两个宏对应的是从深度贴图提取出来的值。
注:_ProjectionParams x
is 1.0 (or –1.0 if currently rendering with a flipped projection matrix), y
is the camera’s near plane, z
is the camera’s far plane and w
is 1/FarPlane.
渲染管线中深度的保存和计算原理
渲染管线过程会出现两次坐标系的选项性转换:
- 世界空间=>观察空间 : 左手变右手。
- 观察空间=>剪裁空间:右手变左手。
进入剪裁空间是为了方便摄像机剪裁而进行的一次对坐标系参数的缩放和偏移。
进入剪裁空间后每一个点(x,y,z,w)只需要满足:
(Opengl) (dx11)
以DX11为例
unity DX11的CullSpace的z值计算方式:
unity对于深度缓存的编码方式:
注:上面的$ z_{cameraspace} $由于CameraSapce 所以始终是一个负数。