《UnityShader入门精要》13.2中深度纹理采样后如何得到世界坐标

在学习《UnityShader入门精要》的一个笔记

一.13.2节中,缺乏对深度纹理采样后的深度值如何得到世界空间下的坐标表示的解释

对应代码如下

//深度纹理采样,本质是返回纹理采样结果的r通道  
float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth);
//获取投影空间下的坐标(数值范围在-1~1)  
float4 H = float4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, d * 2 - 1, 1);  
// 通过视角*投影矩阵的逆矩阵,得到视角空间下的坐标  
float4 D = mul(_CurrentViewProjectionInverseMatrix, H);  
// 除以w分量,将其转为世界坐标  
float4 worldPos = D / D.w;

令世界坐标系中有一点P,齐次坐标记为 ‘ v w o r l d = ( x , y , z , w ) T ‘ ` v_{world}=(x,y,z,w)^T ` vworld=(x,y,z,w)T,其中 ‘ v w o r l d . w = 1.0 ‘ `v_{world}.w=1.0` vworld.w=1.0‘, 则有


‘ v c l i p = M p r o j ∗ M v i e w ∗ v w o r l d ‘ ` v_{clip} = M_{proj}*M_{view}*v_{world}` vclip=MprojMviewvworld    (1)


其中, ‘ v c l i p ‘ ` v_{clip} ` vclip表示P在裁剪空间中的坐标, ‘ M v i e w ‘ `M_{view} ` Mview表示视角矩阵, ‘ M p r o j ‘ `M_{proj} ` Mproj表示投影矩阵,将上述两个矩阵相乘得到当前的观察投影矩阵 ‘ M v p ‘ `M_{vp} ` Mvp,则有


‘ v w o r l d = M v p − 1 ∗ v c l i p ‘ ` v_{world} = M_{vp}^{-1}*v_{clip}` vworld=Mvp1vclip    (2)


P点的深度纹理采样结果为 ‘ d ‘ `d` d,P点的NDC坐标记为 ‘ v n d c ‘ ` v_{ndc} ` vndc,根据Unity的深度纹理的存储规则,d是NDC映射而来,使用原映射的反函数即可,则有


‘ v n d c = d ∗ 2 − 1 ‘ ` v_{ndc} = d*2-1` vndc=d21‘    (3)


透视除法的过程是裁剪空间坐标的4个分量分别除以w分量,即


‘ v n d c = v c l i p / v c l i p . w ‘ ` v_{ndc} = v_{clip}/v_{clip}.w` vndc=vclip/vclip.w    (4)


由公式(2)和公式(3)得


‘ v w o r l d = M v p − 1 ∗ v n d c ∗ v c l i p . w ‘ ` v_{world} = M_{vp}^{-1}*v_{ndc}*v_{clip}.w` vworld=Mvp1vndcvclip.w    (5)


在公式(5)中, ‘ M v p − 1 ‘ `M_{vp}^{-1} ` Mvp1_CurrentViewProjectionInverseMatrix提供, ‘ v n d c ‘ ` v_{ndc} ` vndc ‘ v n d c = d ∗ 2 − 1 ‘ ` v_{ndc} = d*2-1` vndc=d21‘得到,因为 ‘ v w o r l d . w = 1.0 ‘ `v_{world}.w=1.0` vworld.w=1.0‘,则有


‘ v w o r l d . w = ( M v p − 1 ∗ v n d c ) . w ∗ v c l i p . w = 1.0 ‘ ` v_{world}.w = (M_{vp}^{-1}*v_{ndc}).w*v_{clip}.w = 1.0` vworld.w=(Mvp1vndc).wvclip.w=1.0‘    (6)


由公式(5)可得


‘ v c l i p . w = 1 , 0 ( M v p − 1 ∗ v n d c ) . w ‘ ` v_{clip}.w = \frac{1,0}{(M_{vp}^{-1}*v_{ndc}).w} ` vclip.w=(Mvp1vndc).w1,0    (7)


将公式(7)带入公式(5),则有


‘ v w o r l d = M v p − 1 ∗ v n d c ( M v p − 1 ∗ v n d c ) . w ‘ ` v_{world} = \frac{M_{vp}^{-1}*v_{ndc}}{(M_{vp}^{-1}*v_{ndc}).w}` vworld=(Mvp1vndc).wMvp1vndc


且由公式(3),则可知上文H为 ‘ v n d c ‘ ` v_{ndc} ` vndc,D为 ‘ ( M v p − 1 ∗ v n d c ) ‘ `{(M_{vp}^{-1}*v_{ndc})} ` (Mvp1vndc),则世界坐标可由D / D.w得到

参考(侵删):osg中NDC坐标转换为世界坐标
Github:TipsDuringReadingUnityShadersBook

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值