博客 / 詳情

返回

【URP】Unity[RendererFeatures]屏幕空間陰影ScreenSpaceShadows

【從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開始探索遊戲渲染】專欄-直達
(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.