尧图精选

Substance Painter ID蒙版:多材质合并与Draw Call优化

🕒 发布时间:2026/10/1 16:36:12 📁 来源:尧图网络
很多教程讲 Substance Painter 的 ID 蒙版都是从新建填充层、加蒙版、吸颜色这三步开始讲讲完就结束了。可真到项目里卡住人的往往不是这三步而是前面模型怎么给材质、后面导出怎么把好几张图压成一张。我见过太多人蒙版画得漂漂亮亮最后导出的时候还是十条贴图挂在一个模型上draw call 一点没省下来。这篇就围绕一个具体问题展开一个模型身上有皮革、金属、塑料、布料好几种材质怎么用蒙版把这些材质的贴图信息合并到一张套贴图上。适合已经能跑通 SP 基础流程、但被多材质槽合并卡住的 3D 美术、TA以及需要给移动端项目做性能优化的同学。内容以实操为主中间会把每一步为什么要这么干讲透方便你迁移到自己的项目里。1. 先算清楚多材质槽到底吃掉了什么1.1 一次材质切换背后的真实开销在 Max 或者 Blender 里给模型分材质槽是很自然的事皮带用皮革材质、扣子用金属材质、包身用帆布材质分门别类清清楚楚。但这个清楚是给人看的引擎不关心你的分类美学。引擎渲染时一个材质槽基本对应一次 draw call更准确地说对应一次状态切换 一次绘制批次。模型上六个材质槽就是这个模型至少要被提交六次。移动端项目里一个角色身上挂十几个材质槽是常见操作几十个 draw call 就这么没了。而 draw call 在移动端是稀缺资源CPU 提交命令的开销往往比 GPU 画这点面还贵。除了 draw call还有两笔开销容易被忽略第一笔是材质资源本身。每个材质都要绑定一组贴图BaseColor、Normal、Roughness、Metallic 全都要各来一套。你那张 2048 的皮革 BaseColor 里可能只有 30% 的面积是真的皮革剩下 70% 全是空白的 UV 区域——显存照样按整张图扣。第二笔是批次被打断。理想情况下引擎会把相同材质的物体排在一起渲染但一个模型内部没法排序材质槽的切换是硬性的。尤其是模型面数不高但材质槽很多的时候渲染效率会被拖得很惨。所以合并贴图这件事的本质不是省几张图而是把一个模型的多材质结构压成一个材质结构让这个模型只需要一次提交。贴图合并只是手段不是目的。1.2 哪些项目该合并哪些别硬凑并不是所有情况都值得合并。我自己踩过几次坑之后总结出这么几条判断标准值得合并的情况目标平台是移动端、VR 一体机、或者是要跑在低配设备上的项目单个模型材质槽超过 3 个且模型在场景里会大量重复出现比如场景道具、环境零件各材质区域的贴图分辨率需求接近比如都只需要 1K 或 2K材质之间没有物理上的强区分需求靠近看也不会穿帮不建议硬合并的情况金属和布料贴着一张图分辨率被强行拉平。金属需要高分辨率来表现划痕细节布料 512 就够合并后要么金属糊要么布料浪费各区域的 UV 展开密度差距太大合并后统一分辨率会导致某些区域严重欠采样模型后期还要单独替换某一种材质比如做皮肤系统合并了就没法单独换引擎本身支持材质实例化、且这批模型共享同一套材质参数那不合并也能有不错的批次表现提示合并前先跟渲染同学确认引擎的实际瓶颈在哪。如果瓶颈是面数或者带宽合并材质带来的收益可能不如降分辨率明显。还有一个很实际的判断点这个模型是不是独立物件。一个独立的背包、一把枪、一个道具箱合并收益明显一个由几百个小零件组成的大型场景合并工作量巨大且容易出错这时候更该考虑的是用图集、实例化或者引擎侧的合批方案。2. 两条能走通的路合并纹理集还是用蒙版做叠层Substance Painter 里实现多材质一张图我实际操作下来有两条路径各有各的适用场景。标题里说的蒙版实现是第二条但第一条也值得先了解一下因为它决定了你前期要不要在 DCC 里做特殊处理。2.1 路线 A保留多纹理集导出时合并SP 会把从 DCC 导入的每一个材质槽识别成一个独立的Texture Set纹理集。六个材质槽进来左边纹理集列表里就是六个条目每个都有自己完整的图层栈、自己的烘焙贴图、自己的图层组。较新版本的 SP 提供了纹理集合并入口大致位置在纹理集列表上右键。合并的前提条件比较苛刻被合并的纹理集必须有不重叠的 UV。SP 的做法是把它们各自的 UV 重排到不同的 UDIM 象限里去所以合并之后你的模型其实是被拆到了多个 UV tile 上分辨率、烘焙设置要一致否则合并出来的结果会很怪合并是破坏性操作做完之后原来的 UV 布局会变如果后续还要回 DCC 改模型重新烘焙会很麻烦合并完成之后你得到的是一个纹理集、一张 UV 布局跨 UDIM、一套贴图。导出时再配合导出模板里的合并选项就能一次性输出。这条路的好处是前期不用改模型DCC 里该怎么分材质就怎么分美术的工作习惯不变。坏处是 UDIM 重排之后 UV 空间利用率会下降而且一旦合并模型的 UV 就和 SP 工程绑死了后期迭代成本高。2.2 路线 B单纹理集 Color ID 蒙版叠层这是我更常用的一条路也是标题里说的那种做法。核心思路是从一开始就让模型只有一个纹理集所有材质效果都在这一个纹理集的图层栈里用蒙版叠出来。具体来说在 Max / Maya / Blender 里把模型所有面一次性指定给同一个材质槽这样导入 SP 后只会生成一个纹理集各区域的区分信息不靠材质槽来承载而是烘焙一张 Color ID 贴图来承载每块区域一个纯色在 SP 里每种材质做成一个填充层层上加一个 Color Selection 蒙版把这块区域的 Color ID 颜色选中这样一来图层栈大概长这样纹理集Backpack ├── 布料底色层 ← 蒙版Color Selection 青色 ├── 皮革底色层 ← 蒙版Color Selection 品红 ├── 金属底色层 ← 蒙版Color Selection 黄色 ├── 划痕/磨损层 ← 蒙版Color Selection 程序化噪声 └── 手绘细节层每个层都共用同一套 UV、同一张输出贴图。导出的时候无论你叠了多少层材质SP 输出的还是 BaseColor、Normal、Roughness 那几张图每张只有一份。这条路的好处是 UV 完全自主可控、迭代方便、图层结构清晰可读。代价是前期要在 DCC 里做一步材质归拢的处理而且蒙版边缘需要花点功夫修干净。2.3 两条路线的取舍对照对比项路线A纹理集合并路线B单纹理集ID蒙版DCC 前期改动不需要需要归拢材质、指定 ID 色UV 控制权交给 SP 重排到 UDIM完全自主迭代成本高改模型要重新合并低重新烘焙即可边缘质量取决于 UV 边界取决于蒙版锐化处理适合场景模型已定型、材质分区天然清晰长期迭代的项目、需要精细控制图层可读性各纹理集独立结构分散全部在一处一目了然我的建议是模型还会改的走路线 B模型已经定版、只想快速出图的可以试路线 A。下面主要讲 B因为它的坑更多、细节更值得展开。3. 动手之前把材质 ID 分配这步做扎实3.1 在 DCC 里给每块区域一个可识别的纯色路线 B 的第一个关键动作发生在 SP 之外。核心原则是同一材质区域在 Color ID 上必须是完全均一的颜色不能有任何渐变和插值。在 3ds Max 里的做法是先给整个模型指定一个材质然后进入面级别Polygon选中属于皮革的那批面给它们指定一个独立材质材质名比如ID_Leather把这个材质的基础色设成纯品红R255, G0, B255。金属那批面给ID_Metal纯黄色。以此类推。这里有个细节很容易翻车色值不要选相邻色相。我第一次做的时候给两个材质分别设了 (255,0,0) 和 (255,30,30)烘焙出来的 Color ID 因为反锯齿和压缩两个颜色的差值被抹平了一部分蒙版 Tolerance 稍微开大一点就互相串色。后来统一改成 R、G、B 三个通道只在 0 和 255 之间取也就是只用纯红、纯绿、纯蓝、纯黄、纯青、纯品红、纯白、纯黑这八种问题就没了。这八种颜色在 RGB 空间里距离最远抗干扰能力最强。另一个细节是材质数量别超过八个。超过八个就得引入中间值色距被压缩蒙版容差的可调窗口就变窄了。如果区域真的多于八个可以考虑用两个 ID 图层组合的方式或者干脆拆成两个纹理集。归拢完之后把模型所有面重新统一到一个材质上再导出 FBX。这一步不能漏否则 SP 还是会按材质槽拆纹理集。做法是全选所有面指定回那个唯一的材质。但这样 Color ID 的颜色信息就丢了——所以要么在导出前先把颜色烘焙进顶点色要么在 SP 里用另一套办法。3.2 Color ID 烘焙参数与常见的失败场景在 SP 里烘焙 Color ID路径是 Baking 面板里的Color ID这一项。这里的关键参数是颜色来源Color Source选Material Color的话SP 会去读模型材质上的基础色。但前提是材质信息在 FBX 里被完整带过来了而且 SP 导入时确实识别到了多个材质——这跟只保留一个材质槽的做法是冲突的选Vertex Color的话SP 读的是模型的顶点色。这条路更可控因为它跟材质槽没有依赖关系所以我实际用下来更稳的流程是走顶点色在 DCC 里给不同材质区域刷上不同的顶点色同样是那八种纯色模型只保留一个材质槽导出时勾上顶点色选项。SP 里 Color ID 烘焙选 Vertex Color出来就是干净的色块。这里有个必须提醒的前提顶点色在硬边和 UV 接缝处会出问题。因为顶点色是按顶点存储、按面插值的如果一个顶点被多个材质区域共用那这个顶点的颜色只能是一个值插值就会在交界处产生渐变。解决办法是在 DCC 里对材质交界处做按面分离顶点Split Vertices / Break让交界处的顶点各自独立颜色就不会互相污染。代价是顶点数会涨但对于道具级别的模型完全可接受。烘焙失败的几种典型表现烘焙出来全是黑色或者单一颜色 → 检查是不是所有面都被指定成了同一个材质或者顶点色没导出去交界处出现明显的渐变带 → 顶点没分离插值导致Color ID 上出现噪点或色斑 → 模型上有重叠面、非流形面或者 UV 有翻转烘焙卡在某一步不动 → 通常是模型面数过大或者显卡驱动问题可以先降低烘焙分辨率试3.3 顶点色方案和材质色方案到底怎么选这里用一张表把两者的差异列清楚方便按项目情况选维度材质色方案顶点色方案依赖关系依赖 FBX 材质信息完整传递依赖顶点色导出纹理集数量导入后是多个需要合并始终只有一个交界处质量天然干净材质边界是硬的需要分离顶点才干净改动成本改材质分配即可改材质后要重刷顶点色对模型的影响无可能增加顶点数我的推荐度模型定版后使用需要频繁迭代时使用实际项目里我一般是这么处理的如果模型已经锁版直接走材质色 纹理集合并如果还在反复改造型走顶点色。两条路的 SP 部分操作是一样的只是烘焙那一步的来源选项不同。4. 蒙版叠层实操一层材质配一个蒙版4.1 用 Color Selection 建立第一层蒙版主流程开始。假设模型已经导入、Color ID 已经烘焙好现在要往图层栈里加材质。第一步新建一个填充层Fill Layer在图层属性里把它要影响的通道打开——BaseColor、Roughness、Metallic 这些按需勾选。给它一个基础的皮革颜色。第二步建立蒙版。最省事的方式是在图层上右键选Add mask with color selectionSP 会一步到位地给这个图层挂上一个黑蒙版蒙版上再接一个 Color Selection 效果节点。这个右键菜单项是我最常用的入口比手动加黑蒙版再拖 Color Selection 快得多。第三步拾取颜色。在蒙版里选中 Color Selection 节点属性面板上有个吸管点击后在视口里点一下皮革区域的 Color ID 色块。这时候你会看到蒙版上那块区域变白图层效果立刻显现。这里建议养成一个习惯拾色时用视口的 2D 视图对着烘焙出来的 Color ID 贴图点而不是在 3D 视口随便点。3D 视口里拾到的是当前光照下的显示颜色跟 Color ID 的真实色值可能有偏差容易导致 Tolerance 调不准。4.2 容差、模糊和锐化把边缘修干净Color Selection 节点最核心的参数是Tolerance容差。它的作用是告诉 SP跟拾取颜色相差多少以内的像素也算这块区域。容差调到 0蒙版边缘会非常硬但可能出现锯齿和漏白烘焙时反锯齿产生的中间色没被包含进去容差调大边缘会变得干净但超过一定阈值之后相邻的材质颜色会被一起吃进来出现串色。我一般按这个顺序调先设 Tolerance 为 0看蒙版边缘有没有缺口每次加 0.01直到边缘完全闭合在相邻材质区域边缘来回放大检查确认没有串色如果串色出现了说明两种 ID 颜色太接近回去改 DCC 里的色值不要靠调容差硬凑调完容差之后边缘往往是带一点软的过渡。这时候加一个Sharpen锐化滤镜接在 Color Selection 后面把它往前推成硬边。Sharpen 的强度不要拉满一般中间值附近就够了拉太满会出现一圈黑色的描边噪点。反过来如果某块材质的交界本来就需要自然过渡比如生锈金属和未生锈金属之间的渐变那就不加锐化甚至可以在 Color Selection 之后接一个Blur模糊让过渡更柔和。这个模糊半径建议控制在贴图尺寸的 0.5% 到 1% 之间2K 贴图就是 10 到 20 像素左右。注意蒙版处理是逐像素运算模糊和锐化都会增加计算量。图层多的时候能把锐化合并到最后一次性处理会更快。4.3 蒙版的加减组合以及图层顺序的讲究单层材质做完剩下的就是复制这套结构给每块区域各做一层。这里面有两个容易乱的地方。第一个是蒙版的加减。如果你想让某个图层同时影响两块不相邻的区域可以在蒙版里再加一个 Color Selection两个节点会被自动相加白色区域叠加。如果想让某层排除某块区域可以给蒙版加一个 Color Selection然后把它的混合模式改成 Subtract或者直接把它反相。举个实际例子我要做所有金属和塑料部件都要加的一层污渍效果那就建一个污渍层蒙版里放两个 Color Selection一个选金属色、一个选塑料色Top 模式下自动相加一层搞定。反过来如果要做除了金属之外的地方都加一层灰尘那就建一层灰尘蒙版里放一个 Color Selection 选金属色然后把蒙版反相。第二个是图层顺序。图层栈是从上往下叠加的上层盖下层。理性的顺序是最底下放各种材质的基础色层BaseColor 层往上放材质表面的通用处理层污渍、灰尘、磨损再往上放局部细节层金属划痕、布料褶皱加深最上面放手绘层和特殊效果层这里有个坑上面层的蒙版必须自洽。如果你在顶层画了一笔手绘但它下面的材质层蒙版没覆盖这块区域那这一笔就会画在空白 UV 上导出后是一块漂浮的颜色。我习惯的做法是在图层栈最上面单独开一个手绘文件夹画之前先用吸管确认一下当前区域的归属。4.4 程序化材质和手绘细节怎么插进这套结构蒙版搭好之后SP 的程序化材质比如Metal Iron Rusty、Fabric Denim可以直接套进来用。做法是把原本的填充层换成材质层Material Layer或者保留填充层然后在它上面叠一层材质层并继承蒙版。继承蒙版的做法是右键蒙版所在的图层选复制蒙版然后粘贴到材质层的蒙版槽上或者在新建材质层的时候按住蒙版拖拽过去。SP 的蒙版是可以在图层之间复制的这个操作能省大量时间。程序化材质的好处是它自带完整的 PBR 参数直接套上去不需要自己配参数。坏处是它的默认缩放比例往往跟你的模型不匹配——它默认可能是按 1 米为一个纹理循环你的背包只有 30 厘米套上去就变成了一整块糊掉的图案。这时候要在材质层的属性里调UV Scale或者给 UV 加一个投影方式来手动控制密度。手绘细节的插入方式比较直接新建一个 Paint 层放在顶部在视口里用笔刷画SP 会自动记录到当前纹理集的 UV 上。如果只想画在特定材质区域内可以给手绘层也挂同样的 Color Selection 蒙版这样超出区域的笔画就不会显示。这个技巧在处理金属边缘高光皮革缝线这类局部效果时特别省事。5. 导出环节把多张图真正压成一张5.1 Output Template 里那个容易被忽略的合并选项图层叠完了真正决定输出几张图的是导出配置。在 SP 的导出面板里选中一个 Output Template右侧会展开模板的配置项。除了常见的文件格式、尺寸、Padding 之外还有一个跟本文主题直接相关的选项Merge texture sets合并纹理集。这个选项在不同版本里的位置和叫法略有差异有的是在主配置区有的是在模板编辑窗口的高级选项里找不到的话可以向旁边滚动一下或者切到模板编辑模式看看。勾上它之后SP 会把所有纹理集的输出合并到同一套贴图文件里。这里有两个硬性前提各纹理集的 UV 不能重叠重叠了合并之后会互相覆盖各纹理集的输出分辨率必须一致一个 2K 一个 4K 是合不到一起的如果你走的是路线 B单纹理集 蒙版那这一步其实不需要勾——因为本来就只有一套输出。合并选项是给路线 A 准备的。还有一个值得注意的配置输出通道的选择。SP 默认的 PBR 模板会输出 BaseColor、Roughness、Metallic、Normal、Height、AO 一大串很多项目根本用不上全部。在模板里把不需要的通道关掉输出的文件数量会直接减半。这一步对包体大小的影响往往比合并材质本身还大。5.2 通道打包把几张灰度图塞进一张图的 RGB合并材质省的是套数通道打包省的是张数。这两件事经常要一起做。Roughness、Metallic、AO 这三张图都是灰度图单独存的话每张都要占一个完整贴图的显存。把它们分别塞进一张 RGB 贴图的 R、G、B 三个通道里显存占用直接降到三分之一。不同引擎的通道约定不一样这个必须提前跟渲染同学对齐搞错了表现会完全错乱引擎/管线RGBAUnrealORMAORoughnessMetallic未使用Unity HDRPMask MapMetallicAODetail MaskSmoothnessUnity URPMetallic——Smoothness如果 SP 的导出模板没有现成的打包配置可以自己在模板编辑里新建一个把不同来源的通道拖到同一个输出目标的 R/G/B 上。实在不行SP 导完之后用脚本离线打包也可以Python 里几行就够from PIL import Image # 三张灰度图尺寸必须完全一致 ao Image.open(ao.png).convert(L) roughness Image.open(roughness.png).convert(L) metallic Image.open(metallic.png).convert(L) # 按 Unreal 的 ORM 约定打包RAO, GRoughness, BMetallic packed Image.merge(RGB, (ao, roughness, metallic)) packed.save(T_Backpack_ORM.png)用这个脚本的时候注意两点一是三张图的尺寸和色彩空间必须一致二是做完之后要检查一下sRGB 标记。灰度数据图Roughness、Metallic、AO都应该是线性空间的如果被当成了 sRGB 处理引擎里读出来的数值会偏金属会变得不够亮或者粗糙度整体偏移。这个问题我遇到过两次排查了半天才发现是导出时色彩空间设错了。5.3 Padding、Dilation 和命名规范导出配置里还有几个参数不注意的话会在引擎里看到明显的接缝和色边。Padding指的是 UV 岛之间预留的空白像素。做合并贴图的时候这个值要适当调大因为合并之后 UV 岛的间距可能变小了。经验值是1K 贴图用 4 到 8 像素2K 用 8 到 164K 用 16 到 32。Dilation扩张/外扩是把 UV 岛边缘的颜色向外扩展若干个像素防止引擎在低分辨率 mipmap 下采样到空白区域。这个功能在 SP 的导出里通常和 Padding 一起出现建议打开。命名规范这件事听起来很琐碎但真的能救命。合并之后贴图数量变少了很容易出现这张图到底是哪套材质的这种疑问。我自己的习惯是用T_模型名_用途的格式比如T_Backpack_BaseColor.png T_Backpack_Normal.png T_Backpack_ORM.png前缀T_表示 Texture模型名统一用途用引擎的老规矩。这套命名在项目里混着几百张贴图的时候能省下大量靠眼睛认图的时间。另外注意大小写——有引擎对文件名大小写敏感有时候在 DCC 里看着好好的贴图进引擎就报引用错误八成是路径大小写对不上这个问题跟合并无关但经常和合并一起出现排查的时候别被带偏了。6. 几个真实翻车现场和定位路径6.1 引擎里贴图正常但材质交界处发黑或发亮这是合并之后最常见的问题表现是两种材质的交界处出现一条明显的暗边或者亮边。排查顺序是这样的先看是不是 Padding 不够。把导出的贴图放大到交界处如果能看到 UV 岛的边缘有颜色溢出到空白区说明 Padding 太小回去调大重新导出。再看是不是蒙版边缘没修干净。把 Color ID 贴图和蒙版单独导出来对比看交界处是不是有一条灰度过渡带。如果是在蒙版后面补一个 Sharpen。最后看 mipmap。贴图在引擎里生成 mipmap 之后低层级上两种材质的颜色会被平均到一起交界处就会出现过渡色。如果只在远距离出现、拉近了就好那基本就是这个原因。解决办法是给这张贴图关闭 mipmap代价是有闪烁风险或者把 Dilation 调大一些让过渡更自然。提示定位这类问题的时候把 BaseColor 单独导出成纯色版本每个区域一个纯色先跑一遍能快速判断问题出在贴图本身还是出在引擎采样上。6.2 蒙版串色UV 重叠和颜色接近的两种成因蒙版串色的表现是给 A 材质刷的蒙版结果 B 材质区域也跟着变了。第一种成因是 UV 重叠。有些模型为了省 UV 空间会把对称部件共用一段 UV比如左右两个肩带。这种情况下两块区域在 Color ID 上是不同颜色但在 UV 空间里是同一块蒙版自然就分不开了。解决办法只有两个要么把 UV 拆开要么把这两块区域当成同一种材质处理。前者的代价是 UV 利用率下降后者是材质表现被绑架。第二种成因是 ID 颜色太接近。前面说过的色值别只用 R 通道的 255 和 254 这种差异尽量用红绿蓝的组合拉开距离。如果已经做完了才发现颜色接近不用回去改模型——在 SP 的蒙版里给 Color Selection 加一个 Tolerance 的负向调整或者用两个 Color Selection 做交集有时候也能救回来但这是应急手段长期还是建议前期规划好。第三种比较隐蔽的成因是烘焙分辨率不够。Color ID 烘焙分辨率如果比最终贴图低一档交界处的像素会被平均容差调小就漏、调大就串。建议 Color ID 的烘焙分辨率至少和最终贴图一致有条件的话高一档更稳。6.3 合并之后文件体积不降反升这是个很反直觉的情况明明把六套贴图合并成一套了为什么包体反而变大了原因通常是分辨率被统一拉高了。原本皮革用 2K、塑料用 512合并之后所有区域都在一张 4K 图上总像素数可能比原来还多。合并的正确姿势是合并不等于升级要根据所有区域里最高的需求来定尺寸而不是无脑拉满。另一个原因是通道都导出了。原本每套材质可能只用了 BaseColor 和 Normal合并之后导出模板上的所有通道都开着多出来一堆用不上的 Height、Emissive。回去把模板里多余的通道勾掉。还有一种情况是压缩格式没跟上。移动端项目里BaseColor 一般用带 alpha 的压缩格式法线用两通道压缩格式数据图用单通道格式。如果合并之后所有贴图都用了同一个通用格式体积会明显膨胀。这个要在导出模板里按用途分别指定格式不能图省事全用一种。我自己的一个检查习惯是合并前后的包体对比做完之后把两版贴图都放进引擎跑一次 Profiler看显存占用和 draw call 的实际变化。有时候显存降了但 draw call 没降那说明合并哪里没生效需要回去检查纹理集的合并状态。最后分享一个我踩过的小坑SP 工程文件的体积也会随着图层数量线性增长。做蒙版叠层的时候如果你复制了大量的材质层和蒙版层工程文件会从几十兆涨到几百兆打开和保存都变得很慢。我的做法是在保证效果的前提下尽量合并同类型的图层比如把所有磨损类效果整理到一个文件夹里统一管理把中间过程的图层删掉只留最终效果层。SP 的图层不是越多越专业能一层搞定的绝不用两层。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →