改善陰影深度圖的常見技巧
1978年首次推出的陰影地圖是將陰影新增至遊戲的常見技術。 30年後,儘管硬體和軟體方面有進步,但陰影成品(即閃閃發光的邊緣、透視別名和其他精確度問題)仍然存在。
本技術文章提供一些常見的陰影深度地圖演算法和常見成品的概觀,並說明數種技術,範圍從基本到中繼不等,可用來提高標準陰影地圖的品質。 將基本陰影對應新增至標題通常很簡單,但了解陰影成品的細微差別可能具有挑戰性。 本技術文章是針對已實作陰影的中繼圖形開發人員所撰寫,但無法完全了解為何會出現特定成品,且不確定如何解決它們。
選取正確的技術來減輕特定成品是非有趣的。 當解決陰影圖缺點時,質量的差異可能會令人印象深刻(圖 1)。 正確實作這些技術可大幅改善標準陰影。 本文中說明的技術是在 DirectX SDK 的 CascadedShadowMaps11 範例中實作。
圖 1. 實作本文所述的技術之後,具有嚴重成品的陰影(左),以及陰影
陰影深度地圖檢閱
陰影深度對應演算法是雙階段演算法。 第一個階段會在光線空間中產生深度地圖。 在第二個階段中,此地圖可用來比較每個圖元在光線空間中的深度與光線空間深度對應中的對應深度。
圖 2. 陰影場景的主要部分
傳遞 1
圖 2 顯示場景。 在第一次傳遞中(圖 3),幾何會從光線的角度轉譯成深度緩衝區。 更具體來說,頂點著色器會將幾何轉換成淺視圖空間。
第一個階段的結束結果是深度緩衝區,其中包含從光線角度的場景深度資訊。 這現在可以在傳遞 2 中使用,以判斷從光線遮蔽的圖元。
圖 3. 基本陰影對應的第一個階段
傳遞 2
在第二階段(圖 4),頂點著色器會轉換每個頂點兩次。 每個頂點都會轉換成相機的檢視空間,並傳遞至圖元著色器作為位置。 每個頂點也會由光線的檢視投影紋理矩陣轉換,並以紋理座標的形式傳遞至圖元著色器。 檢視投影紋理矩陣是一個矩陣,用來在傳遞 1 中轉譯場景,並加上一個額外的轉換。 這是一個轉換,從檢視空間 (–1 到 1 英 X 和 Y) 到紋理空間 (0 到 1 英 X, 1 到 Y 中的 0 到 0) 的轉換。
圖元著色器會接收插補位置與插補紋理座標。 執行深度測試所需的所有項目現在都位於這個紋理座標中。 現在可以使用 X 和 Y 紋理座標編製深度緩衝區的索引,並將產生的深度值與 Z 紋理座標進行比較,以執行深度測試。
圖 4。 基本陰影對應的第二階段
陰影對應成品
陰影深度對應演算法是最廣泛使用的即時陰影演算法,但仍會產生數個需要緩和的成品。 接下來會摘要說明可能發生的成品類型。
檢視方塊別名
檢視方塊別名是常見的成品,如圖 5 所示。 當檢視空間中的像素對應到陰影圖中的紋素不是一對一比例時,就會發生此情況。 這是因為接近接近平面的圖解析元較接近,而且需要較高的陰影地圖解析度。
圖 6 顯示陰影圖和檢視。 接近眼睛時,圖元會更接近一起,而且許多像素會對應到相同的陰影紋素。 遠平面的圖元會分散出來,藉此減少檢視方塊別名。
圖 5。 高透視別名 (左) 與低透視別名 (右)
針對左邊的影像,檢視方塊別名較高;太多眼睛空間圖元對應至相同的陰影對應紋素。 在右側的影像中,透視別名很低,因為眼睛空間圖元與陰影對應紋素之間有 1:1 的對應。
圖 6。 使用陰影對應檢視 frustum
遠平面中的淺圖元代表低透視鋸齒,而近平面中的深色圖元則代表高透視鋸齒。
陰影地圖解析度也可能太高。 雖然解析度較不明顯,但它還是會導致小型物件,例如電話線,而不是投射陰影。 此外,由於紋理存取模式,解析度太高可能會導致嚴重的效能問題。
透視陰影地圖(PSM)和光線空間透視陰影地圖(LSPSM)會嘗試藉由扭曲光線的投影矩陣來解決透視鋸齒問題,以便將更多紋素放在所需的眼睛附近。 不幸的是,這兩種技術都無法解決檢視方塊別名。 將眼睛空間圖元對應到陰影圖中紋素所需的轉換參數化,無法由線性扭曲系結。 需要對數參數化。 PSM 將太多的細節放在眼睛附近,導致遙遠的陰影品質低,甚至消失。 LSPSM 在眼睛附近增加解析度之間尋找中間點,併為遠離物體留下足夠的細節,做得更好。 這兩種技術都會在某些場景組態中變質為正視陰影。 雖然這很昂貴,但可以藉由為檢視 frustum 的每個臉部轉譯個別陰影圖來反轉此變性。 對數檢視方塊陰影對應 (LogPSM) 也會針對檢視範圍呈現個別的地圖。 這項技術使用非線性點陣化將更多紋素放在眼睛附近。 D3D10 和 D3D11 類別的硬體不支援非線性點陣化。 如需這些技術和演算法的詳細資訊,請參閱參考一節。
串聯陰影圖 (CSM) 是處理透視鋸齒的最常用技術。 雖然 CSM 可以與 PSM 和 LSPSM 結合,但不需要。 使用 CSM 修正檢視方塊別名錯誤,已解決隨附文章 串聯陰影對應。
投影別名
投影別名比檢視方塊別名更難顯示。 圖 7 中反白顯示的虛偽陰影示範投影鋸齒錯誤。 當相機空間中的紋素與淺色空間中的紋素之間的對應不是一對一的比例時,就會發生投影別名:這是因為幾何相對於光線相機的方向。 投影鋸齒會在幾何的正切平面與光線平行時發生。
圖 7。 高投影別名與低投影別名
用來減輕檢視方塊別名錯誤的技術也會降低投影鋸齒。 當表面正常與光線正交時,就會發生投影鋸齒:這些表面應該根據擴散光源方程式接收較少的光線。
陰影瘡和錯誤的自我遮蔽
陰影瘡(圖 8)是錯誤自我遮蔽的詞彙,會在陰影圖將整個材質的深度量化時發生。 當著色器比較實際深度與這個值時,它可能會像未遮蔽一樣自我遮蔽。
陰影瘡的另一個原因是淺色空間中的紋素與深度圖中對應的紋素深度非常接近,精確度錯誤導致深度測試錯誤錯誤失敗。 此精確度差異的其中一個原因是深度圖是由固定函式點陣化硬體所計算,而所比較的深度是由著色器計算。 投影鋸齒也會導致陰影瘡。
圖 8。 陰影瘡成品
如左影像所示,某些像素無法進行深度測試,並建立斑點成品和Moiré模式。 為了減少錯誤的自我遮蔽,近距離平面和遠平面的光空間檢視範圍應盡可能嚴格地計算。 斜率縮放深度偏差和其他類型的偏差是用來減輕陰影瘡的其他解決方案。
彼得·潘寧
彼得·潘寧這個詞從一個兒童書名中衍生出它的名字,他的影子變得分離,誰可以飛。 此成品會使遺漏陰影的物件似乎與表面上方浮動(圖 9)。
圖 9。 Peter Panning 成品
在左側的影像中,陰影會與對象中斷連結,以建立浮動效果。
移除表面瘡的一種技術是增加一些價值在光線空間中的圖元位置:這稱為新增深度位移。 當使用的深度位移太大時,Peter Panning 會產生結果。 在此情況下,深度位移會導致深度測試錯誤地通過。 就像陰影瘡一樣,當深度緩衝區的精確度不足時,彼得·潘寧會加重。 計算緊近平面和遠平面也有助於避免彼得·潘寧。
改善陰影圖的技術
將陰影新增至標題是一個程式。 第一個步驟是讓基本陰影地圖運作。 第二個是確保以最佳方式完成所有基本計算:frusta 能盡可能緊密地調整,近/遠平面會緊密配合,使用斜率縮放偏差等等。 一旦啟用基本陰影,並盡可能好看,開發人員就更清楚哪些演算法需要哪些演算法,才能讓陰影達到足夠的逼真度。 在本節中,可能需要的基本秘訣,以取得查看其最佳效果的基本陰影地圖。
斜率刻度深度偏差
如前所述,自我遮蔽可能導致陰影瘡。 新增太多偏差可能會導致彼得·潘寧。 此外,具有陡峭斜率的多邊形(相對於光線)比具有淺斜率的多邊形(相對於光線)更遭受投影鋸齒。 因此,每個深度地圖值可能需要不同的位移,視多邊形相對於光線的斜率而定。
Direct3D 10 硬體可以根據相對於檢視方向的斜率來偏差多邊形。 這具有將大型偏差套用至多邊形的效果,該多邊形會以邊緣方式檢視到光線方向,但不會將任何偏差套用至直接面對光線的多邊形。 圖 10 說明在針對相同不偏斜率進行測試時,兩個鄰近圖元如何在陰影和未遮蔽之間交替。
圖 10。 與不偏斜深度相比,斜率縮放深度偏差
計算緊密投影
緊密地將光線的投影貼合到檢視範圍會增加陰影地圖覆蓋。 圖 11 說明使用任意投影或將投影調整為場景界限,會導致較高的透視別名。
圖 11。 任意陰影 frustum 和陰影 frustum 適合場景
檢視從光線的觀點來看。 梯形體代表檢視相機的 frustum。 在影像上繪製的網格線代表陰影圖。 右側的影像顯示,相同的解析度陰影圖在與場景更緊密地配合時,會建立更多的紋素涵蓋範圍。
圖 12 說明正確配合的 frustum。 為了計算投影,構成檢視 Frustum 的八點會轉換成光空間。 接下來,找到 X 和 Y 中的最小值和最大值。 這些值構成正則投影的界限。
圖 12. 陰影投影適合用來檢視 frustum
您也可以將 frustum 裁剪到場景 AABB,以取得更緊密的界限。 在所有情況下都不建議這樣做,因為這可能會將光線相機的投影大小從畫面變更為畫面。 許多技術,例如移動光紋素大小的增量一節中所述的技術,在光線投影的大小在每個畫面中維持不變時,提供更好的結果。
計算近平面和遠平面
近平面和遠平面是計算投影矩陣所需的最終部分。 平面越接近,深度緩衝區中的值越精確。
深度緩衝區可以是16位、24位或32位,其值為0到1。 一般而言,深度緩衝區是固定點,接近接近平面的值會比接近遠平面的值更緊密地分組在一起。 深度緩衝區可用的精確度程度取決於接近平面與遠平面的比例。 使用最緊密的近/遠平面可能會允許使用16位深度緩衝區。 16 位深度緩衝區可以減少記憶體的使用,同時提高處理速度。
AABB 型近平面和遠平面
計算近平面和遠平面的簡單天真方法是將場景的周框體積轉換成光空間。 最小的 Z 座標值是接近平面,而最大的 Z 座標值為遠平面。 對於場景和光線的許多組態,此方法就已足夠。 不過,最壞的情況案例可能會導致深度緩衝區的精確度大幅遺失;圖 13 顯示這類案例。 在這裡,近平面到遠平面的範圍是必要平面的四倍。
圖 13 中的檢視範圍是故意選擇很小的。 小型檢視範圍會顯示在非常大的場景中,其中包含從檢視相機延伸出來的柱子。 針對近遠平面使用場景AABB不是最佳。 串聯陰影地圖技術文章中所述的 CSM 演演算法必須計算非常小的機面的近遠平面。
圖 13. 以場景AABB為基礎的近遠平面
以 Frustum 為基礎的近平面和遠平面
計算近平面和遠平面的另一個技巧是將 frustum 轉換成光空間,並使用 Z 中的最小和最大值作為接近和遠平面。 圖 14 說明此方法的兩個問題。 首先,計算過於保守,如 frustum 延伸超出場景幾何時所示。 其次,近平面可能太緊,導致影子投手被裁剪。
圖 14. 以檢視 frustum 為基礎的近遠平面
光 Frustum 與場景交集以計算近遠平面
圖 15 顯示計算近遠平面的正確方式。 使用光空間中檢視 Frustum 的 X 和 Y 座標下限和最大值,計算出四個正向光層的正視平面。 正交檢視 frustum 的最後兩個平面是接近和遠平面。 為了尋找這些平面,場景的界限會裁剪到四個已知的光雲平面上。 新裁剪界限中最小和最大的 Z 值分別代表近平面和遠平面。
執行這項作業的程式代碼位於 CascadedShadowMaps11 範例中。 構成世界ABB的八分被轉化為光空間。 將點轉換成淺色空間可簡化裁剪測試。 光 frustum 的四個已知平面現在可以表示為線條。 光空間中周框音量的場景可以表示為六個四邊。 然後,這 6 個四邊形可以變成 12 個三角形,以進行以三角形為基礎的裁剪。 三角形會根據檢視 frustum 的已知平面裁剪(這些是 X 和 Y 中的水平和垂直線在光線空間中)。 在 X 和 Y 中找到交集點時,會在該點裁剪 3D 三角形。 所有裁剪三角形的最小和最大 Z 值都是接近平面和遠平面。 CascadedShadowMaps11 範例示範如何在 ComputeNearAndFar 函式中執行此裁剪。
還有兩種技術可用來計算最接近和遠平面最緊密的可能。 這些技術不會顯示在 CascadedShadowMaps 範例中。
即使是更緊密的近遠平面,也可以藉由將場景中的階層或場景中的個別物件與光線浮點相交來計算。 這在計算上會更加複雜。 雖然 CascadedShadowMaps11 範例中沒有說明,但對於某些磚而言,這可能是有效的技術。
遠平面的計算方式是採用下列最小值:
- 光空間中檢視範圍的最大深度。
- 檢視範圍和場景AABB交集的最大深度。
當搭配串聯陰影對應使用時,此方法可能會造成問題,因為有可能在檢視範圍外部編製索引。 在此情況下,陰影圖可能遺漏幾何。
圖 15. 以光浮點數和場景周框幾何四個計算平面交集為基礎的近遠平面
以紋素大小遞增移動光線
陰影圖中的常見成品是閃閃發光的邊緣效果。 當相機移動時,沿著陰影邊緣的圖元會變亮和變暗。 這在仍然的圖像中看不到,但它是非常明顯和分散即時的。 圖 16 醒目提示此問題,圖 17 顯示陰影邊緣的外觀。
發生閃閃發光邊緣錯誤,因為每次相機移動時,都會重新計算光線投影矩陣。 這會在產生的陰影對應中產生細微的差異。 下列所有因素都會影響建立以系結場景的矩陣。
- 檢視大小
- 檢視方向
- 光線的位置
- 相機的位置
每次此矩陣變更時,陰影邊緣可能會變更。
圖 16. 閃閃發光的陰影邊緣
當相機從左至右移動時,陰影框線的圖元會進出陰影。
圖 17. 沒有閃閃發光邊緣的陰影
當相機從左至右移動時,陰影邊緣會保持不變。
針對方向光源,此問題的解決方案是將 X 和 Y 中的最小值 /最大值四捨五入(構成正向投影界限)到圖元大小增量。 這可以透過除法運算、樓層作業和乘法來完成。
vLightCameraOrthographicMin /= vWorldUnitsPerTexel;
vLightCameraOrthographicMin = XMVectorFloor( vLightCameraOrthographicMin );
vLightCameraOrthographicMin *= vWorldUnitsPerTexel;
vLightCameraOrthographicMax /= vWorldUnitsPerTexel;
vLightCameraOrthographicMax = XMVectorFloor( vLightCameraOrthographicMax );
vLightCameraOrthographicMax *= vWorldUnitsPerTexel;
vWorldUnitsPerTexel 值是透過採用檢視 frustum 的系結來計算,並除以緩衝區大小。
FLOAT fWorldUnitsPerTexel = fCascadeBound /
(float)m_CopyOfCascadeConfig.m_iBufferSize;
vWorldUnitsPerTexel = XMVectorSet( fWorldUnitsPerTexel, fWorldUnitsPerTexel, 0.0f, 0.0f );
將檢視範圍的大小上限限定為鬆散,以符合正向投影。
請務必注意,使用這項技術時,紋理的寬度和高度大於 1 圖元。 這樣會防止陰影座標在陰影圖外部編製索引。
背面和正面
陰影地圖應該使用標準後臉撲殺來轉譯,此程式會略過檢視者看不到的物件點陣化,並加快場景的轉譯速度。 另一個常見選項是轉譯已啟用正面撲殺的陰影對應,這表示消除查看器面對的物件。 其自變數是它有助於自我遮蔽,因為組成物件背面的幾何稍微位移。 這個想法有兩個問題。
- 任何具有不當正面或後臉幾何的對象都會造成陰影圖中的成品。 不過,有不正確的正面或後臉幾何會導致其他問題,因此可以放心地假設正面和後臉幾何已正確完成。 為樹葉等以精靈為基礎的幾何建立後臉可能不切實際。
- 彼得·潘寧和陰影間距接近牆等物件的基底更可能發生,因為陰影深度差異太小。
陰影地圖-易記幾何
建立在陰影地圖中運作良好的幾何,可在對抗彼得·潘寧和陰影瘡等成品時提供更多彈性。
硬邊緣對自我遮蔽有問題。 邊緣尖附近的深度差異非常小。 即使是小位移也會造成物件失去陰影(圖 18)。
圖 18. 尖銳邊緣導致成品源於低深度差異與位移
牆等狹窄的對象應該有背部,即使它們永遠不會可見。 這將增加深度差異。
請務必確定幾何正向的方向正確;也就是說,物件的外部應該正向,而對象的內部應該是正面的。 這對於啟用後臉撲殺以及對抗深度偏差效果而言非常重要。
重疊的陰影圖
另請參閱 串聯陰影圖和 CascadedShadowMaps11 範例應用程式。 此範例示範串聯陰影圖 (CSM) 演算法,以及數種技術,可用來有效率地使用陰影圖。
您可以在 DirectX 軟體開發工具套件 (SDK) 中找到範例。 或者,您可以執行 Web 搜尋,以在 GitHub 上尋找它。
摘要
本文所述的技術可用來提高標準陰影圖的品質。 下一個步驟是查看可與標準陰影對應搭配運作的技術。 建議 CSM 作為對抗檢視方塊鋸齒的優越技術。 更接近篩選或變異數陰影貼圖的百分比可用來軟化陰影邊緣。 如需詳細資訊, 請參閱串聯陰影地圖 技術文章。
唐納利、W.和勞裡森,A。 變異數陰影對應。 互動式 3D 圖形研討會、2006 年互動式 3D 圖形和遊戲研討會。 2006,第 161–165 頁。
恩格爾, 沃夫剛 F. 第 4 節。 串聯陰影對應。 著色器X5, 進階轉譯技術,沃爾夫岡 F. Engel,Ed。 查理斯河媒體,波士頓,馬薩諸塞州。 2006. pp. 197–206.
斯塔明格、馬克和德里塔基斯,喬治。 檢視方塊陰影地圖。 計算機圖形和互動式技術國際會議, 第29屆計算機圖形和互動式技術年會。 2002,pp 557–562。
Wimmer、M.、Scherzer、D.和 Purgathofer、W. 淺色空間透視陰影地圖。 轉譯的歐文攝影研討會。 2004. 修訂為 2005 年 6 月 10 日。 Technische Universität Wien.