【光照】[漫反射]UnityURP兰伯特能量守恒吗?

【从UnityURP开始探索游戏渲染】专栏-直达

兰伯特漫反射的能量守恒性

‌能量守恒基本原理‌

在物理正确的渲染中,能量守恒要求:

  1. 表面反射的光能总量 ≤ 入射光能
  2. 漫反射+高光反射 ≤ 1.0
  3. 没有能量凭空产生或消失

‌经典兰伯特模型的能量守恒问题‌

传统兰伯特漫反射公式:

漫反射 = 表面反照率 × max(0, N·L)

不守恒的原因‌:

  • 缺乏归一化因子 ‌:
    • 半球积分结果应为π,但兰伯特模型直接使用N·L
    • 正确公式应为:漫反射 = 表面反照率 / π × max(0, N·L)
  • 反射率超标 ‌:
    • 当反照率(albedo)设为1.0时,反射率可能超过100%
    • 例如:N·L=1时反射率为100%,但实际应有吸收损失
  • 恒定反射率 ‌:
    • 对所有入射角使用相同反射率
    • 现实中菲涅尔效应导致掠射角反射率增加

‌URP中的修正方案‌

Unity URP采用改进的兰伯特模型:

c 复制代码
hlsl
// URP实际实现(Lighting.hlsl)
half diffuseTerm = saturate(dot(normal, lightDir));
half3 diffuse = albedo * lightColor * diffuseTerm * INV_PI;

其中:

  • INV_PI ≈ 0.31831 (1/π)
  • 通过除以π实现能量归一化

PBR工作流兼容性分析

‌兼容性类型‌

兼容维度 支持情况 说明
数据输入 ✅ 完全兼容 使用相同的albedo贴图输入
光照计算 ⚠️ 部分兼容 缺乏物理反射特性
材质工作流 ✅ 完全兼容 支持标准材质参数
后期处理 ✅ 完全兼容 兼容HDR/Bloom等效果
全局光照 ⚠️ 有限兼容 需要特殊处理

‌完全兼容的方面‌

  • 材质参数统一 ‌:
    • 使用相同的albedo纹理和颜色参数
    • 支持相同的法线贴图格式
  • HDR管线整合 ‌:
    • 支持线性颜色空间
    • 兼容HDR渲染和自动曝光
  • 后期处理协同 ‌:
    • 与Bloom效果无缝配合
    • 支持屏幕空间环境光遮蔽(SSAO)

‌有限兼容的方面‌

  • 能量守恒缺口‌:

    graph LR A[入射光能量] --> B[经验模型] B --> C[漫反射输出] C --> D{能量总和} D --> |100%| E[违反守恒] D --> |物理模型<90%| F[正确守恒]

  • 金属度工作流问题‌:

    • 金属表面应无漫反射,但兰伯特模型无法正确处理
    • 需要额外代码屏蔽金属表面的漫反射
  • 菲涅尔效应缺失‌:

    • 掠射角反射率无增强
    • 影响边缘光照的真实性
  • 全局光照不一致‌:

    • 与基于物理的GI系统配合时可能出现能量不匹配
    • 需要手动调整间接光照强度

‌URP中的兼容性实现‌

  • URP采用混合方案实现兼容:
c 复制代码
hlsl
// URP的BRDF处理(BRDF.hlsl)
half3 BRDF_lambert(half3 albedo)
{
    return albedo * INV_PI;
}

#if defined(_PBR_ENABLED)
    // 物理正确的漫反射计算
    half3 diffuse = BRDF_lambert(albedo) * saturate(NdotL);
#else
    // 传统兰伯特计算
    half3 diffuse = albedo * saturate(NdotL);
#endif

结论与建议

‌能量守恒结论‌

  • 原始兰伯特模型不守恒‌:缺乏归一化因子,反射率可能超标
  • 修正版可基本守恒‌:通过添加1/π因子实现能量平衡
  • URP实现部分守恒‌:在标准着色器中已包含修正因子

‌PBR兼容性结论‌

  • ✅ ‌美术工作流兼容‌:可使用相同材质和纹理
  • ️ ‌物理精度局限‌:无法完全匹配物理反射特性
  • ️ ‌工程实用方案‌:适合风格化/性能优先项目

‌实际开发建议‌

  • 移动端项目‌:

    c 复制代码
    hlsl
    // 使用优化版兰伯特(包含能量修正)
    half3 diffuse = albedo * saturate(NdotL) * 0.31831;
  • PC/主机项目‌:

    c 复制代码
    hlsl
    // 使用完整PBR漫反射(Disney模型)
    half3 diffuse = albedo * (1 / PI) * (1 - metallic) * saturate(NdotL);
  • 风格化渲染‌:

    c 复制代码
    hlsl
    // 艺术导向的增强版
    half3 diffuse = albedo * pow(saturate(NdotL), _RampPower) * _Intensity;

在URP中,经验模型与PBR工作流可通过条件编译实现无缝切换,开发者可根据目标平台和艺术需求选择最适合的模型,在物理准确性和性能之间取得最佳平衡。


【从UnityURP开始探索游戏渲染】专栏-直达

(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

相关推荐
SmalBox1 天前
【光照】[漫反射diffuse]以UnityURP为例
unity·渲染
SmalBox2 天前
【光照】[自发光Emission]以UnityURP为例
unity·渲染
SmalBox3 天前
【光照】Unity中的[经验模型]
unity·渲染
萘柰奈3 天前
Unity学习----【进阶】TextMeshPro学习(三)--进阶知识点(TMP基础设置,材质球相关,两个辅助工具类)
学习·unity
Yasin Chen3 天前
Unity UI坐标说明
ui·unity
陈言必行3 天前
Unity 性能优化 之 编辑器创建资源优化( 工作流 | 场景 | 预制体)
unity·编辑器·游戏引擎
1uther4 天前
Unity核心概念⑨:Screen
开发语言·游戏·unity·c#·游戏引擎
死也不注释4 天前
【Unity UGUI 交互组件——Slider(7)】
unity·游戏引擎·交互
程序猿多布4 天前
XLua教程之热补丁技术
unity·c#·lua·xlua