
一句话先抓住本质光照贴图就是把这个地方有多亮提前算好画成一张图片贴在物体上。游戏运行时不用再算光照直接查这张图就知道每个点多亮。用提前算好存起来换运行时不用算——和之前聊的球谐、变体压缩是同一个思路拿存储换性能。下面拆开讲为什么要这么做、这张图里存的是什么、它到底怎么被算出来。第一步为什么需要 Lightmap实时算光照很贵。尤其是间接光光打到墙上弹一下再照亮旁边的地面要算它得追踪光线反复弹射手机根本扛不住。但游戏里有个事实场景里大部分东西是不动的墙、地面、山、建筑光源也不动太阳、固定的灯。既然物体不动、光也不动那每个点的亮度永远是固定的。既然固定何必每帧都重算于是提前把这些不动物体上每个点的亮度算好存成一张图。运行时直接查。这就是 Lightmap。动态的东西角色、可移动物体→ 实时算光照 静态的东西墙、地面、建筑 → 查 Lightmap预先算好第二步Lightmap 里到底存了什么一张普通贴图存的是物体表面长什么颜色漫反射贴图。Lightmap 存的是物体表面每个点收到多少光——也就是亮度信息特别是那些实时算不起的部分主要存间接光光弹射后的照明 阴影 环境光遮蔽举个例子一个白色房间墙是白的。开了一盏灯灯直接照到的地方很亮 → 这部分实时算也行墙角、天花板因为光反复弹射被间接照亮有微妙的明暗过渡 →这部分就烤进 Lightmap运行时把这张亮度图和物体本身的颜色图一乘就得到最终画面最终颜色 物体本色颜色贴图 × 收到的光Lightmap第三步关键难题——怎么把 3D 物体的光摊平成一张 2D 图这是理解 Lightmap 最重要的一步。贴图是 2D 的一张平面图片但物体是 3D 的。怎么把一个 3D 物体表面的亮度对应到一张 2D 图片上的像素答案UV 展开专门给 Lightmap 用的叫 Lightmap UV 或第二套 UV。想象你把一个纸盒拆开摊平在桌上3D 盒子 摊平后的 2D 图 ┌──────┐ ┌──┬──────┬──┐ │ │ 拆开摊平 │顶│ 侧面 │底│ └──────┘ ────────→ └──┴──────┴──┘ 这就是 Lightmap 的布局盒子表面的每一块都在这张平面图上有一个唯一的、不重叠的位置。3D 上某个点 → 通过 UV 找到 2D 图上对应的像素那个像素里存着这个点的亮度这套 UV 必须每块都不重叠不像颜色贴图可以重复利用因为每个点的光照是独一无二的不能共用。Unity 里的Generate Lightmap UVs选项就是自动帮你做这个摊平。第四步亮度是怎么算出来的烘焙的核心现在有了这张摊平的图图上每个像素对应物体表面一个点。烘焙Bake就是对每一个点算出它到底收到多少光。怎么算核心方法叫路径追踪 / 光线弹射。对每个点做这件事站在这个点上向四面八方发射很多条光线去问 → 这条光线飞出去撞到了什么 → 撞到光源了吗收到直接光 → 撞到别的墙了吗那面墙又被照亮了多少间接光要递归再问 → 什么都没撞到飞向天空了收到天空光 把所有光线带回来的光加起来就是这个点的总亮度。间接光就是在这里产生的光线撞到墙 A墙 A 本身被灯照亮了所以它把一部分光反射给我们的点。这就是光的弹射。弹得越多次间接光越丰富也越慢。第1次弹射灯 → 地面 第2次弹射地面 → 墙 第3次弹射墙 → 天花板 ... 弹得越多效果越真实计算越久对图上几十万个像素都做一遍这个过程全部填好Lightmap 就烤好了。这就是为什么烘焙动辄要几分钟到几小时。第五步为什么有噪点为什么要降噪上面说向四面八方发射很多光线——但不可能发射无限条。发射的光线是随机采样的数量有限所以算出来的亮度会有随机误差表现为画面上的噪点/颗粒感。采样少 → 快但噪点多画面脏 采样多 → 干净但极慢解决办法有两个通常一起用加采样数多打点光线噪点自然少费时间。降噪器Denoiser算完后用算法把噪点抹平Unity 集成了 Intel/NVIDIA 的降噪器。这就是烘焙设置里那些Samples、Denoising选项在干的事。完整流程串起来① 标记静态物体 把不动的墙、地面标成 Static / Contribute GI ↓ ② 展开 Lightmap UV 把每个物体表面摊平到 2D 图上各占一块不重叠的位置 ↓ ③ 烘焙Bake 对图上每个像素对应的点发射光线追踪弹射 算出直接光 间接光 阴影 天空光 ↓ ④ 降噪 打包 抹掉噪点把结果打包成一张或几张Lightmap 贴图 ↓ ⑤ 运行时 静态物体直接查 Lightmap颜色 × 光照 画面 不用再实时算复杂光照几个关键概念补充① 分辨率Lightmap Resolution每单位面积分多少像素。高 → 阴影细腻但贴图大、烤得慢低 → 省空间但光照糊。② 动态物体怎么办角色会动不能用 Lightmap。它们用Light Probe光照探针——在空间里布一堆采样点预存那里的环境光角色走到哪就插值取哪的光。这里就用到了之前讲的球谐函数来存每个探针的方向光照③ 直接光要不要烤可以选。烤进去最省性能但阴影是死的也可以直接光实时算、只烤间接光兼顾灵活性和质量Unity 的 Mixed Lighting 就是干这个的。一句话总结Lightmap 就是把静态场景里每个点有多亮提前用光线追踪算好通过 UV 展开摊平存进一张 2D 图。运行时直接查表把实时算不起的间接光和阴影变成一次贴图采样。本质还是那句老话能提前算好的就别在运行时算。