1. 程式人生 > >視差貼圖(parallax mapping)學習筆記

視差貼圖(parallax mapping)學習筆記

視差貼圖是一種很神奇的技術,它的效果有點類似法線貼圖,都是通過儘可能少的面片加上特殊的技術來模擬複雜幾何體的視覺效果。通常視差貼圖都會和法線貼圖結合起來使用。

視差貼圖的核心思想,就是通過貼圖時uv座標的偏移,來形成視覺上的幾何體高低視差,給人以立體的感覺。這篇教程很詳細,下面的圖片也是來自於該教程(捂臉):

這裡寫圖片描述

如圖所示,高度為0.0的平面是渲染時的實際面片,棕色的線則代表了原始幾何體的實際高度。這裡我們一共需要三張紋理:法線紋理,高度紋理以及顏色紋理。

A點是我們在面片上看到的點,B點則是該幾何體(如果是幾何體而非一個面片的話)應該被我們所觀察到的點,很明顯A點和B點對應的紋理座標是不同的,為了模擬實際的幾何體表面,我們需要估計A B之間紋理座標的偏移,這裡又是一個“hack”,這裡我們粗暴的將偏移量通過如下公式計算:

Xoffset=viewDir.x/viewDir.zH(A)factor Yoffset=viewDir.y/viewDir.zH(A)factor

其中的viewDir是歸一化之後的視線向量,H(A)代表A點的高度。該公式雖然不精確,但是總體上符合視覺的規律。可以看出,當視線與平面的夾角越大,viewDir.x/viewDir.z 的比值也就越大,這樣計算出來的偏移量也就越大,足以糊弄我們的眼睛。但是這樣模擬出來的偏移量太大,需要調校一下factor這個引數,一般設定為0.1,使視覺效果達到最好。

通過這個UV偏移量得到實際的紋理座標,然後再取該處的法向量和顏色值,最後得到的效果如下圖。

這裡寫圖片描述

但是上述估計實在過於粗糙,當視線接近水平時,紋理會有很多地方發生扭曲。為了更精確的得出偏移量,又有了下面的方法:

steep parallax mapping

這裡寫圖片描述

這次我們將深度紋理分層,每層的間隔相同,然後用一種類似於raymarch的演算法,沿著視線方向往下探,每次高度下降一層,當視線與某一層的交點的高度值小於該處深度貼圖中的高度時停止。圖中所示,T2處的實際高度比該層的高度0.4要高,繼續往下,到了T3時反過來了,因此我們就選取T3作為偏移之後的紋理座標。用這種方式精度提升了很多,而且分層越細,精度越高。但是問題也隨之而來,圖片中產生了很明顯的條帶:

這裡寫圖片描述
 

這裡寫圖片描述

這些條帶產生的原因如上圖,注意其中的灰線和綠線,它們是進行“raymarch”時兩層的分界線,他們對應的偏移後的紋理座標區域(灰虛線和綠虛線之間的區域)有很多是重複的,這也就意味著看到的紋理也會因為重複而產生條紋。

線性插值

為了解決這個問題,我們通過線性插值的方式來確定偏移後的紋理座標,使精度進一步提升,而且更平滑:

這裡寫圖片描述

如上圖,現在我們不再簡單的取T3作為偏移紋理了,根據一個比值R來對紋理座標進行線性插值,現在圖中的H()代表該點處實際高度與該層高度的差值的絕對值。

r=H(T3)/(H(T3)+H(T2)) Xoffset=T3.x(1r)+T2.xr Yoffset=T3.y(1r)+T2.yr

r=1時,偏移座標為T2,當r=0時,偏移座標為T3。這樣處理之後得到的效果就比較令人滿意了,幾乎沒有瑕疵。

這裡寫圖片描述

最後很感謝參考文章中的作者,講的深入淺出,插圖也很直觀(我順便也可恥的利用了一下)。