這篇是自己看shadow map是的一些筆記,內容稍稍凌亂,如有錯誤請幫忙糾正
1.常見陰影處理方式
- Shadow Map : using Z-Buffer
Shadow Mapping 的原理與實踐 - Shadow Volume : using stecil Z-Buffer
Shadow Volume Wiki
2. Shadow Map
參考Shadow Map Wiki、OpenGl Tutorial 16 : Shadow mapping、OpenGL Shadow Mapping
2.1 創建Shadow Map
從光源的視角渲染整個場景,獲得Shadow Map。對點光源而言,透視投影的視角應該表現效果的角度相同,聚光燈類似。對於方向光,應該使用平行投影。通過這次渲染,深度緩存數據被保存下來,鑒於只需要深度信息,可以禁止Color Buffer更新以及所有光源、貼圖計算來節省時間。
深度數據一般保存在顯存中。 深度數據應該隨着場景中光源、物體的變動而修改,但有些情況是不需要的,如攝像機變動。如果存在多光源,可以對每個光源保存各自單獨的一份。在很多實際應用中,可能只需要對場景中一部分物體進行深度采集。同時,為了解決深度接近被繪制物體表面的情況,可以嘗試將深度偏移應用於這次渲染。 有些情況下,可以只渲染物體的背面。
2. 2 渲染場景
從攝像機自身的視角渲染場景,主要包含三個主要部分:
(1) 計算光源視角下物體坐標
為了測試Shadow Map和點的關系,需要將場景中做坐標轉換到光源坐標系下,這個過程溝通過矩陣轉換( matrix multiplication)獲得。物體在屏幕上的坐標是通過做坐標轉換獲得,但是上面第二步需要光源坐標系下的位置信息。將物體世界坐標轉換到光源空間的矩陣類似於渲染管線中的MV矩陣以及投影矩陣。
將世界坐標轉換到光源空間坐標的矩陣與第一步中計算shadow map的矩陣相同(計算方式),通過齊次變換、透視除法將物體坐標轉換到NDC坐標系,通過映射將[-1,1]空間轉換到[0,1]空間,然后保存深度紋理中。上述轉換在vertex shader中進行,通過插值傳遞到pixel shader中。
(2) 對比光源視角的深度數據
獲取光源空間下物體的坐標之后,根據x/y即可獲得深度紋理中的數據,和Z對比來判斷是否為陰影。
- 如果z大於D(x,y) , 物體是在遮擋物體之后,標記為失敗,需要作為陰影來處理
- 如果(x,y)是在深度紋理范圍之外,由程序決定是否將其列入陰影范圍(一般默認為在)
在shader實現中,這個判斷是在pixel shader中實現。需要注意的是如果深度紋理在硬件中不能進行插值,陰影的變換會出現鋸齒。 可以通過修改深度測試方式來實現產生soft edge,比如使用一組數值而不是簡單通過一個數值來判斷是否失敗。
(3) 制物體或者陰影
繪制帶有shadow的場景有幾種方式。如果在shader中實現, depth map test 可以在pixel shader中進行,並根據其結果繪制物體或者陰影。如果不能再shadow中進行:
-
Render the entire scene in shadow. For the most common lighting models (see Phong reflection model) this should technically be done using only the ambient component of the light, but this is usually adjusted to also include a dim diffuse light to prevent curved surfaces from appearing flat in shadow.
-
Enable the depth map test, and render the scene lit. Areas where the depth map test fails will not be overwritten, and remain shadowed.
-
An additional pass may be used for each additional light, using additive blending to combine their effect with the lights already drawn. (Each of these passes requires an additional previous pass to generate the associated shadow map.)
2.3 Shadow map real-time implementations
Shadow mapping的效果受深度紋理尺寸影響,比較常見的比如鋸齒或者陰影邊緣不連續等,一般情況下可以簡以通過增加 shadow map的尺寸來減少鋸齒,但是受限於內存和硬件情況,一般是不可能的。解決這個繞開這個問題的改進技術:Cascaded Shadow Maps、Trapezoidal Shadow Maps 、Light Space Perspective Shadow maps、 Parallel-Split Shadow maps等。
1. Shadow Acne
Shadow Acne知乎
原因:浮點計算精度以及采樣問題(多個點從Depth Texture同一個點獲得數據,光線角度越大,越明顯)
處理: shadow bias,對物體深度進行稍稍的偏移
2. Peter Panning
原因: shadow bias is too much.
處理:背面剔除(不是太理解)
3. Depth Map Aliasing
原因:
Because the depth map has a fixed resolution the depth frequently spans more than one fragment per texel. As a result multiple fragments sample the same depth value from the depth map and come to the same shadow conclusions, which produces these jagged blocky edges.
處理:
Percentage Closer Filtering
Smoothie
Variance Shadow maps.
3. Techniques to Improve Shadow Map
參考:Common Techniques to Improve Shadow Depth Maps
3.1 Process
3.2 Shadow Map Artifacts
1. Perspective Aliasing
It occurs when the mapping of pixels in view space to texels in the shadow map is not a one-to-one ratio. This is because pixels close to the near plane are closer together and require a higher shadow map resolution.
Perspective shadow maps (PSMs) and light space perspective shadow maps (LSPSMs) attempt to address perspective aliasing by skewing the light's projection matrix in order to place more texels near the eye where they are needed. Cascaded shadow maps (CSMs) are the most popular technique for dealing with perspective aliasing.
2. Projective Aliasing
Projective aliasing occurs when the surface normal is orthogonal to the light; these surfaces should be receiving less light based on diffuse lighting equations.
3. Shadow Acne and Erroneous Self-Shadowing
4. Peter Panning
Peter Panning is aggravated when there is insufficient precision in the depth buffer. Calculating tight near planes and far planes also helps avoid Peter Panning.
3.3 Improve Techniques
1. Slope-Scale Depth Bias
polygons with steep slopes (relative to the light) suffer more from projective aliasing than polygons with shallow slopes (relative to the light). Because of this, each depth map value may need a different offset depending on the polygon's slope relative to the light.
https://www.gamedev.net/topic/662625-slope-scale-depth-bias-shadow-map-in-hlsl/#entry5191604
2. Calculating a Tight Projection
Tightly fitting the light's projection to the view frustum increases the shadow map coverage,results in higher perspective aliasing.
3. Calculating the Near Plane and Far Plane
The more closely together the planes are, the more precise the values in the depth buffer.
- AABB-Based Near Plane and Far Plane is test.
- Frustum-Based Near Plane and Far Plane
- Light Frustum Intersected with Scene to Calculate Near and Far Planes
4. Moving the Light in Texel-Sized Increments
As the camera moves, the pixels along the shadows' edges brighten and darken. This cannot be seen in still images, but it is very noticeable and distracting in real time。
For directional lights, the solution to this problem is to round the minimum/maximum value in X and Y (that make up the orthographic projection bounds) to pixel size increments. This can be done with a divide operation, a floor operation, and a multiply.
參考
OpenGL Shadow Mapping
OpenGl Tutorial 16 : Shadow mapping
Shadow Map Wiki
Shadow Acne知乎
Common Techniques to Improve Shadow Depth Maps
Cascaded Shadow Maps
Percentage Closer Filtering