Stories

Detail Return Return

【光照】[PBR][漫反射]實現方法對比 - Stories Detail

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

URP BRDF漫反射方法對比

方法名稱 數學公式 特點 性能消耗 適用場景
Lambert $L_d = k_d * max(0, N·L)$ 經典模型,能量不守恆 ★☆☆ 移動端低配
Half-Lambert $L_d = k_d * (0.5*(N·L)+0.5)^2$ 增強暗部細節 ★★☆ 卡通渲染
Disney Diffuse 複雜能量守恆公式 物理準確,計算複雜 ★★★ PC/主機高品質
Burley Diffuse 基於微表面理論 PBR標準,次表面散射近似 ★★★ 金屬/粗糙度工作流

具體實現方法及示例

Lambert模型(URP默認)

hlsl
// Lighting.hlsl 中的實現
half3 DiffuseLambert(half3 diffuseColor)
{
    return diffuseColor / PI; // 能量歸一化
}

// 實際調用示例
half NdotL = saturate(dot(normalWS, light.direction));
half3 lambert = DiffuseLambert(_BaseColor.rgb) * NdotL;

Half-Lambert(Valve改進版)

hlsl
half3 DiffuseHalfLambert(half3 diffuseColor, half NdotL)
{
    half wrap = 0.5 * (NdotL + 1.0);
    return diffuseColor * wrap * wrap;
}

// 調用示例
half3 halfLambert = DiffuseHalfLambert(_BaseColor.rgb, NdotL);

Disney Diffuse(URP Lit.shader使用)

hlsl
// BRDF.hlsl 中的實現
half3 DiffuseDisney(half3 baseColor, half NdotV, half NdotL, half LdotH, half roughness)
{
    half fd90 = 0.5 + 2 * LdotH * LdotH * roughness;
    half lightScatter = (1 + (fd90 - 1) * pow(1 - NdotL, 5));
    half viewScatter = (1 + (fd90 - 1) * pow(1 - NdotV, 5));
    return baseColor * lightScatter * viewScatter / PI;
}

URP實際使用情況

  • 默認採用方案‌:

    • Simple Lit管線:Lambert模型(簡化版)
    • Lit管線:Disney Diffuse + Burley改進(見BRDF.hlsl
  • 核心代碼路徑‌:

    Packages/com.unity.render-pipelines.universal/ShaderLibrary/BRDF.hlsl
    → DirectBDRF()函數
    → DisneyDiffuse()分支
    
  • 性能優化策略‌:

    csharp
    // URP Asset中可關閉高質量漫反射
    UniversalRenderPipelineAsset.asset →
    Lighting → UseRoughnessRefraction = false
    

方法對比

  • 視覺差異‌:
    • Lambert:明暗對比強烈
    • Half-Lambert:暗部提亮約30%
    • Disney:邊緣光更自然(菲涅爾效應)
  • 推薦選擇‌:
    • 移動端:Lambert(Simple Lit)
    • 主機/PC:Disney(Lit Shader)
    • 風格化:Half-Lambert(需自定義Shader)

URP 2022 LTS版本中,主流的Lit.shader默認使用改進版Disney模型,通過#define _BRDF_BURLEY宏啓用。開發者可通過修改BRDF.hlsl中的#define語句切換不同模型。

除了以上Unity URP中涉及到的基於物理光照模型的漫反射實現方式,還有Oren-Nayar模型來實現漫反射

Oren-Nayar模型原理

  • 核心思想‌:

    由Michael Oren和Shree Nayar於1994年提出,基於‌微表面自陰影理論‌,適用於粗糙表面(如布料、砂石)。其公式為:

    $L = k_d * max(0, N·L) * (A + B * max(0, cos(φ_v-φ_l)) * sin(α) * tan(β))$

    $A = 1 - 0.5*(σ²)/(σ²+0.33)$

    $B = 0.45*(σ²)/(σ²+0.09)$

    $α = max(θ_v, θ_l)$

    $β = min(θ_v, θ_l)$

    • σ:表面粗糙度參數(0°-90°)
    • φ:方位角
  • 視覺特性‌:

    • 粗糙表面邊緣亮度增強
    • 逆向光時出現"後向散射"效果
    • 相比Lambert更符合真實布料觀測

Unity URP中的使用情況

  • 默認未採用原因‌:
    • 性能考量‌:需要額外計算角度和粗糙度(比Lambert多30%指令數)
    • 藝術控制‌:參數物理意義不如PBR直觀
    • 光照一致性‌:URP優先保證移動端性能
  • 替代方案‌:
    • 簡單場景:使用SimpleLit的Lambert
    • 複雜材質:通過LitShader的Smoothness參數間接控制

手動實現方案

若需在URP中使用Oren-Nayar,可修改BRDF.hlsl

hlsl
// 在BRDF.hlsl中添加
half3 DiffuseOrenNayar(half3 albedo, half roughness, half NdotV, half NdotL, half LdotV)
{
    half sigma2 = roughness * roughness;
    half A = 1.0 - 0.5 * sigma2 / (sigma2 + 0.33);
    half B = 0.45 * sigma2 / (sigma2 + 0.09);

    half s = LdotV - NdotL * NdotV;
    half t = s > 0 ? 1.0 / max(NdotL, NdotV) : 1.0;

    return albedo * (A + B * s * t) * NdotL;
}

適用場景建議

  • 推薦使用情況‌:

    • 風格化渲染(如手繪布料)
    • 考古/地質仿真項目
    • 需要特殊邊緣光效果的場景
  • 性能對比‌:

    模型 指令數(移動端) 內存訪問
    Lambert 12 3
    Oren-Nayar 38 5
    Disney 45 6

當前URP 2022 LTS版本中,可通過自定義Shader Graph節點實現Oren-Nayar,但官方未內置因其不符合URP的"性能優先"設計原則。實際項目中建議通過法線貼圖+Lambert近似替代。


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

(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)

Add a new Comments

Some HTML is okay.