這篇是本身看shadow map是的一些筆記,內容稍稍凌亂,若有錯誤請幫忙糾正html
參考Shadow Map Wiki、OpenGl Tutorial 16 : Shadow mapping、OpenGL Shadow Mapping
windows
從光源的視角渲染整個場景,得到Shadow Map。對點光源而言,透視投影的視角應該表現效果的角度相同,聚光燈相似。對於方向光,應該使用平行投影。經過此次渲染,深度緩存數據被保存下來,鑑於只須要深度信息,能夠禁止Color Buffer更新以及全部光源、貼圖計算來節省時間。緩存
深度數據通常保存在顯存中。 深度數據應該隨着場景中光源、物體的變更而修改,但有些狀況是不須要的,如攝像機變更。若是存在多光源,能夠對每一個光源保存各自單獨的一份。在不少實際應用中,可能只須要對場景中一部分物體進行深度採集。同時,爲了解決深度接近被繪製物體表面的狀況,能夠嘗試將深度偏移應用於此次渲染。 有些狀況下,能夠只渲染物體的背面。app
從攝像機自身的視角渲染場景,主要包含三個主要部分:less
(1) 計算光源視角下物體座標ide
爲了測試Shadow Map和點的關係,須要將場景中作座標轉換到光源座標系下,這個過程溝經過矩陣轉換( matrix multiplication)得到。物體在屏幕上的座標是經過作座標轉換得到,可是上面第二步須要光源座標系下的位置信息。將物體世界座標轉換到光源空間的矩陣相似於渲染管線中的MV矩陣以及投影矩陣。測試
將世界座標轉換到光源空間座標的矩陣與第一步中計算shadow map的矩陣相同(計算方式),經過齊次變換、透視除法將物體座標轉換到NDC座標系,經過映射將[-1,1]空間轉換到[0,1]空間,而後保存深度紋理中。上述轉換在vertex shader中進行,經過插值傳遞到pixel shader中。ui
(2) 對比光源視角的深度數據
獲取光源空間下物體的座標以後,根據x/y便可得到深度紋理中的數據,和Z對比來判斷是否爲陰影。this
在shader實現中,這個判斷是在pixel shader中實現。須要注意的是若是深度紋理在硬件中不能進行插值,陰影的變換會出現鋸齒。 能夠經過修改深度測試方式來實現產生soft edge,好比使用一組數值而不是簡單經過一個數值來判斷是否失敗。spa
(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.)
Shadow mapping的效果受深度紋理尺寸影響,比較常見的好比鋸齒或者陰影邊緣不連續等,通常狀況下能夠簡以經過增長 shadow map的尺寸來減小鋸齒,可是受限於內存和硬件狀況,通常是不可能的。解決這個繞開這個問題的改進技術:Cascaded Shadow Maps、Trapezoidal Shadow Maps 、Light Space Perspective Shadow maps、 Parallel-Split Shadow maps等。
Shadow Acne知乎
緣由:浮點計算精度以及採樣問題(多個點從Depth Texture同一個點得到數據,光線角度越大,越明顯)
處理: shadow bias,對物體深度進行稍稍的偏移
緣由: shadow bias is too much.
處理:背面剔除(不是太理解)
緣由:
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.
參考:Common Techniques to Improve Shadow Depth Maps
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.
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
Tightly fitting the light's projection to the view frustum increases the shadow map coverage,results in higher perspective aliasing.
The more closely together the planes are, the more precise the values in the depth buffer.
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