大場景的陰影算法一直以來是個比較麻煩的問題,一般來說都是使用級聯陰影算法,將視錐體進行從近到遠的划分,整個場景的物體可以更均勻的分布在幾張ShadowMap上,但可以明顯看出這種情況視角平視才可以,如果視角俯視,那么算法打很大折扣。

ShadowMap和陰影體是常見的兩種實時陰影算法,陰影體由於需要模型是流型等嚴格要求其實也較少用,反而都用在體積光等渲染技術上,所以一般來說實時陰影用ShadowMap的居多。實時陰影技術一書中對各種陰影技術都總結的很全面,里面介紹了ShadowMap的各種變種技術,如級聯陰影,光源空間陰影算法等,PCF,VSM各種等,之前也試驗了其中不少方法,就我個人的經驗總結如下:
陰影邊緣的過濾最普通的是PCF方法,但會對陰影邊緣有一些模糊,如果要比較好的模糊效果,可以Jitter采樣多次,模糊的效果較好,有種環境光情況下,陰影邊緣模糊的樣子,可以參考Unigine引擎,但多次采樣特別是在移動端損失效率。類似的在陰影邊緣做文章的例子可以參考英偉達SDK,D3DSDK等,像啥HARD,PCSS等算法,在像素着色器中使用了DXDY等高級函數。感覺這方面的例子挺多的,效果也不錯,但性能堪憂啊,用這種方法渲染場景中少量物體還行。
PeterPaning偏移是另一個問題,但只要在Z方向壓緊光源包圍盒問題則不大。
VSM使用概論不等式方法,得到邊緣較清楚,需要使用32位浮點精度,在移動端的16位浮點精度下,效果很差。
LiPSM光源空間陰影算法,是書中介紹的陰影包裝算法中比較典型的一種,這類算法都是想辦法從物體空間到光源空間的變換上做文章,以此高效利用ShadowMap。LiPSM光源空間陰影算法在光源是視角平行時則表現同標准的ShadowMap算法,不理想。
還有就是多張ShadowMap了,有CSM,PSSM等,但大體意思一樣,目前發表的各種論文,很多都是在分析怎樣切分視錐體,這個其實在GPU精粹3的一篇文章中已經介紹很清楚了,分析了特殊視角下精度的問題,但在實踐中發現大概符合近處距離小的原則就可以了,沒必要搞那么嚴格,特別是場景視角在不停變化,一般論文也都像GPU精粹3中一樣只是分析了特殊視角下精度問題,對任意視角完全沒有考慮到,個人感覺從數學理論上也很難分析清楚了。這個算法存在的特點和問題前面已經介紹了,在此不贅言了。
http://www.klayge.org/2013/05/07/%E5%A4%A7%E8%8C%83%E5%9B%B4shadow-map%EF%BC%88%E4%BA%8C%EF%BC%89%EF%BC%9Asdsm/
以上這個鏈接中介紹的龔大的SDSM陰影算法,預先算一遍場景深度,在這個深度范圍內進行切分,避免了無效的視錐體對應的ShadowMap,算是對原有算法的一種改進,但如果場景范圍已知,比如場景中都是大型地面上各種建築物,則在CPU端直接可以嚴格的計算出包圍盒大小,壓緊視錐體Z值,不僅可以用於ShadowMap切分,更可以緩解ZFighting現象。這種算法依然同之前CSM算法一樣在處理俯視大場景問題中的缺陷一樣。
