【从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)$
- 视觉特性:
- 粗糙表面边缘亮度增强
- 逆向光时出现"后向散射"效果
- 相比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;
- }
复制代码 适用场景建议
- 推荐使用情况:
- 风格化渲染(如手绘布料)
- 考古/地质仿真项目
- 需要特殊边缘光效果的场景
- 性能对比:
模型指令数(移动端)内存访问Lambert123Oren-Nayar385Disney456
当前URP 2022 LTS版本中,可通过自定义Shader Graph节点实现Oren-Nayar,但官方未内置因其不符合URP的"性能优先"设计原则。实际项目中建议通过法线贴图+Lambert近似替代。
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |