一種用於生成實時陰影的技術。另外一種是Shadow Volume(原理複雜,編寫複雜,運算的複雜度與場景複雜度有關)
Shadow Map的基本實現方法:
1、將場景的深度值預先渲染到 以光源位置為原點、光線發射方向為觀察方向的投影坐標系中,形成深度紋理。
2、再次渲染場景的過程中,將每個片斷(像素)變換到前述眼坐標系中,並縮放到[0,1]的範圍內以便查詢紋理。
3、以當前片斷在眼坐標中的S、T坐標查詢深度紋理獲得深度值,將此深度值與當前片斷的R坐標進行比較,若R坐標大於深度值,則當前片斷在陰影中;否則當前片斷受光照。
上述是基本原理,希望能夠理解。
但令人失望的是,這種方法只適合於燈類型是聚光燈(Spot light )的場合。
如果燈類型是點光源(Point light)的話,則在第一步中需要生成的不是一張深度紋理,是一個立方深度紋理(cube texture)。
如果燈類型是方向光(Directional light)的話:第一步要做的工作是:
1、需要把視點(camera,view)的視椎體(camera frustum)搬到光源的view space
2、求得view matrix的各個參數:farZ參數為在view space中視椎體的maxZ-minZ;nearZ為0.0;upVector是方向光的任意一個垂直向量;lookAt是視椎體的“質心”
3、計算view matrix,把veiw matrix搬到平行投影坐標系(orthographic projection space)
Shadow Map可以正確地形成自陰影,但會出現幾種失真。
第一種失真是陰影邊緣有鋸齒。這容易明白,主要是因為深度紋理的解析度有限。
第二種是陰影內部甚至是整個場景都有不規則陰影。這是因為深度紋理每一個像素點的精度有限,當這個深度像素點在pixel shader里和當前處理的點做比較時,由於這兩點的z都很相近,產生z-fighting。可以通過在做比較時設定一個z偏移(即把這兩點人為的分開一點距離)來避免z-fighting;也可縮小投影視椎體大小(即減小fov,減小Zn和Zf的距離,特別的,儘量增大Zn,原因請參考投影矩陣的原理),提高深度紋理像素點的數值大小,從而提高精度。
此外還受深度紋理尺寸的限制,所形成的陰影邊緣鋸齒較嚴重。需要進行模糊處理,甚至是半影處理