Unity Shader 使用深度紋理,計算像素的世界坐標(biāo)

Unity Shader系列文章:Unity Shader目錄-初級篇

Unity Shader系列文章:Unity Shader目錄-中級篇

參考文章:獲取深度紋理和法線紋理

我們知道,若已知坐標(biāo)系中的一個頂點坐標(biāo),和它相對于另一個頂點坐標(biāo)的偏移量,則可以求出另一個頂點坐標(biāo)。計算像素的世界坐標(biāo)也是基于這樣的思想,我們只需要知道攝像機(jī)在世界空間下的位置,以及世界空間下該像素相對于攝像機(jī)的偏移量,把它們相加就可以得到該像素的世界坐標(biāo)。整個過程可以使用下面的代碼來表示:

floa worldPos = _WorldSpaceCameraPos + linearDepth * interpolatedRay;

其中,_WorldSpaceCameraPos 是攝像機(jī)在世界空間下的位置,這可以由 Unity 的內(nèi)置變量直接訪問得到。而 linearDepth * interpolatedRay 則可以計算得到該像素相對于攝像機(jī)的偏移linearDepth 是由深度紋理得到的線性深度值, interpolatedRay 是由頂點著色器輸出并插值后得到的射線,它不僅包含了該像素到攝像機(jī)的方向,也包含了距離信息。

linearDepth可以通過深度紋理計算:

float linearDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv));

而 interpolatedRay 來源于對近裁剪平面的4個角的某個特定向量的插值,這4個向量包含了它們到攝像機(jī)的方向和距離信息,我們可以利用攝像機(jī)的近裁剪平面距離、 FOV、橫縱比計算而得。下圖顯示了計算時使用的一些輔助向量。 為了方便計算,我們可以先計算兩個向量——toTop 和 toRight,它們是起點位于近裁剪平面中心、分別指向攝像機(jī)正上方和正右方的向量。它們的計算公式如下:

halfHeight=Near\times tan(\frac{FOV}{2})
toTop=camera.up\times halfHeight
toRight=camera.right\times halfHeight·aspect

其中, Near 是近裁剪平面的距離, FOV 是豎直方向的視角范圍, camera.up、camera.right分別對應(yīng)了攝像機(jī)的正上方和正右方。當(dāng)?shù)玫竭@兩個輔助向量后 ,我們就可以計算4個角相對于攝像機(jī)的方向了。我們以左上角為例(見下圖中的 TL 點),它的計算公式如下:

TL=camera.forward·Near+toTop-toRight

同理,其他 個角的計算也是類似的:

TR=camera.forward·Near+toTop+toRight
BL=camera.forward·Near-toTop-toRight
BR=camera.forward·Near-toTop+toRight

注意,上面求得的4個向量不僅包含了方向信息,它們的模對應(yīng)了 個點到攝像機(jī)的空間距離。由于我們得到的線性深度值并非是點到攝像機(jī)的歐式距離,而是在 z 方向上的距離,因此,我們不能直接使用深度值和4個角的單位方向的乘積來計算它們到攝像機(jī)的偏移量,如下圖所示。想要把深度值轉(zhuǎn)換成到攝像機(jī)的歐式距離也很簡單,我們以 TL 點為例,根據(jù)相似三角形原理,TL 所在的射線上,像素的深度值和它到攝像機(jī)的實際距離的比等于近裁剪平面的距離和 TL向量的模的比,即:

\frac{depth}{dist}=\frac{Near}{|TL|}

由此可得,我們需要的 TL 距離攝像機(jī)的歐氏距離 dist:

dist=\frac{|TL|}{Near}\times depth

由于4個點相互對稱,因此其他3個向量的模和 TL 相等,即我們可以使用同一個因子和單位向量相乘 ,得到它們對應(yīng)的向量值:

scale=\frac{|TL|}{|Near|}
Ray_{TL}=\frac{TL}{|TL|}\times scale,Ray_{TR}=\frac{TR}{|TR|}\times scale
Ray_{BL}=\frac{BL}{|BL|}\times scale,Ray_{BR}=\frac{BR}{|BR|}\times scale

計算interpolatedRay
采樣得到的深度值并非是點到攝像機(jī)的歐式距離

屏幕后處理的原理是使用特定的材質(zhì)去渲染一個剛好填充整個屏幕的四邊形面片。這個四邊
形面片的 個頂點就對應(yīng)了近裁剪平面的 個角。因此,我們可以把上面的計算結(jié)果傳遞給頂點
著色器,頂點著色器根據(jù)當(dāng)前的位置選擇它所對應(yīng)的向量 然后再將其輸出,經(jīng)插值后傳遞給片
元著色器得到 interpolatedRay,然后就可以根據(jù)之前的公式計算該像素在世界空
間下的位置:

floa worldPos = _WorldSpaceCameraPos + linearDepth * interpolatedRay;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容