【從UnityURP開始探索遊戲渲染】專欄-直達
Screen Space Shadows(屏幕空間陰影)是Unity URP中通過屏幕空間數據實時計算陰影的技術,其核心原理是通過深度/法線信息重建世界座標後與陰影貼圖比較生成陰影。以下是詳細分析:
技術原理與發展歷史
- 基礎原理:傳統Shadow Mapping需從光源視角生成深度圖,再與攝像機視角深度比較。而Screen Space Shadows直接在屏幕空間計算,利用_CameraDepthTexture和_MainLightShadowmapTexture進行深度比較。
-
技術演進:
- 早期採用標準Shadow Mapping存在精度問題
- 引入級聯陰影(CSM)解決大場景問題
- URP 14+版本通過ScreenSpaceShadowResolvePass實現優化
- 性能對比:相比傳統方案,屏幕空間陰影減少Overdraw但增加Depth Prepass開銷。
原理
核心原理
-
雙階段渲染機制
- 深度圖生成階段:從光源視角渲染場景,將最近表面深度值存儲到
_MainLightShadowmapTexture中 - 陰影判定階段:在攝像機視角渲染時,將像素座標轉換到光源空間,比較當前深度與ShadowMap中的深度值,若當前深度更大則判定為陰影區域
- 深度圖生成階段:從光源視角渲染場景,將最近表面深度值存儲到
-
級聯陰影優化CSM
通過將視錐體劃分為多個層級(如4級),近處使用高分辨率ShadowMap,遠處使用低分辨率,平衡性能與精度
關鍵實現步驟
-
ShadowCaster Pass
hlsl Pass { Tags {"LightMode"="ShadowCaster"} HLSLPROGRAM #pragma vertex ShadowPassVertex #pragma fragment ShadowPassFragment #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" // 應用深度偏移防止自陰影偽影 float3 _ShadowBias; // x:DepthBias, y:NormalBias ENDHLSL }該Pass專用於生成深度圖,通過
_ShadowBias參數控制深度偏移 -
光源空間矩陣計算
構建
_MainLightWorldToShadow矩陣,將世界座標轉換到光源裁剪空間:csharp Matrix4x4 worldToView = light.transform.worldToLocalMatrix; Matrix4x4 viewToProj = GL.GetGPUProjectionMatrix(light.projectionMatrix, false); _MainLightWorldToShadow = viewToProj * worldToView;該矩陣用於在着色器中計算陰影座標
-
陰影採樣與混合
在片元着色器中通過PCF(Percentage Closer Filtering)實現軟陰影:
hlsl float SampleShadowmap(float4 shadowCoord) { float shadow = 0; for(int i = 0; i < 4; i++) { shadow += SAMPLE_TEXTURE2D_SHADOW( _MainLightShadowmapTexture, sampler_MainLightShadowmapTexture, shadowCoord.xyz + poissonDisk[i] * _ShadowSoftness ); } return shadow / 4; }使用泊松圓盤採樣實現邊緣柔化
完整URP示例
-
ShadowFeature.cs
using UnityEngine.Rendering.Universal; public class ShadowFeature : ScriptableRendererFeature { class ShadowPass : ScriptableRenderPass { public override void Execute(ScriptableRenderContext context, ref RenderingData data) { // 1. 配置光源參數 var shadowLight = data.lightData.mainLightIndex; if (shadowLight == -1) return; // 2. 渲染ShadowMap CommandBuffer cmd = CommandBufferPool.Get("ShadowMap"); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } } } -
ShadowShader.shader
Shader "Custom/ShadowReceiver" { Properties { _ShadowStrength("Shadow Strength", Range(0,1)) = 0.5 } SubShader { Pass { HLSLPROGRAM #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" float _ShadowStrength; float4 frag(v2f i) : SV_Target { float shadow = MainLightRealtimeShadow(i.shadowCoord); return lerp(1, shadow, _ShadowStrength); } ENDHLSL } } }
參數説明
| 參數 | 作用 | 典型值 | 技術原理 |
|---|---|---|---|
Shadow Distance |
陰影最大渲染距離 | 50-100 | 超出距離後淡出陰影 |
Cascade Count |
級聯分層數 | 2/4 | 動態分配紋理分辨率 |
Depth Bias |
深度偏移量 | 0.01-0.1 | 防止自陰影偽影 |
Normal Bias |
法線偏移量 | 0.5-2.0 | 改善尖鋭邊緣陰影 |
該實現結合了URP的ShadowCaster管線與自定義Shader,通過級聯陰影和PCF濾波達到平衡性能與質量的效果
參數説明與用例
| 參數 | 説明 | 典型值 |
|---|---|---|
| Strength | 陰影濃度 | 0.5-1.0 |
| Bias | 防止自陰影 | 0.05-0.2 |
| Normal Bias | 法線偏移 | 0.3-0.7 |
| Resolution | 精度等級 | High/Very High |
實際應用場景:
- 動態物體陰影:配合CSM實現高質量移動物體陰影
- 性能敏感場景:中低端設備可降低Resolution至Medium
- 特效增強:結合Decal系統實現彈孔等動態貼花效果
完整配置流程
- 創建Renderer Feature並附加到URP Asset
- 編寫Shader處理深度比較邏輯
- 通過Frame Debugger驗證陰影生成階段
- 調整Bias參數消除陰影瑕疵
關鍵Shader需包含以下處理:
- 深度重建世界座標
- 光源空間座標轉換
- 陰影強度插值計算
【從UnityURP開始探索遊戲渲染】專欄-直達
(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)