|
深度纹理
深度纹理是渲染过程中产生的,具体来说,场景中物体从模型空间经过 MVP 矩阵变换到 NDC,z 坐标的值就存储了其深度信息,将这个值缓存,经过一些数值变换就可以作为深度纹理使用。
从 Shader Graph 的一些节点可以很好的了解深度纹理
根据官方文档:Scene Depth Node,有三种采样模式:Linear01,Raw,Eye。从最基本的 Raw 模式开始说。
《Unity Shader 入门精要》13.1
Raw 模式的深度值由上图 NDC 中的 z 坐标变换得到,将其值域 [-1, 1] ,映射到 [0, 1] 得到,具体计算为:
由于从视空间到 NDC 经过透视投影,所以 Raw 模式下的深度值是非线性的,有时需要线性空间下的深度值,则需要 View Space 下的 Z 坐标,也就是 Eye 模式。
至于 Linear01 模式,就是通过 View Space 下的 Z 坐标,将其值域从 (对应近平面和远平面值),映射到 (准确的说是 ),具体计算为:
下面再梳理一下三种模式的关系:
首先,从视空间到裁剪空间,左乘投影矩阵(推导见:王二:[GAMES101] 投影变换和模型变换 作业1),
可以得到
(加上了负号是因为 Unity 中 视空间的 z 轴与其他空间相反,使用右手系)
再经过透视除法从 Clip Space 变到 NDC
结合 (1)(2)可以得到 和 之间的关系
(同样加上了负号)
(TODO)用 Shader Graph 验证发现有问题,目前还不知道什么原因, 和 的关系是对的,但 不对
用 Shader Graph 验证失败
屏幕空间坐标
Screen Position Node 在 shader graph 里有四种模式
未经过透视除法的,左下角是(0,0)右上角是(1,1)的屏幕空间
IN.ScreenPosition = (clip.xy * 0.5f + 0.5 * clip.w, clip.z, clip.w); // clip 为裁剪空间坐标
IN.ScreenPosition;
Raw
为什么会有 0.5 * clip.w 这个单看起来很奇怪的项,与 ComputeScreenPos 函数一样,为了提高效率,在顶点着色器中使用这个函数,就必须将除以 w 分量的步骤放到片元着色器,因为裁剪空间不是一个线性空间,而从顶点着色器到片元着色器的插值是线性插值。
经过透视除法的,左下角是(0,0)右上角是(1,1)的屏幕空间
float4(IN.ScreenPosition.xy / IN.ScreenPosition.w, 0, 0);
Default
经过透视除法的,左下角是(-1,-1)右上角是(1,1)的屏幕空间
float4(IN.ScreenPosition.xy / IN.ScreenPosition.w * 2 - 1, 0, 0);
Center
经过透视除法的,分成上下均等的四块组成,每块左下角是(0,0)右上角是(1,1)的屏幕空间
frac(float4((IN.ScreenPosition.x / IN.ScreenPosition.w * 2 - 1) * _ScreenParams.x / _ScreenParams.y, IN.ScreenPosition.y / IN.ScreenPosition.w * 2 - 1, 0, 0));
Tiled
最终的屏幕空间坐标由 NDC 缩放得到,NDC 的 xyz 分量值属于 ,将其缩放到 , ,z 和 w 分量与裁剪空间保持一致(根据 ComputeScreenPos 函数),下面是计算公式
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|