Unity:嘗試製作可相交的視差遮蔽貼圖 Shader (Trying to Create an Parallax Occlusion Mapping Shader with Pixel Depth Offset)
警告,本文只是分享摸索的過程,並不是完善的技術文。 此文在計算深度位移有錯誤,後續有所更新,詳見 此文 視差貼圖(Parallax Mapping)是一種改進後的凹凸貼圖的技術,可以用極少的面數模擬複雜模型的表面凹凸,因為介紹視差貼圖這個技術的文章很多了此處就不詳細介紹,本文只大概說明使用視差貼圖要怎麼讓模型與一般的物件產生正確的陰影投射和相交的效果。 一般的視差貼圖的做法是依照切線空間的視線相量位移貼圖採樣的 UV 座標而產生立體感,物件本身的幾何形狀並未更改,因此各個像素的深度也是原有形狀的位置,因此相交時無論畫面上的物體因為視差貼圖產生凹凸的樣貌為何,相交還是依照原有的幾何形狀,而接收物件陰影投射亦有相同狀況。(如下圖) Unity 中的 HDRP 中內建的 Lit Shader 提供的像素深度位移(Pixel Depth Offset)的功能,可以讓各個像素的深度位置依照視差貼圖位移的量產生位移,進而讓視差貼圖凹凸的效果也能對應到物件的相交上。(如下圖) 需要提到的是 Unreal 引擎的 Shader 也有同個功能,但無論是 Unity 和 Unreal 引擎的做法我都無法取得夠詳細的資料,雖然 Unity 的 Lit Shader 可以找到原始碼,但是太複雜了,目前暫時還是沒有辦法理清做法。 (゚∀。) 為了產生正確的物件相交與陰影投射勢必要計算出正確的深度,那麼怎麼計算正確的深度呢?我的做法就是直接將像素的世界空間座標依照凹凸的位移量計算出位移後的世界座標,然後再計算剪裁空間的座標,然後就得出深度了。 需要說的是我採用的視差貼圖技術是視差遮蔽貼圖(Parallax Occlusion Mapping,POM) ,原先是在 Shader Graph 中用 Custom Function 節點製作的,結果如下方的影片。 參考了 Unity 的做法,使用的是高度圖而非深度圖,因此高度(深度)最低為0,最高為1,需要特別注意。 取得視差位移後的深度首先第一步是求出視差位移後的高度(深度)。這個很簡單,回傳位移後的 UV 時一並回傳目前的高度(深度),如下圖可以看到高度最低至最高由 0 到 1 灰階漸層。 一旦取得高度後便可以取得世界空間的...