《Approximate Soft Shadows on Arbitrary Surfaces using Penumbra Wedges》
Tomas Akenine-Moller and Ulf Assarsson
Eurographics Workshop on Rendering(2002)
這是一個基于標準shadow volume和Haines的《Soft Planar Shadows using Plateaus》改進的算法。算法核心在于在多邊形silhouette邊的基礎上建立一種新的圖元-penumbra wedge,根據陰影接受表面上的點在在penumbra wedges中的位置進行插值,得到改點的陰影級別。
下面對該算法進行更詳細的介紹。假設:光源為球形光源,LI=light intensity光照強度在公式中用s表示。
penumbra wedges如下圖所示。

從圖中可以看出來,PW方法并不是在本影外邊模擬出柔和的過渡,因此相對于Haines的方法在物理上更加真實。
在PW中的LI-s在[0,1]之間計算,表示陰影級別,s=0表示不在陰影范圍內,s=1表示位于本影內。
算法使用一個16bits的buffer作為LI-buffer,就如同是一個更高精度的stencil buffer,可以通過繪制一個HILO的紋理來實現。
一般硬件都具有8-bit的顏色緩存,因此我們使用一個k=255來乘以LI值,然后用color buffer中的值減去255s就得到了改點的顏色值。算法的步驟如下:
1,LI-buffer預置255
2,用spacular+diffuse繪制場景,得到color buffer值
3,繪制所有PW,將PW繪制到LI-buffer中
4,將LI-buffer中的值調制到[0,255]之間并合并到color buffer(我理解是cb-lb)
5,繪制ambient光
其中第3步的偽代碼和對應的圖如下:
1 : rasterizeWedge(){
2 : for each visible fragment(x,y) on front facing triangles of wedge
3 : pf = computeEntryPointOnWedge(x; y);
4 : pb = computeExitPointOnWedge(x; y);
5 : p = point(x; y; z); //z is the Z-buffer value at (x; y)
6 : pi = choosePointClosestToEye(p;pb);
7 : sf = computeLightIntensity(pf );
8 : si = computeLightIntensity(pi);
9 : addToLIBuffer(round(255(si-sf)));
10 : end;}

其中第4步調制的目的是為了把因為位于不同PW中而值大于255的值歸整到0到255之間,以便能夠正確的體現陰影柔和程度。
構造原理如下圖所示:

每個PW分成前后左右四個面,其中前后面的構造分別是:b=c+rn 和 f=c-rn ,r是光源球半徑,n是shadow volume的法線。左右面的構造如下圖所示,是由相鄰PW的兩個前面交點和兩個后面交點以及sil的交點構成。

文章中對于r=0可以直接繪制硬陰影以及鄰sil邊是銳角的情況也給以討論。
- 光照強度插值(Light Intensity Interpolation)
插值的關鍵是在相鄰的PW之間插值要連續,這樣在穿過兩個不同的PW的時候才會保持陰影的光滑。其計算如下圖所示:



文章后邊詳細介紹了優化算法和實現結果,以及與其他算法的比較,這里就不說了。
我對此算法的認識是:
- 相對于以前的算法可以較好的生成軟陰影,同時基于shadow volume,可以有效的避免前邊算法出現的問題。
- 存在著較多的局限性。比如球面光源,比如SV能夠處理的非多邊形體和半透明物體的陰影,比如頂點具有兩個以上sil邊的情況,等等。
- 雖然作者宣稱可以在明年的顯卡上獲得實時的性能,但是沒有硬件的加速完全無法達到很好的性能,這可能就是其沒有上siggraph的原因吧。
- 很多的問題對于我來說,既是機遇也是挑戰。
- 具體怎么實現,還得跟WJ大牛學習學習。