rustum 发表于 2022-4-21 17:27

Unity Shader Graph 中深度纹理(Depth Texture)和屏幕 ...

深度纹理

深度纹理是渲染过程中产生的,具体来说,场景中物体从模型空间经过 MVP 矩阵变换到 NDC,z 坐标的值就存储了其深度信息,将这个值缓存,经过一些数值变换就可以作为深度纹理使用。
从 Shader Graph 的一些节点可以很好的了解深度纹理

[*]Scene Depth Node
根据官方文档:Scene Depth Node,有三种采样模式:Linear01,Raw,Eye。从最基本的 Raw 模式开始说。



《Unity Shader 入门精要》13.1

Raw 模式的深度值由上图 NDC 中的 z 坐标变换得到,将其值域 [-1, 1] ,映射到 得到,具体计算为:

https://www.zhihu.com/equation?tex=z_%7Braw%7D%3D0.5+%5Ccdot+z_%7Bndc%7D+%2B+0.5++++%5Ctag%7B1%7D+%5C%5C
由于从视空间到 NDC 经过透视投影,所以 Raw 模式下的深度值是非线性的,有时需要线性空间下的深度值,则需要 View Space 下的 Z 坐标,也就是 Eye 模式。
至于 Linear01 模式,就是通过 View Space 下的 Z 坐标,将其值域从 https://www.zhihu.com/equation?tex=+%5Bn%2C+f%5D+ (对应近平面和远平面值),映射到 https://www.zhihu.com/equation?tex=+%5B0%2C+1%5D+ (准确的说是 https://www.zhihu.com/equation?tex=%5B%5Cfrac%7Bn%7D%7Bf%7D%2C+1%5D ),具体计算为:

https://www.zhihu.com/equation?tex=z_%7B01%7D+%3D+%5Cfrac%7Bz_%7Bview%7D%7D%7Bf%7D+%5C%5C
下面再梳理一下三种模式的关系:
首先,从视空间到裁剪空间,左乘投影矩阵(推导见:王二: 投影变换和模型变换 作业1),

https://www.zhihu.com/equation?tex=P_%7Bclip%7D+%3D+M_%7Bper%7D%5Ccdot+P_%7Bview%7D%3D+%5Cleft%5B%5Cbegin%7Bmatrix%7D++%5Cfrac%7B2n%7D%7Br-l%7D%260%26%5Cfrac%7Bl%2Br%7D%7Bl-r%7D%260%5C%5C++0%26%5Cfrac%7B2n%7D%7Bt-b%7D%26%5Cfrac%7Bb%2Bt%7D%7Bb-t%7D%260%5C%5C++0%260%26%5Cfrac%7Bn%2Bf%7D%7Bn-f%7D%26%5Cfrac%7B2fn%7D%7Bf-n%7D%5C%5C++0%260%261%260%5C%5C++%5Cend%7Bmatrix%7D+%5Cright%5D+++++%5Cleft%5B%5Cbegin%7Bmatrix%7D++x_%7Bview%7D%5C%5C++y_%7Bview%7D%5C%5C++z_%7Bview%7D%5C%5C++1%5C%5C++%5Cend%7Bmatrix%7D+%5Cright%5D+++++%5C%5C+
可以得到

https://www.zhihu.com/equation?tex=z_%7Bclip%7D+%3D+-z_%7Bview%7D%5Ccdot+%5Cfrac%7Bf%2Bn%7D%7Bf-n%7D+-+%5Cfrac%7B2nf%7D%7Bf-n%7D+%5C%5C+

https://www.zhihu.com/equation?tex=w_%7Bclip%7D+%3D+-z_%7Bview%7D+%5C%5C
(加上了负号是因为 Unity 中 视空间的 z 轴与其他空间相反,使用右手系)
再经过透视除法从 Clip Space 变到 NDC

