郦湘云 发表于 6 天前

【光照】Unity[光照烘焙]的原理与具体流程

【从UnityURP开始探索游戏渲染】专栏-直达
URP光照烘焙介绍

Unity通用渲染管线(URP)的光照烘焙系统是用于预计算全局光照(GI)的核心技术,它将静态光源的光照效果预先计算并存储在光照贴图(Lightmap)中,运行时直接采样使用以提高性能。URP支持三种光源模式:

[*]‌Realtime实时模式‌:

[*]完全动态计算,不生成光照贴图,适用于高频移动光源或需要实时互动的场景。

[*]‌Baked烘焙模式‌:

[*]完全离线烘焙到光照贴图中,运行时无实时计算,适合静态环境光。

[*]‌Mixed混合模式‌:

[*]结合烘焙与实时计算的优势,包括三种子模式:
[*]Baked Indirect:烘焙间接光照,直接光和阴影实时计算
[*]Subtractive:烘焙直接光和阴影,动态物体通过Light Probe接收光照
[*]Shadowmask:烘焙间接光+阴影贴图,实时计算直接光

历史发展

URP的光照烘焙技术源自Unity传统的Enlighten和Progressive光照系统,经过多次迭代:

[*]早期版本主要依赖Enlighten光照系统
[*]2018年后引入Progressive光照烘焙器(CPU/GPU)
[*]URP 7.x版本开始支持StructuredBuffer优化光源处理
[*]最新版本支持Shadowmask混合模式,平衡效果与性能
内部实现原理与数学公式

光照烘焙核心算法

光照烘焙主要基于辐射度算法(Radiosity)和光子映射(Photon Mapping),核心数学公式包括:
‌辐射传输方程‌:

$L_o(x,ω_o) = L_e(x,ω_o) + ∫_Ω f_r(x,ω_i,ω_o)L_i(x,ω_i)(n·ω_i)dω_i$
其中:

[*]$L_o$:出射辐射度
[*]$L_e$:自发光辐射度
[*]$f_r$:双向反射分布函数(BRDF)
[*]$L_i$:入射辐射度
[*]$(n·ω_i)$:余弦项
‌光照贴图采样‌:

float3 SampleLightMap(float2 lightMapUV) {
    #if defined(LIGHTMAP_ON)
    return SampleSingleLightmap(TEXTURE2D_ARGS(unity_Lightmap, samplerunity_Lightmap),
      lightMapUV, float4(1.0, 1.0, 0.0, 0.0),
      #if defined(UNITY_LIGHTMAP_FULL_HDR)
      false,
      #elsetrue,
      #endif
      float4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0.0, 0.0));
    #elsereturn 0.0;
    #endif
}动态物体光照处理

动态物体通过Light Probe接收烘焙光照,采样使用球谐函数(SH):
float3 SampleLightProbe(Surface surfaceWS) {
    #if defined(LIGHTMAP_ON)
    return 0.0;
    #elseif(unity_ProbeVolumeParams.x) {
      return SampleProbeVolumeSH4(TEXTURE3D_ARGS(unity_ProbeVolumeSH, samplerunity_ProbeVolumeSH),
            surfaceWS.position, surfaceWS.normal, unity_ProbeVolumeWorldToObject,
            unity_ProbeVolumeParams.y, unity_ProbeVolumeParams.z,
            unity_ProbeVolumeMin.xyz, unity_ProbeVolumeSizeInv.xyz);
    } else {
      float4 coefficients;
      coefficients = unity_SHAr;
      coefficients = unity_SHAg;
      coefficients = unity_SHAb;
      coefficients = unity_SHBr;
      coefficients = unity_SHBg;
      coefficients = unity_SHBb;
      coefficients = unity_SHC;
      return max(0.0, SampleSH9(coefficients, surfaceWS.normal));
    }
    #endif
}具体流程与手动计算示例

光照烘焙流程


[*]‌场景准备‌:

[*]标记静态物体(勾选Static)
[*]生成光照贴图UV(Generate Lightmap UVs)
[*]设置光源模式(Baked/Mixed)

[*]‌烘焙参数设置‌:

[*]间接光反弹次数(Max Bounces,通常设为5)
[*]光照贴图分辨率
[*]启用环境光遮蔽(AO)

[*]‌执行烘焙‌:

[*]CPU或GPU渐进式烘焙
[*]降噪处理
[*]生成光照贴图和光照探针

手动计算示例

假设一个简单场景,计算某点P的烘焙光照:
‌直接光照计算‌:

$L_direct = I * max(0, n·l) / (d² + 1)$
其中:

[*]I:光源强度
[*]n:表面法线
[*]l:光源方向
[*]d:距离光源的距离
‌间接光照计算‌:
$L_{indirect} = Σ (L_{bounce} * albedo / π)$
其中:

[*]$L_{bounce}$:来自其他表面的反射光
[*]albedo:表面反射率
‌最终光照‌:
$L_{final} = L_{direct} + L_{indirect} + L_{emission}$
常见问题与优化


[*]‌黑斑问题‌:因模型没有光照贴图坐标或UV重叠导致,需勾选Generate Lightmap UVs并调整Pack Margin。
[*]‌硬边问题‌:因UV在光照图中比例太小,需调大Scale In Lightmap参数。
[*]‌性能优化‌:

[*]使用Shadowmask模式平衡效果与性能
[*]控制附加光源数量(PC平台最多8个)
[*]合理设置阴影距离(Shadow Distance)

URP的光照烘焙系统通过结合预计算和实时计算,在保持良好视觉效果的同时显著提升了渲染性能,特别适合移动端和中低端硬件平台
<blockquote>
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 【光照】Unity[光照烘焙]的原理与具体流程