在一个3D场景里,动态光源的实时计算开销相当可观,尤其是多个区域光、面光源同时存在时,中低端设备几乎扛不住。光照贴图(Lightmap)的思路很直接:既然场景中不动的物体和不变的光照占了大多数,那就在离线阶段把这些静态光照和阴影一次性算好,烘焙成贴图贴在模型表面,运行时只需一次纹理采样就能得到接近离线渲染的光照效果。这篇文章就来完整梳理光照贴图的烘焙流程,从原理到引擎实操,再到常见问题的处理。

光照贴图的工作原理与适用范围
光照贴图本质上是一张记录了入射光信息的纹理。烘焙器会从每个纹素(texel)的位置向场景发射光线,计算该点接收到的直接光照和间接反弹光,再把结果写入贴图。运行时渲染器在像素着色器中根据模型的第二套UV坐标采样这张贴图,把结果与动态光源的贡献叠加,就得到了最终画面。因为间接反弹光也被算进去了,所以Lightmap能呈现出实时光栅化很难做到的柔和色彩渗透效果,比如红色地毯把墙面映出淡红色。
这套方案的核心约束是"静态"。参与烘焙的物体必须被标记为Static(或者UE中的Lightmap Static、Geometry Static),光源的位置、强度、颜色在烘焙后也不能再变。一旦场景布局调整,就必须重新烘焙。因此Lightmap适合建筑结构、地形、固定家具这类不动的东西,而角色、载具、可交互道具则交给实时光照处理,两者通过光照探针(Light Probe)过渡衔接。
还有一个容易被忽视的点:光照贴图存储的是漫反射间接光(Diffuse GI),它不区分视线方向,所以从任何角度看结果都一样。镜面反射和法线贴图的高光细节仍然需要实时光源来驱动,这也是为什么烘焙场景中通常会保留一个方向光作为实时光,只把它的间接光部分烘进去。
UV2展开:烘焙质量的地基
所有支持Lightmap的引擎都要求模型有一套独立的UV,习惯上称为UV2。直接用 diffuse 贴图的UV是不行的,因为那套UV为了提高贴图利用率会重叠、镜像,而光照贴图的每个纹素必须对应模型表面上唯一的点,否则重叠区域的光照会互相污染。UV2需要重新展开,保证所有面片摊开后互不重叠,并且尽量填充0到1的UV空间。
在Blender中可以先选中模型,进入UV Editing工作区,执行Lightmap Pack操作,软件会自动生成一套不重叠的UV并放到UV2通道:
# Blender Python脚本:为选中物体生成UV2
import bpy
obj = bpy.context.active_object
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
# 使用Smart UV Project生成不重叠的UV
bpy.ops.uv.smart_project(
angle_limit=66,
island_margin=0.02, # 岛与岛之间留出缝隙,避免纹素渗色
correct_aspect=True
)
# 把结果复制到UV2通道
me = obj.data
if len(me.uv_layers) < 2:
me.uv_layers.new(name="UV2_Lightmap")
me.uv_layers.active_index = len(me.uv_layers) - 1
bpy.ops.object.mode_set(mode='OBJECT')
UV壳之间的边距(island margin)很关键。纹理过滤在采样时会跨纹素取值,如果两个UV壳贴得太近,一个壳的光照会渗到另一个壳上,表现为墙面边缘出现莫名的一块亮斑或暗斑。经验值是留出2%到5%的空间,同时开启贴图的填充设置。
另外要注意模型本身的质量:面与面之间不能有大面积重叠或穿插,法线方向必须朝外。烘焙器是按表面来发射光线的,法线翻转会直接导致该面接收不到光,烘焙结果一片黑。
Unity与Unreal的烘焙设置对比
两大主流引擎都内置了烘焙系统,但实现路径和参数体系差别不小。Unity使用Progressive Lightmapper,基于CPU或GPU的路径追踪,特点是边烘边看,质量逐步收敛,可以随时停止。UE则默认使用SWARM分布式烘焙加CPU路径追踪,新版本转向了GPU加速的Lumen辅助烘焙流程。下面通过表格对比主要参数:
| 对比项 | Unity Progressive | Unreal Lightmass |
|---|---|---|
| 烘焙核心 | CPU/GPU路径追踪 | CPU分布式+GPU可选 |
| 间接光反弹次数 | Bounces参数,1到4常用 | Num Sky Bouncing Bounces |
| 环境光遮蔽 | 内置Ambient Occlusion | Detailed AO可开关 |
| 单物体分辨率 | Object Scale调整 | 覆盖World Setting中的值 |
| 输出格式 | HDR的EXR序列 | 压缩后的图集 |
Unity中操作步骤是:先把场景物体勾选Lightmap Static,光源的Mode设为Baked,打开Lighting窗口点击Generate Lighting。几个核心参数中,Indirect Resolution决定间接光的精度,Lightmap Resolution决定贴图纹素密度,通常按每米20到40纹素设置。Final Gather开启后边缘质量明显提升,但烘焙时间会成倍增加,建议最终出图时才开。
UE这边,在World Settings里设置间接光质量和反弹次数,静态光源的Light Source Radius控制阴影软硬,半径越大阴影越柔和。UE还提供Lightmass Importance Volume,把烘焙计算集中到玩家活动的区域,场景外围的远处山体就不浪费烘焙算力了,这是控制烘焙时长的实用手段。
常见问题排查与优化技巧
烘焙结果不理想时,先按现象分类定位。最常见的是漏光(Light Leaking),表现为薄墙另一侧透出光来。根本原因是墙太薄,光照贴图分辨率不够,纹素跨过墙体表面采样到了亮面。解决办法有三个:加厚墙体、提高该物体的Lightmap Resolution、或者在UE里给墙体设置双面光照。如果只是个别位置漏,也可以放置遮光挡板(Shadowcaster),一个不可见的小平面专门用来挡光。
第二个高频问题是接缝处的黑线或白线,也就是所谓seam。UV壳边缘的纹素在过滤时找不到邻居数据,就会采样出错。除了前面提到的加大边距,还可以在引擎中把光照贴图的过滤模式从双线性调整为限制性过滤,Unity中对应Filtering设置为Auto的Gaussian模式,UE中则可以调高Lightmap的边距压缩补偿。
第三类是烘焙时间过长。先检查是不是场景中存在超高面数模型被错误标记为Static,比如一棵几十万面的雕刻树,烘焙器会给它分配大量纹素。对这类模型应该减面或者干脆不参与烘焙,改用光照探针。其次利用分区烘焙,Unity支持按场景分块分别烘焙再叠加,UE的SWARM可以把任务分发到多台机器并行。最后,开发期用低分辨率快速迭代,出正式版本时再切换到高参数完整烘焙,能节省大量等待时间。
内存方面也要留意,光照贴图是场景常驻资源,一个大型场景动辄几十张2048贴图。Unity中可以通过压缩格式(BC6H对HDR贴图压缩率不错)和降低非重点区域的分辨率来控制总量;UE中可以启用Lightmap Streaming,让贴图按需加载。把预算控制在移动平台50MB、PC平台300MB以内是比较稳妥的工程基线。
光照贴图Lightmap烘焙静态光照修改时间:2026-09-15 21:58:56