轉自:http://blog.csdn.net/zjull/article/details/11819923html
Shadow Map和Shadow Volume是當今比較流行的實時陰影渲染方法,跟Shadow Map相比,Shadow Volume最大的優勢是沒有陰影鋸齒問題,但因爲它是基於幾何的方法,每幀都有可能要構造和渲染陰影錐,並且有些工做必須由CPU完成,使得它在效率上沒有Shadow Map高,由於其計算都是在GPU端完成的;不過對於室內場景或者objects很少的室外場景,Shadow Volume仍有用武之地,陰影錐的實現有多種算法,並且能夠作比較多種優化,這裏學習一下Z-PASS和Z-FAIL算法,它們都是multipass的,暫時沒考慮優化問題。算法
Z-PASS算法緩存
pass1:打開depth test,按正常方式渲染整個場景,獲得depth map。學習
pass2:打開stencil test,關掉z writing和color buffer writing,渲染shadow volumes;設置stencil test always pass,對於front faces,若z test pass,則stencil value +1,若z test fail,則不更新stencil value;對於back faces,若z test pass,則stencil value -1。優化
pass3:pass2完成以後,stencil buffer中value不爲0的像素就處於陰影區域,據此繪製陰影效果便可。spa
圖1:Z-PASS算法.net
Z-PASS算法在視點位於陰影錐內或者跟近裁剪面相交時,會獲得錯誤的stencil values,以下圖所示:code
圖2:Z-PASS算法失效的狀況htm
Z-FAIL算法blog
Z-FAIL算法是 John Carmack,Bill Bilodeau 和 Mike Songy 各自獨立發明的,其目的就是解決視點進入 shadow volume 後 Z-PASS 算法失效的問題;
pass1:跟Z-PASS算法同樣
pass2:打開stencil test,關掉z writing和color buffer writing,渲染shadow volumes;設置stencil test always pass,對於front faces,若z test fail,則stencil value -1,若z test pass,則不更新stencil value;對於back faces,若z test fail,則stencil value +1。
pass3:跟Z-PASS同樣
如圖3所示,Z-FAIL算法不論視點位於陰影錐外面,裏外仍是近裁剪面與陰影錐相交,均可以正確獲得stencil values。
圖3:Z-FAIL算法
Z-FAIL要求Shadow Volume必須是閉合的,圖4左將獲得錯誤的stencil values,加上陰影錐caps(圖4右)能夠糾正。
圖4:Z-FAIL算法的失效場景以及補救措施
陰影錐實現(Z-PASS)
Shadow Map與Shadow Volume的比較
Shadow Map的優點:
實現簡單,不須要任何幾何計算,shadow map能夠徹底由GPU生成。
不須要模板緩存,只須要爲每一個光源保存一張shadow map,沒有緩存高填充率問題。
Shadow Map的劣勢:
在陰影邊緣容易造成鋸齒,下降了陰影質量,特別在光源離陰影投射體很遠的時候更明顯。
對於每一個光源,場景都須要渲染一次以獲得shadow map,對於點光源,須要作更多的工做。
Shadow Volume的優點:
可得到高質量的陰影效果,沒有陰影邊緣鋸齒問題;
能方便處理聚光照,方向光等多種光源。
Shadow Volume的劣勢:
當光源或者投射物體的幾何信息發生變化時,陰影錐都須要從新計算,佔據比較多的CPU時間;
對幾何體的拓撲有要求,即幾何體必須是閉合的;
須要模板緩存,不優化的狀況下存在高填充率問題,常見的優化方法有:有限陰影錐(Finite Volumes)、XY裁剪(XY Clipping)、Z限定(Z-Bounds);
沒法處理具備透明材質物體的陰影投射,如公告板,粒子系統,樹葉,grass等;
要求場景中的全部物體都接收投射的陰影,即便接收不到的狀況下。
參考連接
http://http.developer.nvidia.com/GPUGems/gpugems_ch09.html
http://blog.donews.com/yyh/archive/2005/05/19/387143.aspx