2026/10/17 14:47:13

移动端烘焙光照实战:从场景准备到压缩优化全流程

移动端烘焙光照实战:从场景准备到压缩优化全流程 做移动端项目最怕什么最怕场景里堆了一堆实时灯光白天室内还好一进到大场景、多光源的关卡帧率和发热立刻教你做人。烘焙光照的思路就是把昂贵的实时光照计算提前在编辑器里做完把结果存进一张张光照贴图和探针里运行时手机只需要采样、插值、查表——这就是“把阳光装进罐头”制作期花时间封装阳光运行期开罐即食成本低到可以忽略。这篇攻略我会从移动端烘焙光照的适用场景、场景准备、UV展开、参数设置到压缩优化、问题排查全流程捋一遍基本都是实际项目里反复试过、调过之后留下的经验适合正在做移动端游戏、特别是室内或者固定关卡制的团队参考。1. 为什么移动端必须“装罐头”1.1 实时光照在手机上的成本账先说清楚一个前提烘焙光照不是炫技是被移动端的硬件条件逼出来的。手机GPU和桌面GPU最大的差异在带宽和功耗尤其不少移动GPU采用了基于瓦片的渲染架构好处是省带宽坏处是一旦场景里有大量逐像素光照每个像素都要反复读写颜色缓冲、法线缓冲、阴影信息瓦片内的计算和带宽压力会瞬间飙升。做个简单的换算一个普通室内场景放60盏灯如果全部走实时渲染每个物体表面要依次计算几十盏灯的直接光贡献哪怕做了剔除和光照裁剪最终叠加的CPU和GPU开销仍然非常可观。桌面显卡可以硬扛手机的散热和电量扛不住结果就是掉帧、发烫、降频三连。玩家的体感比任何Benchmark都诚实烫手、卡顿、电池哗哗掉这游戏基本就告别好评了。烘焙光照本质上是“时间换空间”把运行期要做的昂贵计算挪到开发期慢慢算。算完的结果编码成光照贴图运行时每个像素只需要一次纹理采样和简单的解码相当于把原来要跑一百遍的复杂光照公式换成了一次“查表”。对移动GPU来说这是最划算的交换。1.2 烘焙光照解决了什么、牺牲了什么任何方案都有代价烘焙光照也不例外。先看它解决了什么第一直接把场景里固定物体的漫反射间接光、环境光遮蔽、静态阴影全部预计算好视觉效果可以做到很丰富尤其是墙角、家具下方、门缝这些AO细节实时渲染想做到同等效果性能开销非常夸张第二运行时没有逐像素光照计算DrawCall和Shader复杂度都能压下来帧率曲线会稳定很多第三功耗降低手机不那么热这对移动端项目可以说是直接影响留存的生命线。它牺牲的也很明确场景一旦改了布局、换贴图、挪光源就得重新烘焙动态物体无法从光照贴图里取到光影信息只能依靠光照探针去近似时间系统、动态天气、可破坏场景这类玩法基本告别烘焙。所以烘焙光照适合的是关卡制、固定场景、室内环境和风格化美术的项目如果是全动态日夜循环的开放世界那就得换一套思路。一句话总结我的判断标准画面里大部分东西“不会动”并且美术风格允许光照结果比较精细稳定那就值得烘焙反过来如果一半场景都能被玩家拆掉烘焙就会变成持续的返工噩梦。2. 动手烘之前先把场景收拾利索很多团队一上来就开烘结果烘出来的光照不是漏光就是接缝然后开始怀疑软件有问题。实际上八成问题出在场景准备阶段。这一步不值得省后面返工更痛苦。2.1 静态和动态物体如何划分烘焙光照的第一步不是调参数而是清理场景里物体的静态标记。主流引擎里有个关键的“Static”标记但很多人习惯随手把所有物体标成Static这是灾难的开始。要分三类看待场景里的物体完全静止的墙体、地板、柱子、大型固定装饰这些应该参与烘焙标为静态。半静态的门、抽屉、可移动箱子、机关踏板这些物体虽然不是完全固定但也不是主角需要单独处理。半静态物体可以在运行时小范围移动用光照探针配合低成本实时投影来补足动态感。真正动态的角色、NPC、怪物、可以被拿起来的道具它们必须依赖光照探针和实时阴影。划分标准可以很简单这个物体在玩法里会不会被玩家影响如果会就尽量不要标成烘焙静态。我之前见过一个项目沙发标了静态结果角色可以推着沙发跑沙发上的烘焙阴影纹丝不动画面非常割裂。这种问题一旦烘焙完成再改必须全场景重新来一遍非常浪费时间。另外要注意“静态光照”和“静态物体”是两个概念。静态光照只表示这个物体接收烘焙光照不代表它不能动。有些引擎支持让标了静态光照的物体在运行时播放简单动画前提是它的阴影和AO变化不明显。没有把握的话统一按前面三分类处理最稳妥。2.2 光照UV展开是成败关键烘焙光照贴图时引擎需要物体的第二套UV也就是光照UV。很多新手根本不看这个直接用模型的第一套UV去烘结果接缝密集、贴图精度浪费、漏光频发。光照UV和纹理UV的要求不一样纹理UV可以为了贴图精度和排布牺牲一些接缝但光照UV的优先级是“少接缝、不重叠、充分留边距”。先说重叠问题。光照UV一旦重叠两个位置的烘焙光照会互相污染渲染时就会出现漏光、暗斑和奇怪的渐变。检查方法很简单在引擎的UV查看器里打开光照UV把重复区域高亮出来见到红色区域就必须拆开。一个常见误区是美术建模时为了方便画贴图会把一个箱子的六个面全部叠在一张UV里这在纹理贴图里是合法操作但在光照UV里就是不能用的。再说留边距。每个UV“岛”之间要留出至少4到8像素的边距Padding不然相邻的岛在贴图过滤时会产生颜色渗透表现成黑边或亮边。如果是大面积平整墙面边距可以稍大一些因为墙面光照变化平缓渗透一点就会很显眼。我见过最省事的方案在DCC工具里给模型生成第二套UV时用基于角度和面积的自动分拆然后把每块岛适当放大保证岛之间留出足够间距。整个过程有点像做罐头贴纸设计标签边缘留白不够印刷的时候颜色就会互相蹭脏道理一模一样。2.3 模型与法线的坑模型的面数、拓扑和法线直接影响烘焙结果这个环节踩坑的人特别多。第一是面数。烘焙计算时每个三角形都会参与光照计算和投影面数越高烘焙时间越长。移动端场景的静态模型尤其是不起眼的小物件可以大胆合并和减面合并之后要重新生成UV千万别拿合并前的旧UV凑合。第二是法线。顶点法线不一致会导致烘焙结果出现黑缝或棱线。常见情况是两块墙板接在一起法线一个朝左一个朝右烘焙时间接光在接缝处产生不连续表现成一道很难看的暗线。这种问题单看网格很难发现但烘完以后一动不动非常难排除。处理办法是统一平滑组或者在建模阶段保证相邻面的法线过渡合理。硬边结构比如柱子棱角有明确折痕可以保留硬边但不能在应该平滑的地方出现法线撕裂。第三是物体的大小。超大物体比如整面地形在烘焙时会占用一整张光照贴图分辨率分配效率很低直接把一个小区块切成独立Mesh会更划算。反过来一串完全一样的路灯如果每盏都单独烘焙每一盏都要占一块光照UV空间浪费得让人心疼。合理做法是把它们合并成一个Mesh再烘焙光影信息还有机会共享。3. 烘焙参数与一次完整流程实操场景准备干净了接下来才是真正调参数和跑烘焙。这个环节不需要玄学核心是理解几个关键数值代表什么以及它们对移动端的连锁反应。3.1 纹理分辨率与纹素密度测算烘焙光照贴图的清晰度用“纹素密度”来衡量意思是场景中每米距离对应多少像素。移动端我一般这么取室内主要交互区域70~100像素/米保证近景墙面、家具上的阴影边缘清晰。大型室内空间或大厅40~60像素/米因为距离远玩家不会贴着墙面数像素点。户外大世界地形20~40像素/米大面积自然地形需要的是光照铺底不是清晰阴影。重点展示物体、剧情特写区域可以单独提到100~120像素/米但要警惕贴图总量爆炸。怎么算需要多大的光照贴图简单估算假设一面墙长5米、高3米按80像素/米需要400×240像素如果这面墙是一个整体Mesh放一张512×512的光照贴图就够还能把周围几面墙一块塞进去。要是塞不下引擎会自动拆成多张贴图贴图数量一多内存和带宽都会上去。移动端的光照贴图尺寸单张一般控制在2048×2048以内超过这个尺寸对手机很危险。很多引擎允许设置光照贴图最大尺寸移动端场景建议直接设成2048个别大场景可以用4096但要做好压缩不然运行期VRAM会非常紧张。3.2 光照贴图参数设置主流的烘焙器里有几个参数需要特别关注顺序从重要到次要排开间接光照分辨率控制反弹光、环境光的计算精度。移动端可以设得比直接光照低一些因为间接光变化平缓分辨率太高感知不强还很吃烘焙时间和内存。直接光照分辨率控制太阳光、人造光源产生的阴影边缘质量。这个参数值得给足它决定了墙面阴影和物体投影的清晰度。采样数每一束光线的采样数量。采样数越低烘焙越快但噪点越多画面会像蒙了一层灰沙。移动端可以先从128开始看效果再往上加。最终采集烘焙完成后再做一轮全局平滑处理能有效去除残留噪点但烘焙时间可能直接翻倍。移动端建议在正式出包前开并且先只开一次试跑确认时间可接受。环境光遮蔽距离控制AO的扩散范围。距离太大会让整个空间变暗、发闷太小又会让角落的阴影太碎。室内场景一般从0.3~0.5米起步风格化项目可以刻意调大写实项目克制一点。压缩设置烘焙完成的光照贴图默认可能是浮点格式体积巨大。移动端一定要在管线里设置成合适的压缩格式这一步省下的内存非常可观。参数之间是联动的采样数很低但分辨率很高噪点会变得特别明显分辨率很高但采样不够拉高分辨率只会让噪点更清晰采样数很高但分辨率太低过度平滑反而丢失细节。我给移动端项目的默认起步组合是直接光照分辨率比间接高两档、采样数128、开AO、先关最终采集、光照贴图最大尺寸2048。跑完看效果再逐项调整。3.3 从标记到烘焙的完整步骤把整个过程串成一套可复用的流程基本是下面这些步骤打开场景资源进入光照面板确认所有参与烘焙的物体都标了静态动态物体全部排除。检查所有静态Mesh有没有生成光照UV没有的立刻补一套。重点检查合并过的Mesh和从外部导入的大型建筑模型。摆放光照探针组。探针要覆盖动态物体的活动范围尤其是横穿场景的路径和门口、楼梯这类明暗变化剧烈的区域探针太稀会出现“飘着走”的光晕突变感。检查场景里的光源所有需要进烘焙的光源设置烘焙模式纯实时光源尽量只留给角色身边数量控制在个位数。先用低分辨率、低采样数试烘焙一遍比如把光照贴图分辨率设成512或1024采样数减半。这一步是为了检查光照布局、是否有漏光、接缝是否明显。确认大方向没问题后再按正式参数烘焙。烘焙过程中开着日志遇到进度卡住或者内存爆掉优先看是不是有超大Mesh或者极高采样数。烘焙完成后在移动端预览模式下检查一张光照贴图纹理确认尺寸、格式、压缩方案符合预期不要到真机上看时才发现问题。我的习惯是试烘焙和正式烘焙各留一档参数预设不反复手改。比如“低清测试”预设和“高清正式”预设一键切换。“低清测试”跑一次只要几分钟花这几分钟确认了大方向再跑正式能省下大量反复等待的时间。4. 移动端特有的体积与质量优化烘焙完成后画面可能已经很漂亮了但不代表可以就这样上手机。移动端有更苛刻的内存、带宽和发热限制光照贴图的体积和格式必须专门设计。4.1 压缩格式与内存优化光照贴图在刚烘焙出来时通常是高精度的浮点格式按RGBA计算一张2048×2048的贴图裸奔需要16MB甚至更高这个体积在移动端是完全不可接受的。必须转成带压缩的格式。移动端主流方案是ASTC格式。ASTC有多个档位压缩比和画质成反比4x4档质量最好体积相对最大适合近景墙面的光照贴图。6x6档质量与体积均衡是我在绝大多数室内场景的默认选择。8x8档压缩最狠体积最小适合大面积地形和远处光照铺底。光照贴图一般优先考虑LDR格式就行也就是把颜色亮度限制在0~1范围。HDR光照贴图能保留超过1的高光范围视觉效果更丰富但体积和带宽压力大不少。移动端项目我基本都是LDR只有特殊展示场景才用HDR并且局部用非常克制。内存估算上有个经验值一张2048×2048的LDR光照贴图ASTC 6x6压缩后大约能到1~2MB级别比原始浮点数据省了十倍不止。但注意光照贴图往往不止一张整个场景加起来几十张总量还是要严格控制。我在项目里会定一条红线整场景所有光照贴图总内存不超过多少超了就去砍高分辨率物体或者拆分区域。4.2 光照探针和动态物体的衔接动态物体无法从光照贴图取光靠的是光照探针。探针本质上是一个个记录光照球谐系数的点运行时角色取附近几个探针做插值得到一个近似的光照方向与亮度。探针摆放有几个容易被忽略的细节密度不能太均匀要跟场景明暗结构挂钩。门口内外、楼梯上下、大型落地窗旁边这些地方明暗变化剧烈需要加密探针空旷走廊中间可以稀疏一点因为光照渐变平缓。探针不能贴在墙面太近否则会记录到不合理的局部AO角色走过去会突然一暗。探针不要放在不可达区域比如二楼平台悬空位置连续跳跃场景里插值会产生错误的光照过渡。动态物体衔接还有个大坑角色站在烘焙好的静态场景里由于动态角色只能靠探针取光它的光子接收量与静态地面往往不一致看起来会“浮”在场景上面。变通做法是给角色脚下加一个低成本的实时阴影或者利用引擎的阴影距离设置让角色在近距离投射一小块实时阴影远处则靠烘焙的Shadowmask补齐主观视觉上就“落”地了。这个方法在移动端非常好用性能开销可以控制得很低。4.3 间接光与AO的移动端取舍烘焙之后间接漫射光和AO都已经躺进光照贴图里了移动端运行时几乎零成本。真正要做取舍的是烘焙阶段这俩效果值不值得让烘焙时间变长。AO是最值回票价的一个参数。移动端场景光照往往偏平跑完烘焙如果不开AO墙角、桌底、柜缝这些位置会亮得发假整个画面缺少立体感。烘焙时把AO开关打开距离控制在合理范围画面立刻会“沉”下去。风格化项目还经常故意调高AO强度阴影浓重一点美术风格更鲜明。间接光这块移动端不需要贪多。实时GI做不了烘焙GI可以做但给移动端烘焙时不要试图模拟特别多光的反弹通常两次反弹就够了。反弹次数越多烘焙时间越长收益却逐渐递减。移动端的画面最终靠的是直接光照的锐利阴影和AO的扎实感而不是复杂的光线弹射这是很多技术美术新手容易走偏的地方。5. 常见问题速查与实战排查烘焙光照的问题来来去去就那么几类但每类都够人折腾好几天。我整理了一份排查清单按“现象-原因-解法”的思路写照着查效率能高不少。5.1 接缝、漏光、噪点三板斧接缝是光照贴图最经典的毛病。表现是同一面墙或者同一个盒子的棱角处出现一道亮线或暗线原因是光照UV的岛与岛之间边距不够或者过滤时采到了岛外空白区域。第一步去检查光照UV的Padding小于4像素的直接调大第二步检查岛的数量一个盒子拆出几十个细碎小岛再怎么调也是接缝重灾区最好在DCC里重新生成UV少而大的岛比多而碎的小岛靠谱得多。第三步是有些引擎带“锁边缘”或“补边”功能烘焙后让贴图边缘自动外扩也能缓解接缝。漏光的现象很吓人明明被墙挡住的区域却透进了一团亮光或者椅子下面莫名其妙亮堂。常见原因是UV重叠两个区域的烘焙结果互相污染这时候就要回到UV编辑器里查红色重叠区域另一个原因是物体标静态失误比如墙是静态的但门框是动态的两块之间就会出现不连续的光照边界。排查时放一个简单的球体测试件手动移动看哪里漏出来比直接目测贴图快得多。噪点则是烘焙采样不足表现是光滑墙面上有脏兮兮的颗粒。加采样数是最直接的解法从128提到256或512噪点会明显减少。如果加了采样依然很脏大概率是分辨率太低把光照贴图分辨率翻一倍再烘一次。真的不想再跑长烘焙可以开最终采集做后期平滑但要注意烘焙时间会大幅上升适合作为最后手段。5.2 烘焙时间与内存失控怎么办烘焙时间爆炸通常是这几个原因采样数拉到512以上、场景静态物体数量太多、AO距离过大、超高质量参数同时叠加。排查时不要一个参数一个参数地猜直接把预设降到“低清测试”那一档再把场景里参与烘焙的大Mesh数量数一遍。如果只是等待时间过长可以尝试把场景切成几块分别烘焙再合并贴图但要注意接缝管理。内存失控则更棘手。光照贴图数量多、单张尺寸大、HDR贴图残留未压缩都会把内存顶爆。还有一个隐蔽问题图集碎片化。引擎会把UV岛打包进一张大图如果岛的形状和大小差异过大图集空间利用率很低明明没多少内容却要开好几张2048。解法是减少岛的碎块尽量让UV岛大小接近同时在导入设置里限制单张光照贴图的最大尺寸。烘焙到一半程序崩溃多数情况是内存不足。先把采样数和分辨率降下来关闭其他占内存的编辑器窗口别同时开着大量Scene面板预览。还有一个不直观但有效的操作把超大Mesh比如超过几百米的地形块拆成多个中等Mesh烘焙器的内存压力会小很多。5.3 排查问题速查表现象可能原因优先排查方向墙面有暗缝/亮缝光照UV边距不足增大Padding到4~8像素减少UV岛碎片墙角透光UV重叠或静态标记错误检查UV重叠区域核对Static标记光滑墙面有颗粒噪点采样数不足或分辨率过低提高采样数考虑开启最终采集烘焙时间过长采样数/AO距离/物体数超标先切低清测试预设拆分大Mesh烘焙时内存爆掉单张贴图太大或Mesh过大限制光照贴图尺寸拆大Mesh角色在场景中“浮空”动态物体光照衔接差补光照探针密度加近处实时阴影画面发闷、角落全黑AO距离过大减小AO距离适当提间接光强度光照贴图内存总量超标图集碎片化、未压缩统一UV岛大小转ASTC压缩格式这份表格基本上覆盖了我这两年排查问题时的第一反应。遇到问题先按表格从最可疑的源头查起很少需要从头到尾重新烘焙。我个人在实际操作中最深的体会是烘焙光照不是“点一下等结果”的按钮而是一套需要配合场景结构、UV规范、资源管理共同运转的工作流。每换一个项目美术风格不同、场景规模不同参数都要重新权衡。但底层的那套判断逻辑——静态动态怎么分、UV怎么摆、压缩怎么选、问题怎么查——是相通的把它吃透了换什么引擎都难不倒你。