Screen Space Shadows(屏幕空間陰影)是Unity URP中通過屏幕空間數據實時計算陰影的技術,其核心原理是通過深度/法線信息重建世界座標後與陰影貼圖比較生成陰影。以下是詳細分析:
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
}
}
}
參數説明
|
參數
|
作用
|
典型值
|
技術原理
|
|
|
陰影最大渲染距離
|
50-100
|
超出距離後淡出陰影
|
|
|
級聯分層數
|
2/4
|
動態分配紋理分辨率
|
|
|
深度偏移量
|
0.01-0.1
|
防止自陰影偽影
|
|
|
法線偏移量
|
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需包含以下處理:
- 深度重建世界座標
- 光源空間座標轉換
- 陰影強度插值計算