【从UnityURP开始探索游戏渲染】专栏-直达
微表面理论的核心概念
微表面理论是一种物理渲染模型,它将宏观表面视为由无数微观几何细节(微表面)组成的复杂结构。这一理论是Unity URP中PBR(基于物理的渲染)实现的基础。
基本假设
- 微观结构 :
- 宏观表面由大量随机方向的微观小平面组成
- 每个微表面都是完美的镜面反射体
- 微表面尺度小于单个像素但大于光波长
- 宏观表现 :
- 粗糙度:描述微表面法线分布的集中程度
- 光泽度:反射方向的集中程度
- 菲涅尔效应:视角变化导致的反射率变化
核心方程
微表面理论的核心是Cook-Torrance BRDF方程:
f_r=\\frac{DFG}{4(ω_o⋅n)(ω_i⋅n)}
- 其中:
- D:法线分布函数(NDF)
- F:菲涅尔方程
- G:几何遮蔽函数
- ω_i:入射光方向
- ω_o:出射光方向
- n:表面法线
Unity URP中的微表面实现
1. 法线分布函数(Normal Distribution Function - NDF)
作用:描述微表面法线朝向的概率分布
Unity URP实现:Trowbridge-Reitz GGX分布
c
hlsl
// 代码路径: Packages/com.unity.render-pipelines.universal/ShaderLibrary/BRDF.hlsl
float D_GGX(float NdotH, float roughness)
{
float a = roughness * roughness;
float a2 = a * a;
float NdotH2 = NdotH * NdotH;
float denom = NdotH2 * (a2 - 1.0) + 1.0;
denom = PI * denom * denom;
return a2 / max(denom, 0.000001); // 避免除零错误
}
数学公式:
D_{GGX}(h) = \\frac{\\alpha_g^2}{\\pi\[(n·h)^2(\\alpha_g^2-1)+1\]^2}
特性:
- 高光区域随粗糙度增加而扩散
- 能量守恒,保持亮度一致
- 长尾分布,模拟真实表面散射
2. 几何遮蔽函数(Geometry Function - G)
作用:模拟微表面间的自阴影和遮蔽效应
Unity URP实现:Smith联合Schlick-GGX模型
c
hlsl
// 几何遮蔽项计算
float V_SmithGGX(float NdotL, float NdotV, float roughness)
{
float a = roughness;
float a2 = a * a;
float GGXV = NdotL * sqrt(NdotV * NdotV * (1.0 - a2) + a2);
float GGXL = NdotV * sqrt(NdotL * NdotL * (1.0 - a2) + a2);
return 0.5 / max((GGXV + GGXL), 0.000001);
}
数学公式:
G(n,v,l)=G_1(n,v)⋅G_1(n,l)
其中:
G_1(n,v)=\\frac{n⋅v}{(n⋅v)(1−k)+k},k=\\frac{(α+1)}8
特性:
- 粗糙表面边缘产生更多阴影
- 模拟掠射角时的光线衰减
- 保持能量守恒
3. 菲涅尔方程(Fresnel Equation - F)
作用:描述不同视角下的反射率变化
Unity URP实现:Schlick近似
c
hlsl
// 菲涅尔项计算
float3 F_Schlick(float cosTheta, float3 F0)
{
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
}
数学公式:
F(v,h)=F_0+(1−F_0)(1−(v⋅h))\^5
特性:
- F0F0 是0度角的基础反射率
- 掠射角反射率接近100%
- 金属与非金属材质反射特性不同
URP中的完整微表面BRDF实现
Unity URP中的镜面反射计算在BRDF.hlsl
文件中实现:
c
hlsl
// 完整镜面反射BRDF计算
float3 BRDF_Specular(float3 F0, float roughness, float NdotH, float NdotL, float NdotV, float LdotH)
{
// 1. 计算法线分布
float D = D_GGX(NdotH, roughness);
// 2. 计算几何遮蔽
float V = V_SmithGGX(NdotL, NdotV, roughness);
// 3. 计算菲涅尔反射
float3 F = F_Schlick(LdotH, F0);
// 4. 组合Cook-Torrance BRDF
return (D * V) * F;
}
完整镜面反射调用链
-
数据准备阶段:
chlsl // 获取光线数据 Light light = GetMainLight(); float3 halfVec = normalize(light.direction + viewDir); // 计算中间量 float NdotV = saturate(dot(normalWS, viewDir)); float NdotL = saturate(dot(normalWS, light.direction)); float NdotH = saturate(dot(normalWS, halfVec));
-
BRDF计算阶段:
chlsl // 计算三项核心参数 float D = D_GGX(NdotH, roughness); float G = G_Smith(NdotV, NdotL, roughness); float3 F = F_Schlick(max(dot(halfVec, viewDir), 0), F0); // 最终镜面反射 float3 specular = (D * G * F) / (4 * NdotV * NdotL + 0.0001);
URP 2022 LTS版本中,通过#define _SPECULARHIGHLIGHTS_OFF
可关闭高光计算。实际开发时建议通过Smoothness
参数(0-1范围)控制镜面反射强度,金属材质会自动增强高光响应。
微表面理论与传统模型的对比
特性 | 微表面模型 | Phong模型 | Blinn-Phong模型 |
---|---|---|---|
物理基础 | 基于物理 | 经验模型 | 经验模型 |
能量守恒 | 是 | 否 | 否 |
视角依赖性 | 精确模拟 | 近似 | 近似 |
材质参数 | 物理属性(金属度/粗糙度) | 光泽度 | 光泽度 |
边缘表现 | 精确菲涅尔 | 固定反射率 | 固定反射率 |
性能开销 | 较高 | 低 | 中等 |
URP中的优化实现
- 重要性采样:通过预计算环境贴图优化实时计算
- 分割和近似:将环境光照分解为预过滤环境和BRDF LUT
- 移动端优化:使用简化的IBL(基于图像的照明)计算
- LOD控制:根据距离自动降低计算精度
c
hlsl
// 环境镜面反射优化实现
float3 EnvBRDFApprox(float3 specColor, float roughness, float NdotV)
{
// 使用预计算的LUT纹理
float2 envBRDF = tex2D(_BRDFLUT, float2(NdotV, roughness)).rg;
return specColor * envBRDF.r + envBRDF.g;
}
实际应用建议
材质设置:
- 金属度:金属表面接近1.0,非金属接近0.0
- 粗糙度:光滑表面0.0-0.3,粗糙表面0.4-1.0
性能优化:
- 简单材质使用SimpleLit着色器
- 复杂场景降低反射质量
csharp
csharp
// URP Asset中调整反射质量
UniversalRenderPipelineAsset.asset → Lighting → Reflection Quality
视觉优化:
- 使用高质量法线贴图增强微观细节
- 添加环境光遮蔽贴图增强深度感
微表面理论为Unity URP提供了物理准确的渲染基础,通过精确模拟光线与微观表面的相互作用,实现了在各种材质和光照条件下的逼真渲染效果。
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)