您當前的位置:首頁 > 攝影

點光源陰影實現(避坑)

作者:由 amadios 發表于 攝影時間:2022-09-12

寫了兩週的點光源陰影,踩了坑記錄下。

關於點光源陰影,傳統的做法是渲染場景六次。

曾經一度有使用 Dual-Paraboloid 來做的,它是透過一種對映手段,可以渲染場景兩次得到 shadowMap。它的實現比較依賴於細分著色器,

caster 時無法避免的會需要細分

。否則就會和下圖一樣。從

陰影質量

來說無法和立方體方案相提並論。同時利用率要低於其他方法。klayGE 的文件中提到這種方法已經是過時的了。

點光源陰影實現(避坑)

GPU Pro 1 中首次提出了使用四面體進行陰影渲染。我也復現了其中的程式碼。和 Dual-Paraboloid 一樣,能夠減少提交場景的次數,同時陰影質量要強於使用剖面來做,但是還是略遜於立方體。同時,比較巧妙的在於為了提高利用率。會在渲染 shadow 之前,填充 shadowMap 的 stencil。渲染時,透過 stencil 剔除掉不在三角形內部的物體。但是在實現上就略微蛋疼,支援 stencil 就意味著在 Unity 中放棄了 Native Shadow Format,在後面取樣的時候 GL平臺 的取樣器會有問題。我實現了一個版本的 Demo, 並和 URP 11 中新的點光源陰影做了對比。由於這種組織形式,512 * 512 的四面體陰影,效果接近 1024 * 512 的立方體陰影。

點光源陰影實現(避坑)

點光源陰影實現(避坑)

點光源陰影實現(避坑)

綠色區域外的透過 stencil 進行剔除

但是對比下來效能並沒有明顯提升,甚至略差。透過 Renderdoc 簡單抓取時間後發現,shadow 的 gpu 耗時似乎主要和物體覆蓋的像素面積相關。由於 512 * 512 大小的單次覆蓋畫素數為 512 * 256,總的畫素覆蓋就要高於立方體。這是因為在實現的時候,CPU 端使用的是相機的視錐體進行剔除。但是實際上四面體的剔除並不適合直接使用相機的視錐。透過自定義 Culling Plane 後,大大減少了 stencil test failed 的物體,減少了 shadow caster 的數量。但是即便如此,得到的效能提升也比較有限。在物體數量較少時,因為進行 stencil 的填充,耗時反而還高了。(單光源)

點光源陰影實現(避坑)

GPU PRO 6 中提到使用四叉樹進行管理四面體陰影。透過光源在視錐體上 AABB 包圍盒的大小,去四叉樹中查詢光源對應的 tile 的大小和位置。相較於立方體那種分配方式,可以說是簡潔美觀多了。同時,為了減少繪製的數量,透過 GS,完成了 One Pass Shadow。同時,把剔除工作放到了 GS 中進行,進一步解放了 CPU。同時由於進行了更細粒度的剔除,也就不需要使用模版緩衝了。

但是!Metal 不支援用 GS。。我單光源四面體和 tileMap 都做完了,發現使用 GS 能避免 stencil,正準備刪掉倒黴的 stencil fill 結果你個么兒告訴我不支援。。。

結論:還是老老實實用六面體吧。。不搞這些花裡胡哨的。。就算支援了 GS ,也不過就是多生成一半的頂點罷了。。另外,使用視錐體相交測試也會省很多。我要去抄 URP 嘍。。有錯誤的還請大佬指正。

標簽: Stencil  512  陰影  GS  立方體