https://www.zhihu.com/equation?tex=z_%7Bndc%7D%3D%5Cfrac%7Bz_%7Bclip%7D%7D%7Bw_%7Bclip%7D%7D%3D+%5Cfrac%7Bf%2Bn%7D%7Bf-n%7D+%2B+%5Cfrac%7B2nf%7D%7B%28f-n%29%5Ccdot+z_%7Bview%7D%7D++++++%5Ctag%7B2%7D+%5C%5C
结合 (1)(2)可以得到 https://www.zhihu.com/equation?tex=z_%7Braw%7D+ 和之间的关系

https://www.zhihu.com/equation?tex=z_%7Bview%7D+%3D+%5Cfrac%7Bnf%7D%7B%28n-f%29+z_%7Braw%7D+%2B+f%7D+%5C%5C
(同样加上了负号)

https://www.zhihu.com/equation?tex=z_%7B01%7D+%3D+%5Cfrac%7Bz_%7Bview%7D%7D%7Bf%7D+%3D%5Cfrac%7Bn%7D%7B%28n-f%29+z_%7Braw%7D+%2B+f%7D+%5C%5C

(TODO)用 Shader Graph 验证发现有问题,目前还不知道什么原因, https://www.zhihu.com/equation?tex=z_%7B01%7D 和的关系是对的,但 https://www.zhihu.com/equation?tex=z_%7Braw%7D 不对



用 Shader Graph 验证失败

屏幕空间坐标

Screen Position Node 在 shader graph 里有四种模式

[*]Raw
未经过透视除法的,左下角是(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 分量的步骤放到片元着色器,因为裁剪空间不是一个线性空间,而从顶点着色器到片元着色器的插值是线性插值。


[*]Default

经过透视除法的,左下角是(0,0)右上角是(1,1)的屏幕空间
float4(IN.ScreenPosition.xy / IN.ScreenPosition.w, 0, 0);


Default



[*]Center

经过透视除法的,左下角是(-1,-1)右上角是(1,1)的屏幕空间
float4(IN.ScreenPosition.xy / IN.ScreenPosition.w * 2 - 1, 0, 0);


Center



[*]Tiled

经过透视除法的,分成上下均等的四块组成,每块左下角是(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 分量值属于 https://www.zhihu.com/equation?tex=%5B-1%2C1%5D,将其缩放到 https://www.zhihu.com/equation?tex=x%5Cin%5B0%2C+screenWidth%5D , https://www.zhihu.com/equation?tex=y%5Cin%5B0%2C+screenHeight%5D ,z 和 w 分量与裁剪空间保持一致(根据 ComputeScreenPos 函数),下面是计算公式

https://www.zhihu.com/equation?tex=%5Cbegin%7Balign%7D+x_%7Bscreen%7D%26%3D+%280.5+%5Ccdot+%5Cfrac%7Bx_%7Bclip%7D%7D%7Bw_%7Bclip%7D%7D+%2B+0.5%29+%5Ccdot+screenWidth+%5C%5C+%26%3D%280.5+%5Ccdot+x_%7Bndc%7D+%2B+0.5%29+%5Ccdot+screenWidth+%5Cend%7Balign%7D+%5C%5C

https://www.zhihu.com/equation?tex=%5Cbegin%7Balign%7D+y_%7Bscreen%7D%26%3D+%280.5+%5Ccdot+%5Cfrac%7By_%7Bclip%7D%7D%7Bw_%7Bclip%7D%7D+%2B+0.5%29+%5Ccdot+screenHeight%5C%5C+%26%3D%280.5+%5Ccdot+y_%7Bndc%7D+%2B+0.5%29+%5Ccdot+screenHeight+%5Cend%7Balign%7D+%5C%5C

https://www.zhihu.com/equation?tex=z_%7Bscreen%7D+%3D+z_%7Bclip%7D+%5C%5C

https://www.zhihu.com/equation?tex=w_%7Bscreen%7D%3Dw_%7Bclip%7D%3D-z_%7Bview%7D+%5C%5C
页: [1]
查看完整版本: Unity Shader Graph 中深度纹理(Depth Texture)和屏幕 ...