【光照】[PBR][镜面反射]实现方法解析

【从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;
}

完整镜面反射调用链

  • 数据准备阶段‌:

    c 复制代码
    hlsl
    // 获取光线数据
    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计算阶段‌:

    c 复制代码
    hlsl
    // 计算三项核心参数
    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开始探索游戏渲染】专栏-直达

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

相关推荐
mxwin4 小时前
Unity Shader 半透明物体为什么不能写入深度缓冲?
unity·游戏引擎·shader
晚枫歌F5 小时前
三层时间轮的实现
网络·unity·游戏引擎
咸鱼永不翻身6 小时前
Lua脚本事件检查工具
unity·lua·工具
leo__5208 小时前
单载波中继系统资源分配算法MATLAB仿真程序
算法·matlab·unity
努力长头发的程序猿9 小时前
Unity使用ScriptableObject序列化资源
unity·游戏引擎
mxwin9 小时前
Unity Shader 手写基于 PBR 的 URP Lit Shader 核心光照计算
unity·游戏引擎·shader
小贺儿开发10 小时前
Unity3D 智能云端数字标牌系统
unity·阿里云·人机交互·视频·oss·广告·互动
魔士于安10 小时前
Unity windows 同步 异步 打开文件文件夹工具
游戏·unity·游戏引擎·贴图·模型
魔士于安11 小时前
unity lowpoly 风格 城市 建筑 道路 交通标志
游戏·unity·游戏引擎·贴图·模型
mxwin11 小时前
Unity GPU Shader 性能优化指南
unity·游戏引擎·shader