一、基于圖像的陰影技術(Shadow Map)
什么是陰影
當來自光源的至少一個點在空間中被遮擋時,就產生了陰影區域。
陰影的前提
- 直接光照
- 不透明物體
陰影的實現方式
陰影體(Shadow Volumes)——空間中黑暗部分的幾何
陰影映射(Shadow Map)——在場景中沒有背光源找到的地方
陰影映射(Shadow Map)
綠色的點沒有陰影。
紅色點在攝像機視角看是在陰影里,但在光源的視角看在盒子后面,不代表一定在陰影中(例如多光源情況)。
深度比較
相機視角渲染的深度圖與光照視角渲染的深度圖進行比較。
陰影映射-問題
- 低分辨率的陰影映射會導致有鋸齒的陰影。
- 當比較深度時,為了避免表面自陰影,需要設置容錯閾值(深度偏移)。
二、基于圖像的陰影技術的優化
深度偏移(Depth Bias)
傳統Shadow Map因為自陰影出現的問題——陰影失真(Shadow Acne)
紅色斜著的區域對應了ShadowMap上每塊片段(像素)的位置,因為陰影貼圖受限于分辨率,在距離光源比較遠的情況下,多個片段可能從ShadowMap的同一個值中去采樣。圖片每個斜坡代表ShadowMap一個單獨的紋理像素。你可以看到,多個片段從同一個深度值進行采樣。有些在地板上面,有些在地板下面;在和屏幕空間深度做比較的時候就會出現誤差,這樣我們所得到的陰影就有了差異。
我們可以用一個叫做陰影偏移(shadow bias)的技巧來解決這個問題,我們簡單的對表面的深度(或深度貼圖)應用一個偏移量,這樣片段就不會被錯誤地認為在表面之下了。
舉個栗子:
這四個fragment分別取名a,b,c,d,由于光源的位置會導致求得的四個距離會不一樣,先求a到光源的距離假設為9.8<10,b到光源的距離是11.6 >10,c到光源的距離12.1>10,c到光源的距離9.5<10,。就會導致a和d亮,b和c暗,他們本來應該都是亮的才對。然后整個光源視椎體下各個片段都會出現這個問題,就會出現上面的明暗交錯的條紋。
?
如果Bias值過大也會導致一個問題——懸浮
Unity中的自陰影優化
與OpenGL優化原理差不多。
陰影映射的走樣
人們期望,正常情況下Shadow Map上的像素可以對應上屏幕空間的像素,這種情況僅在目標Light垂直于目標物體(平面)時才會出現,但通常并不會滿足上述條件。
因此人們開始針對此類問題進行優化,主要優化點如下:
- 初始采樣(渲染陰影映射)
- 重采樣:從攝像機視角對采樣信號(陰影映射)重采樣
- 重建:使用濾波函數(例如PCF)
主要誤差類型
解決方案:
- 初始采樣——透視走樣
- 光空間透視陰影映射 (LiSPSM)
- Z分割(級聯陰影映射)
- 視口采樣映射
小結
- 只能使用一張陰影映射時,LiSPSM是最好的選擇,尤其是戶外頂部光照
- 允許多張陰影映射時,最好的方案是Z分割(CSM等)
- 自分割可以同時處理透視與投影走樣,RMSM與現值虛擬紋理的方案很類似,支持虛擬紋理的引擎很容易實現
- 無走樣方案可以達到像素級別的精度,應該會是未來的趨勢
硬陰影的濾波
- 主要用于減少重采樣的誤差(使用陰影映射進行渲染時產生)
- 濾波
-
- 圖像處理中可以通過濾波強調一些特征或者去除圖像中一些不需要的部分
- 濾波是一個鄰域操作算子,利用給定像素周圍的像素的值決定此像素的最終的輸出值
- 任何使用一部分陰影映射采樣點來計算某個指定View采樣點的最終陰影結果的方法
PCF(Pencentage close Filtering)濾波
- 可以模糊來隱藏欠采樣的瑕疵;
- 得到類似軟陰影的效果,不少游戲引擎稱之為“軟陰影”;
- 一個重要缺陷是較大的濾波核會導致更多采樣點的計算,性能消耗大;
- 無法進行預計算,因為濾波依賴于
- PCF 雖然能對陰影進行平滑模糊,但畢竟無法模擬基于物理的軟陰影, PCSS(Percentage Closer Soft Shadows)能夠設置變化的濾波核來改進這一點。
三、基于圖片的軟陰影算法
流程:
1.查找遮擋體
2.半影寬度的計算
Wpenumbra=P sz- Zavg / Zavg * Wlight
Wlight為光源的大小
3.濾波
Wf = Znear / PSZ *Wpernumbra