實時陰影渲染(三):軟陰影深度校正


上一篇介紹的軟陰影技術已經可以生成很好的軟陰影

再結合第一篇介紹的PSSM就可以實現不錯的陰影效果

但在實際應用中的會遇到一個很重要的問題:陰影渲染中的自陰影問題

這種問題的產生的原因和鋸齒原因類似:

視空間中的像素和燈光空間像素不一致

比如視空間中的一塊區域(多個像素)在渲染陰影時對應同一個像素,因而僅產生一個深度值(中心深度)

對於燈光空間中傾斜的三角面來說,這些值是應該不同的

一般對這種問題的解決辦法是通過一個小的深度偏移量,或者再通過背面渲染緩解這種問題

 而采用多個采樣的深度軟陰影技術,這種問題會更加顯著,這樣僅采用一個小小的偏移就不夠了

但如果深度偏移太大又會導致本該出現陰影的地方沒有陰影

 

下圖以水平3像素的軟陰影采樣為例說明這種問題:

如上圖,假設場景中僅存在ABC所在的平面,ABC為相鄰的三個陰影像素,

采用水平3采樣計算c點陰影時,會得到強度為0.333的陰影,因為 depth(a)>depth(c)+depthBias

這樣渲染那出來的結果是:整個平面都在強度為0.333陰影中;而實際上整個平面都不應該有陰影

 除非我們將depthBias設的足夠大,但AB平面越傾斜、采樣數越多所需要的depthBias的值就越大

這樣通過增大depthBias的值是不能解決問題的

 

思考一下,如果我們能知道ac點的深度差dz = depth(c)-depth(a)的值,就可以通過計算比較出:

  depth(a) - dz  <   depth(c)+depthBias;

  depth(c)  <     depth(c)+depthBias;

  depth(b) + dz <   depth(c)+depthBias;

從而得出整個平面都不在陰影中的結果

 

計算深度差dz

在GPU設計體系中,片段程序執行時並不知道其它片段的信息

但好在GPU的實現中提供了ddx ddy兩個例外的指令,通過這兩條指令可以得出相鄰片段間的偏導,也就是相鄰片段之間的數據差值

因為實際采樣一般為3*3,5*5,我們需要計算水平和垂直兩個方向上的深度差zx、zy

假設在當前片段所在三角面對應一個陰影紋理像素的深度差為float2(zx, zy), 陰影紋理寬高為float2(w,h)

通過求解二元一次方程組:

  ddx(uv) * float2(zx, zy) * float2(w,h)= ddx(z)

  ddy(uv) * float2(zx, zy) *float2(w,h)= ddy(z)

 就可以得到zx、zy

注:uv  為當前片段的深度紋理uv坐標, z 為當前片段深度值 ,這些都是已知

 

2017-9-22修改: +方程求解說明

之前的方程寫的意思不明確,想表達的是:

    ddx(u)*zx*w + ddx(v)*zy*h = ddx(z)   即 x方向z變化量【ddx(z)】 = x方向u變化量【ddx(u)】 * 單位u變化對應的z變化量【zx】 +  x向v變化量【ddx(v)】 * 單位v變化對應的z變化量【zy】

    ddy(u)*zx*w + ddy(v)*zy*h = ddy(z)   同上

 

求解我就不寫了,相當於求解 方程組:

a* zx + b * zy = c

d* zx + e * zy = f 即利用a b c d e f六個已知量,計算兩個未知量zx\zy,但寫出來挺長,還不如自己推導便於理解

 

 方程ddx(u)*zx*w + ddx(v)*zy*h = ddx(z) 成立的意思是:

當前片段x方向變化對應紋理坐標uv兩個變化,而陰影紋理u、v的變化分別產生各自的z變化值,累加就是ddx(z)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM