时间:2025-09-27 15:58
人气:
作者:admin
【从UnityURP开始探索游戏渲染】专栏-直达
| 方法名称 | 数学公式 | 特点 | 性能消耗 | 适用场景 |
|---|---|---|---|---|
| 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标准,次表面散射近似 | ★★★ | 金属/粗糙度工作流 |
hlsl
// Lighting.hlsl 中的实现
half3 DiffuseLambert(half3 diffuseColor)
{
return diffuseColor / PI; // 能量归一化
}
// 实际调用示例
half NdotL = saturate(dot(normalWS, light.direction));
half3 lambert = DiffuseLambert(_BaseColor.rgb) * NdotL;
hlsl
half3 DiffuseHalfLambert(half3 diffuseColor, half NdotL)
{
half wrap = 0.5 * (NdotL + 1.0);
return diffuseColor * wrap * wrap;
}
// 调用示例
half3 halfLambert = DiffuseHalfLambert(_BaseColor.rgb, NdotL);
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;
}
默认采用方案:
BRDF.hlsl)核心代码路径:
Packages/com.unity.render-pipelines.universal/ShaderLibrary/BRDF.hlsl
→ DirectBDRF()函数
→ DisneyDiffuse()分支
性能优化策略:
csharp
// URP Asset中可关闭高质量漫反射
UniversalRenderPipelineAsset.asset →
Lighting → UseRoughnessRefraction = false
URP 2022 LTS版本中,主流的Lit.shader默认使用改进版Disney模型,通过#define _BRDF_BURLEY宏启用。开发者可通过修改BRDF.hlsl中的#define语句切换不同模型。
除了以上Unity URP中涉及到的基于物理光照模型的漫反射实现方式,还有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)$
视觉特性:
SimpleLit的LambertLitShader的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开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,????)