1. 为什么贴图导出与后期优化会成为效率分水岭
做 3D 资产生意的朋友应该都有过这种体验:在 Substance Painter 里花了好几个小时把金属划痕、磨损、污渍一层层叠上去,画完之后感觉特别漂亮,结果一导出、放进引擎或者渲染器里,发现整张贴图怎么都不对劲——材质发灰、法线方向翻转、边缘接缝明显得像是拿记号笔描过一圈。很多人第一反应是软件出问题了,或者在引擎里疯狂调参数,但我可以直说,绝大多数情况下,问题都出在贴图导出前的通道设置和导出后的优化处理上。
Substance Painter 这个软件,说白了画贴图只是其中一半工作,另一半是你怎么把画好的东西交给下游。很多新手甚至一些在职设计师,都把导出理解成“最后点一下 Export”的动作,但实际上,一个合理的导出流程里藏着命名规范、通道取舍、尺寸策略、色彩空间、压缩格式、边缘修复这一大串事情。省掉这些步骤,你确实能快速拿到一堆后缀为 jpg 的图片,但从来没想过为什么引擎里看起来和软件里不一样。
这篇文章我不会照着官方手册给你念参数,而是从我实际处理过的项目里,把这些年在贴图导出和后期优化上踩过的坑、试出来好用的方法、以及现在固定下来的一套流程整体摊开。无论你是做游戏道具、场景地编,还是做产品渲染、元宇宙数字资产,只要主力流程是 Substance Painter 出 PBR 贴图,这套思路应该都能直接抄进你自己的管线里。我用实际工作里最常遇到的情况来讲,把能落地的操作放在前面,原理放在旁边,免得你听完一堆概念回头还是不知道怎么下手。
先给你一个总的认识:Substance Painter 出图这件事,本质上是“把纹理集的通道信息,按照下游渲染器的规则,打包成一批文件”。前期在软件里花大把时间画的图层,最后全部要通过通道重映射、尺寸缩放、格式压缩才能变成引擎真正吃的东西。你要是能在动手画材质之前就想清楚下游需要什么、要什么精度、用什么颜色空间,后面导出就是一条直线,几乎没有返工。真正让你加班到半夜的,永远不是画画本身,而是乱导、错导、再重导。
2. 导出前先在 Substance Painter 里把“底子”摆正
2.1 别把纹理集当成 UV 的附属品,它是你导出的最小单元
不少人打开 Substance Painter 后,默认的纹理集叫 TextureSet_0,后面一看网格物体多,纹理集也跟着多出一大片,就顺手导出,也不管命名。这个习惯非常坑,因为纹理集的名字就是导出文件名的根,你在项目里建多少个纹理集,几乎就等于要导出来多少组贴图,而且每个纹理集的 UV 布局、填充、分辨率都独立维护。如果你一开始不规划纹理集,后面排查问题时,光找文件就能耗掉半小时。
我常用的思路是这样的:拿到一个模型后,先想清楚最终会被拆成几套材质。一个道具如果只有一套材质,那就一个纹理集;一个角色如果身体、皮肤、衣服要分开调,那就拆成多个 TextureSet,并且新建纹理集时就把它改成人话名字,比如 Body、Cloth、Armor,而不是留给系统默认值。
有些小伙伴可能会想,那我是不是尽量少建纹理集、把东西全塞在一个里面省事?分情况。如果你只做实物类非 CG 插画,可以;但做角色或者带软硬表面区分的载具,尽量按材质区拆。因为不同材质需要独立的 UV 摆布和填充密度,强行塞一起会导致 UV island 被缩得特别小,贴图分辨率再高也没用,渲染时糊成一团。
2.2 通道配置是贴图导出质量的隐形开关
Substance Painter 默认的 project 通道有 Base Color、Normal、Height、Roughness、Metallic、AO,也能自定义保存为自发光、透明度等。你在项目开始之前就要打开 Edit > Project Configuration,把不需要的通道关掉,把要用的通道选对。为什么要多花这一步?因为通道越多,导出时数据量越大、文件越臃肿,而且某些通道如果一开始没开启,后面画图层时根本找不到对应选项。
我这里重点说一下三个最容易弄混的通道:Metallic、Roughness、AO。很多美术同学把 Metallic 当作“颜色”来画,习惯性地用黑白灰度去区分金属和非金属,这从结果是没问题的,但你要注意 Metallic 通道不处理颜色信息,只存浮点值。表面刮痕如果不能影响金属度,后期想单独做一层划痕放在金属度上,你会发现划痕画上去是灰的,因为它只能响应颜料覆盖的灰度。另一个关键是 AO 要不要导出。如果你做的是写实向游戏资产,AO 肯定是要出的;但 AO 很容易在软件里看挺好,一到引擎里整个物体显得“脏脏的”,因为引擎里的环境光照和你画材质时的默认环境差异太大。更好的习惯是:AO 导归导,但后期可以在引擎里把 AO 强度压低,不要把 SP 里的 AO 当作定死的成品。
还有一个经常在导出时翻车的点,是 Height 通道。有些模板会自动把 Height 转成 Normal,导致你明明导出了两层法线,最后叠加起来细节“重影”。所以我建议,如果你不准备用视差或曲面细分,项目通道里直接不要开启 Height,省得导出模板里冒出来一堆你根本没用上的文件。如果你确实要 Height,那我建议在 Substance Painter 的“计算法线”功能里指定高度来源,而不是最后才想起来多勾一个选项。
3. 模板选择的取舍:没有万金油,只有用途匹配
3.1 先认清下游渲染器到底吃哪套 PBR 规则
Substance Painter 的导出面板里预制了一堆模板:Unreal Engine 4、Unity 5、PBR Metal/Rough、PBR Spec/Gloss、Marmoset Toolbag、Arnold 等。不少同学每次都是随手选一个,反正名字看起来差不多。但这里有个最根本的门槛,就是渲染器采用的是 Metal/Rough 工作流还是 Spec/Gloss 工作流。Metal/Rough 是现在游戏和实时渲染的主流,Unreal、Unity 默认都是它;Spec/Gloss 常见于离线渲染和部分旧引擎。
如果你是做游戏或者给实时渲染项目出图,直接选对应的引擎模板基本没问题。但我个人不太建议完全依赖默认模板,因为引擎版本不同、Shader 版本不同,对贴图后缀和颜色空间的要求会有差异。例如某些版本的 Unity HDRP 里,Metallic 和 AO 会拼在一张 Mask 图里,R 通道存 Metallic、G 通道存 AO,这属于项目内部约定,模板里未必帮你预设好。这时候你需要自定义一套导出配置,而不要等着模板来救你。
3.2 自定义模板里最容易被忽略的两个参数:尺寸与后缀
自定义模板面板里,大家最常盯着“格式选 PNG 还是 TGA”,却很少去改文件名的后缀变量。Substance Painter 支持用 $mesh、$textureSet、$colorSpace 等变量来控制导出文件名的结构。如果你每次导出的文件名都带着一堆默认变量,比如 terrain_03_objs_BaseColor_$mesh,再加上引擎那边的规则对不上,面对一堆无规律后缀的文件时你会崩溃的。
我实际用的命名结构是:资产名_纹理集名_通道名。比如树桩模型叫 stump_01,材质拆了 Bark 和 CrossSection 两个纹理集,那么导出的基础色应该是 stump_01_Bark_BaseColor.png,而不是一堆丢在文件夹里的 BaseColor_color.png。这个习惯在推进项目交接时非常香,别人拿到文件夹看文件名就知道属于哪个模型、哪套材质、哪个通道。你在导出一开始就要把模板变量的顺序定好,后面每一次重导都不需要再改文件名。
另外还有一个隐蔽开关是“Resize”,如果你项目里某些纹理集是 2K,另一些是 4K,导出模板里千万不要勾选“Resize all to...”统一缩放,除非项目规范要求所以贴图强制单一尺寸。如果强行把 4K 纹理缩到 2K 导出,等于砸掉了高模细节和手绘细节,后期再想补救是不可能的。
3.3 法线贴图的方向与翻转问题,别指望引擎帮你调
如果你把 Substance Painter 导出的法线贴图拿到另一个软件里使用,经常发现光照方向反了,凹的地方凸起来,凸的地方凹下去。这基本是 Y 轴或者 Green 通道方向不匹配导致的。Substance Painter 默认导出的是 DirectX 格式的法线贴图,OpenGL 格式的法线贴图在 Green 通道上是反的。
很多人在 Unreal 里没感觉,因为 Unreal 默认接受 DirectX;但如果你要拿去 Blender、Marmoset 或者多数离线渲染器里用,那边通常吃 OpenGL,你就要在导出设置里把 Normal 通道的格式从 DirectX 切到 OpenGL,或者在后期用工具翻一下 Green 通道。这个问题最恶心的地方是它不影响你在 Substance Painter 里看到的画面,因为软件内部会针对不同格式做补偿,只有等下到别的软件里才爆雷。切记,法线贴图的正反方向是一票否决项,哪怕只反了一张,整个资产的造型感都会垮掉。
4. 高效出图:命名、目录与批量重导的实战习惯
4.1 先把资产目录建好,导出就是照线路走
我见过太多人把导出的贴图全部丢到桌面或者一个叫 export 的文件夹里,后续资产一多,整个目录就成了灾难现场。我的固定习惯是:在每个资产的主目录下,建一个 textures 子文件夹,里面按纹理集分组再建子目录。比如某个手持道具项目,结构大概长这样:
Assets/props/axe_hero/textures/body/ Assets/props/axe_hero/textures/handle/ Assets/props/axe_hero/textures/metal/这样一次导出时,直接把导出路径分别指到纹理集所对应的子文件夹里。你可能会说分组子目录有点多,但如果某天发现了问题要重导,只需替换对应的一组贴图,不用整个资产目录都翻一遍。尤其是做版本迭代时,我只替换 body 组,不会动 handle 组,旁边协作的渲染师一眼就知道你改了哪个部位,省了多少沟通成本。
同时建议目录里放一个 README 或者资产卡文件,把三件事写清楚:模型面数、贴图分辨率、使用的渲染器版本。这不是给别人看的,是给你自己留的。一个月后你再回看旧项目,对着 README 里的记录回忆当时怎么导的,远比你翻半天工程文件靠谱。
4.2 批量导出与增量重导的联动
Substance Painter 的 Export 对话框里可以保存多套预设,这是个被低估的功能。我建了三套:Game 2K、Game 4K、Offline Render。游戏方向用 8bit 压缩格式、带 Mipmap;离线渲染方向用 16bit 的 TIF 格式、保留更多灰度信息。切需求时直接点预设,不需要每次重新配参数。
增量重导真正的痛点是图层调整。比如你在 Substance Painter 里只改了一处粗糙度,没有改其他通道,理论上没必要把整套贴图重新导一遍,因为大文件 IO 和下游压缩都要时间。很多项目组会直接整包重导,浪费很多时间。我的方法是:每次大改之后先导出一个“验证版”,也就是只导出基础色、法线、粗糙度三张图,尺寸降一档,丢进引擎里快速看一眼,确认没问题再执行最终完整导出。这个习惯帮我平均省下至少四分之一的时间,而且不用每次都守着导出进度条发呆。
还有个小技巧:Substance Painter 的导出面板里有一个“输出缓存”的概念。如果你只是改了某个图层参数,软件不一定重新计算所有纹理集,它是按资源状态增量计算的。你可以在 Export 的时候只勾选变更过的纹理集,不要图省事把整个项目全部打勾。Substance Painter 会聪明地处理增量提交,但前提是你别把所有 TextureSet 重新计算一遍。
4.3 为什么不建议所有图都导成 16bit
有人为了追求质量,把基础色、法线、粗糙度全部导成 16bit 的 TIFF,觉得高精度更可靠。但大多数实时渲染引擎在运行时只吃 8bit 压缩贴图,16bit 贴图进引擎后要么被强制性转换,要么白白浪费显存和带宽。你要区分清楚:哪些通道需要 16bit?在我看来,高度通道、流量密度图、形变数据这些浮点信息才用得上 16bit;而 Base Color、Metallic、Roughness,8bit 完全够用,前提是压缩格式别太离谱。如果你做的是电影级别离线渲染,烘焙阶段需要保留更多精度,那当然可以用 16bit,但导给引擎或者移动端项目时,还是切回 8bit 更务实。
5. 后期优化实战:把贴图从“软件里好看”变成“引擎里好用”
5.1 颜色空间与压缩比例,别再乱选了
导出到引擎之后,第一个要检查的就是颜色空间。用一句话概括规则:基础色(BaseColor/Diffuse/Albedo)必须设置为 sRGB,而法线、粗糙度、金属度、AO 全部设置为线性(Linear)。这个错误我见过太多次了,有些同学把整组贴图都设为 sRGB,结果是粗糙度贴图变得偏灰、金属度产生色偏,物体的反光和材质感全都不对。
如果你用 Unreal,导入贴图时需要在纹理编辑器的 Compression Settings 里选择正确的类型:BaseColor 用 “sRGB, 8bit” 或者 “BC7”,法线和粗糙度用 “Normalmap” 和 “Masks (sRGB 不勾选)”。Unity 里也是一回事,勾选 sRGB 选项要跟通道属性对齐。判断依据很简单:Normal、Metallic、Roughness、AO 这些都存储的是浮点数值,把数值当颜色来解码就会出问题。
压缩比例我这里说个实践值:基础色我一般用 BC7 或高质量的 PNG 也可以;移动端项目推荐 BC3 转 ETC2/ASTC;法线贴图用 BC5,因为它把两个通道专门存为高精度,比把法线直接转成彩色压缩更理想;粗糙度和金属度通常用 BC4(单通道)或者直接放在掩码图里。如果项目允许,我建议把金属度和粗糙度合并到一张贴图的两个通道里,能明显减少文件数量,但要注意命名和 Shader 约定,别把通道对错了。
5.2 边缘处理、接缝修复与抗混叠
贴图导出来之后,最脏的是模型 UV 摊开的边缘。很多时候,Substance Painter 的默认填充已经处理得不错,但如果你在模型表面上画了颜色 ID 或像素级细节,UV island 边界常常会出现一条细线,尤其在 Alpha 或 ID 的图层上。针对这个问题,我有两个工具链上的建议:一是把 Substance Painter 的填充模式调成“Stretch”,让边缘像素向外拉伸而不是直接复制;二是在导出到引擎里之后,为接缝明显的位置手动修补。
手动修补有很多办法,我试得比较多的是在 Photoshop 里对法线贴图和外接边缘做 3px 左右的柔化,不要大幅度模糊整张贴图,只需处理接缝附近的像素差异。过度抗混叠会吃掉细节,所以修缝原则是“窄范围、轻力度”。如果在 Marmoset 或者引擎里看接缝还是很明显,那就回头检查一下 UV island 间的填充范围,把 Padding 从默认的 4px 提高到 8px 或者 16px。不过 Padding 也不是越大越好,太大了会在边缘产生过度拉伸,尤其是法线贴图会出现“鼓起”的假轮廓。
5.3 用批处理减轻重复劳动
单独处理一两张开到 Photoshop 里修没问题,但一整个资产组十几张、几十张贴图,再手动来就是给自己找麻烦了。我一般会用命令行工具做批处理,比如用 ImageMagick 快速调整格式、缩略、翻转通道,不用开设计软件。
举个我常用的例子,把一组 OpenGL 法线贴图转成 DirectX 格式,本质上是让 Green 通道取反:
mogrify -channel G -negate +channel -path ./dx *_nor_ogl.png .如果电脑里装了 Python,配合 Pillow 库也能做类似操作。比如把一组图统一压成指定尺寸并改输出格式:
from PIL import Image import glob for f in glob.glob('textures/*.png'): im = Image.open(f) im = im.resize((2048, 2048), Image.LANCZOS) im.save(f.replace('.png', '_2k.tga'), 'TGA')这类脚本思路很简单,但能稳定实现三件事:转换颜色空间需要的通道翻转、把不同分辨率统一到项目规范尺寸、把命名里的错误前缀批量修正。我个人建议把这类脚本放在资产库的 tool 目录里,每次拿到新资产直接一键处理,又能省出半天时间去做更有创造力的事。
6. 常见问题与排查速查:我踩过的坑基本都在这
6.1 导出后一进引擎就发灰、发暗、太白
这类问题的根源大多是颜色空间标错或者粗糙度/金属度通道配置有问题。我做过一个快速定位矩阵,基本不用瞎试:
| 症状 | 最可能原因 | 对策 |
|---|---|---|
| 整体发灰、像蒙了一层雾 | 法线贴图没有被正确识别为 Normalmap | 在引擎里重新指定贴图类型为法线 |
| 金属发暗、高光不亮 | 金属度贴图被误设成 sRGB | 把 Metallic 通道改为线性/无 sRGB |
| 暗部细节全糊、脏得过分强 | AO 太强 | 压低 AO 强度或重出 AO 时降低对比 |
| 表面像塑料、没有质感 | 粗糙度贴图丢失对比度 | 检查粗糙度贴图直方图,适当拉大反差 |
很多人以为发灰是曝光问题,其实是线性和 sRGB 混乱。若出现上述情况,先回贴图导入设置逐项核对,通常不到五分钟就能定位。
6.2 接缝、摩尔纹和贴图糊掉
接缝问题已经在上一节聊过,这里讲摩尔纹。摩尔纹多数发生在远景看贴图时,细密的布料纹理、栅栏或者草地贴图特别容易出现。解决办法不是把贴图放模糊,而是在引擎里开启适当的纹理过滤和 Mipmap 生成。要是移动端平台还想省资源,就尝试把贴图的分辨率提高一档而不是提高过滤等级,因为摩尔纹本质是采样频率低于纹理信号频率造成的。多数 3D 引擎里给贴图设置 Generate Mipmaps 就能明显缓解,但有些压缩格式对高频细节不友好,比如过度锐化的法线贴图压缩后极其容易出摩尔纹。经验值:Normal 贴图的锐化半径尽量克制在 0.5px 以内,宁可细节平一点也别让画面“闪”起来。
6.3 后期优化时最容易忽略的“关乎全局”的细节
第一是显存。贴图后期优化不只是为了好看,更是为了性能。一个 4K 基础色贴图在内存里占约 64MB,如果全局有几十个材质,随随便便就是上 GB。做移动端或者中小型项目时,后期优化要拿出“减内存”的心态:离主镜头最近的主要道具才用 2K,大场景的背景物件 1K 甚至 512 足够了。不要舍不得,因为画面感受更多来自曝光和构图,而不是每一块地面都是 8K 纹理。
第二是我反复回购的一个习惯,永远保留一份未压缩的原始导出文件。很多人后期优化后直接把原始 PNG 删了,到了引擎里发现 BC7 压缩出现了色块或噪点,想找回原始文件只能重开 Substance Painter 工程再导一遍。我在每个资产目录下都会保留 _source 子文件夹,里面放最初导出、还没优化压缩的版本,压缩和平台适配版本放在 _platform 里。这样一来,每次修复 bug 时发言权都掌握在自己手里,不用再求着别人“帮我重导一下”。
第三是贴图文件后缀里带 V1、V2 这类版本号。如果你还在用文件名标注版本,换版本时旧文件留着就是一堆垃圾,删掉又怕浪费。更科学的是用文件夹分版本,比如 export_v1、export_v2,文件内部的名字全部保持一致。这样你复制新版本时,不会出现一堆带 _final_2 的文件,下面不知道哪个才是真正的最终版本。
7. 我个人摸索出的一套出图预案
最后再分享一个我现在固定使用的套娃流程,它不是什么灵丹妙药,但至少能保证我在中途被叫去开会、回来之后还能快速接上之前的工作。
第一步,项目启动时新建 Substance Painter 工程,立刻按材质拆好纹理集,并且把所有纹理集改名、把项目分辨率和输出目录定好。第二步,按照下游渲染器需求配置好模板,先跑一次“验证导出”,只出基础色、法线、粗糙度,检查文件名和后缀是否符合规范。第三步,把验证导出的贴图丢进引擎或者 Marmoset 简单搭一个场景看一眼,确认颜色空间和法线方向没问题。第四步,才真正开始画材质、做细节。第五步,最终完成之后再完整导出,进行压缩和平台适配,最后把原始导出文件归档到 _source。
这套东西看起来像是“最麻烦的路径”,但实际体验下来,它反而是最稳工时的。很多高级艺术家画到一半发现纹理集命名错了需要重建工程,那才是真正的地狱。导出和后期优化不是画完贴图的收尾动作,而是一个贯穿始终的质量管理流程。我之所以能在一堆项目并行时不手忙脚乱,靠的也真不是什么黑科技,就是把那些最繁琐、最不起眼的输出环节标准化了而已。