博客 / 詳情

返回

【URP】Unity[後處理]景深DepthOfField

【從UnityURP開始探索遊戲渲染】專欄-直達

Unity URP中的景深(Depth of Field)是一種模擬真實相機光學特性的後處理效果,通過模糊近處或遠處的物體來突出焦點區域,增強畫面層次感和真實感。其發展經歷了從Built-in管線的基礎實現到URP/HDRP的物理化演進過程,早期採用高斯模糊近似,現代則引入散景(Bokeh)等更接近真實光學特性的算法。

核心作用

  • 視覺引導‌:突出主體對象,弱化背景干擾
  • 增強真實感‌:模擬攝影鏡頭物理特性
  • 藝術表現‌:通過散景光斑創造氛圍

實現原理

基於深度緩衝區計算彌散圈(Circle of Confusion),通過多Pass模糊處理非焦點區域。URP提供兩種模式:

  • 高斯模式‌:性能優先,僅支持遠場模糊
  • 散景模式‌:質量優先,模擬光圈葉片光學特性

Unity URP中的景深(Depth of Field)效果基於光學透鏡的物理特性模擬,其核心原理是通過計算混淆圈(Circle of Confusion, CoC)來實現虛實分層。

光學基礎原理

  • 透鏡成像特性‌:真實相機中,只有特定距離(焦平面)的物體能清晰成像,其他距離的物體會在傳感器上形成彌散圓斑(CoC),其直徑與光圈大小成正比。URP通過高斯模糊或散景模式模擬這一現象,前者計算效率高但物理準確性較低,後者更接近真實光學效果。
  • CoC計算‌:每個像素的模糊程度取決於其深度值與焦點距離的差值。計算公式為:

    CoC = |(d_l f (z - z_f)) / (z * (f + z_f))|

    其中d_l為光圈直徑,f為焦距,z為物體距離,z_f為對焦平面距離5。URP在Shader中通過深度紋理(_CameraDepthTexture)獲取每個像素的z值。

URP實現流程

  • 預處理階段‌:生成包含CoC數據的紋理。通過比較像素深度與焦點距離,標記需要模糊的區域(近景或遠景)。示例參數包括:

    csharp
    [Range(0.1f, 100f)] public float focusDistance = 10f;// 焦點距離
    [Range(0.1f, 10f)] public float focusRange = 3f;// 清晰範圍
    [Range(1f, 10f)] public float bokehRadius = 4f;// 散景強度
  • 模糊處理‌:根據CoC數據對非焦點區域進行分層模糊。URP提供兩種方式:

    • 高斯模糊‌:使用降採樣+上採樣的多Pass模糊,適合性能敏感場景
    • 散景模糊‌:模擬光學透鏡的虛化效果,在高亮區域生成光斑(Bokeh),需額外計算亮度閾值
  • 合成階段‌:將模糊後的圖像與原圖按CoC權重混合。清晰區域的權重為,模糊區域根據CoC半徑插值。

示例代碼邏輯

以下為簡化版CoC計算Shader代碼片段:

hlsl
float4 Frag(Attributes input) : SV_Target {
    float depth = SampleDepthTexture(_CameraDepthTexture, input.uv);
    float linearDepth = Linear01Depth(depth);
    float coc = saturate(abs(linearDepth - _FocusDistance) / _FocusRange);
    return float4(coc, coc, coc, 1);
}

該代碼生成CoC圖,白色表示完全模糊,黑色表示完全清晰。完整實現還需結合多尺度模糊和色調映射處理。

性能優化

  • 降採樣‌:在Half/Quarter分辨率下計算模糊,減少像素處理量
  • 動態調整‌:根據平台性能切換高斯/散景模式,移動端建議使用高斯模糊
  • 焦點追蹤‌:通過射線檢測動態更新focusDistance,實現自動對焦效果

完整實現流程

  • URP_DepthOfFieldSetup.cs

    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    
    public class URP_DepthOfFieldSetup : MonoBehaviour
    {
        [SerializeField] private VolumeProfile volumeProfile;
    
        void Start()
        {
            var depthOfField = volumeProfile.Add<DepthOfField>();
            depthOfField.mode.value = DepthOfFieldMode.Bokeh;
            depthOfField.focusDistance.value = 5f;
            depthOfField.aperture.value = 5.6f;
            depthOfField.focalLength.value = 50f;
        }
    }
  • DoF_Shader.shader

    Shader "Custom/DoF"
    {
        Properties { _MainTex ("Texture", 2D) = "white" {} }
        SubShader
        {
            Pass {
                // 深度採樣與模糊處理
            }
        }
    }

參數詳解

參數 作用 典型值
Focus Distance 焦點平面距離 3-10m
Aperture 光圈大小(f值) 1.4-16
Focal Length 鏡頭焦距(mm) 35-200mm
Blade Count 光圈葉片數 5-9片

實際應用案例

  • 角色特寫‌:聚焦角色面部,模糊環境
  • 場景過渡‌:動態調整焦點實現鏡頭語言
  • UI突出‌:模糊遊戲界面背景

性能優化建議

  • 移動端使用高斯模式
  • 控制Blur Iterations≤3
  • 採用DownSample降低分辨率

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

發佈 評論

Some HTML is okay.