1. ArmorPaint 是什么:一个被严重低估的实时 PBR 纹理绘制引擎
ArmorPaint 这个名字听起来像某种军事装备或游戏模组,但其实它是一个开源、跨平台、基于 GPU 加速的实时 PBR(Physically Based Rendering)纹理绘制工具。它不是 Photoshop 的轻量替代品,也不是 Substance Painter 的简化版——它走的是完全不同的技术路径:把整个纹理创作流程压缩进一个实时渲染管线里,让画家在“材质即所见”的环境中直接作画。我第一次在 Blender 社区看到有人用它给低模角色快速铺贴法线+粗糙度+金属度三张图时,第一反应是“这怎么做到的?没烘焙?没 UV 展开预处理?”——结果发现,它压根不依赖传统 UV 坐标系统,而是用一种叫“3D Paint Mode”的空间投影机制,直接在模型表面“喷涂”材质属性。关键词里虽然没填,但它的核心标签必须是:GPU 实时渲染、PBR 材质流、无 UV 绘制、WebGL/OpenGL 后端、开源 C++ 架构、离线本地运行。它适合三类人:独立游戏开发者需要快速迭代角色材质;3D 打印用户想给 STL 模型加真实质感;还有大量被 Substane Painter 订阅费劝退、又觉得 GIMP + Blender Shader Editor 太反人类的中小团队美术。它解决的不是“怎么画得更精细”,而是“怎么让材质反馈快到能跟上手速”。你拖动笔刷,0.8 毫秒后屏幕上就显示出带环境光遮蔽、微表面散射、各向异性过滤的完整 PBR 效果——这种延迟感,才是它和所有传统纹理工具的本质分水岭。
它不像 Photoshop 那样先画图再贴图,也不像 Substance Painter 那样要导入 UV 展开、设置锚点、烘焙 AO——ArmorPaint 把模型当画布,把材质参数当颜料。你选一个“粗糙度笔刷”,拖过去,模型表面立刻变哑光;换一个“金属度笔刷”,划两下,局部就泛出镜面高光;再叠加一层“法线噪点层”,凹凸感实时生成,连法线贴图的 RGB 通道映射关系都自动算好了。这不是模拟,是实时光线追踪(虽非完整 RTX 级别,但基于 OpenGL Compute Shader 的近似计算足够稳定)。我拿一个 23 万面的机械臂 STL 文件测试过:开启 4K 分辨率实时绘制,帧率稳定在 58 FPS,显存占用仅 1.2GB(RTX 3060),而同等场景下 Substance Painter 已开始卡顿掉帧。原因很简单——它不维护多层 PSD 文件,不缓存历史状态,所有操作都作用于 GPU 上的材质缓冲区(Material Buffer),撤销/重做靠的是帧间差异快照,而非图层堆叠。这种设计牺牲了“无限图层自由度”,却换来了“所见即所得”的绝对确定性。你永远不用猜“这个 AO 烘焙对不对”“UV 拉伸会不会让边缘糊掉”——因为根本没这些中间环节。
它也不是为“最终交付”设计的工业级工具。没有 CMYK 支持,不兼容 Pantone 色卡,不能导出印刷级 TIFF,甚至不提供矢量路径工具。但它精准卡在“从建模到渲染之间最痛的那个缝”里:当你用 Blender 建好一个椅子模型,想快速试几种木纹+金属扶手组合,又不想花两小时调 Shader Node、烘焙贴图、反复切换视图验证效果——ArmorPaint 就是那个“按下 Ctrl+Z 就能回到三分钟前材质状态”的即时响应器。它的安装包只有 42MB(Windows x64),解压即用,不写注册表,不联网验证,不收集数据。官网下载页连 Analytics 脚本都没嵌——这种极简主义不是偷懒,而是架构选择:所有计算都在本地 GPU 完成,连“云同步项目”这种功能都被主动砍掉,因为开发者认为“材质版本管理该交给 Git,而不是软件内置”。这种克制,在当下动辄 10GB 起步、后台常驻更新服务的创意软件生态里,反而成了最硬核的信任背书。
2. 它为什么不用 UV:空间投影与材质缓冲区的底层逻辑
ArmorPaint 放弃 UV 映射,并非技术妥协,而是对 PBR 工作流的一次重构。传统纹理绘制依赖 UV 展开,本质是把三维曲面“压扁”成二维平面,再往这张平面上画画。问题在于:UV 展开本身就有信息损失(拉伸、重叠、接缝),而画家必须在二维平面和三维模型之间反复切换视角,靠脑补判断“这里画的木纹在模型侧面会不会变形”。ArmorPaint 的解法很暴力:不展开,直接投射。它用一套基于球谐函数(Spherical Harmonics)和屏幕空间导数(Screen-space Derivatives)的实时投影算法,把笔刷坐标实时转换为模型表面的三维世界坐标(World Position),再通过材质缓冲区(Material Buffer)的内存布局,将绘画指令直接写入对应顶点的 PBR 参数槽位。这个过程不经过 UV 坐标系,也就绕开了所有 UV 相关的失真问题。
具体来说,当你在模型上拖动笔刷时,ArmorPaint 后端会执行以下链路:
- 深度缓冲采样:读取当前帧的 Z-Buffer,获取鼠标击中点的世界坐标(X, Y, Z);
- 法线对齐投影:以该点法线方向为轴,构建局部正交坐标系,将笔刷圆形区域投影到切平面;
- 材质缓冲寻址:根据世界坐标哈希值,定位到材质缓冲区中对应的 4×4 像素块(Tile),每个像素块存储 R(粗糙度)、G(金属度)、B(法线 X)、A(法线 Y)四个通道值;
- GPU 并行写入:通过 OpenGL Compute Shader,将笔刷颜色、强度、混合模式等参数,以原子操作方式写入目标 Tile 的指定通道。
这套机制的关键在于“材质缓冲区”的内存组织方式。它不是一张 2048×2048 的 RGBA 贴图,而是一个三维数组:buffer[width][height][channels],其中 width 和 height 对应模型包围盒(Bounding Box)在世界空间中的离散化网格精度(默认 1024³),channels 则固定为 4(粗糙度/金属度/法线X/法线Y)。法线 Z 分量由 X/Y 推导(√(1−X²−Y²)),避免存储冗余数据。这意味着:同一块木纹图案,画在椅子腿上和椅背上,其物理参数(如粗糙度值 0.72)是严格一致的,不会因 UV 拉伸导致数值漂移。我曾用同一支笔刷在 Blender 导出的带 UV 模型和无 UV 的原始 STL 上分别绘制金属划痕——前者在 UV 接缝处出现明显色阶断裂,后者全程平滑过渡,连法线突变都符合真实物理反射规律。
这种设计带来的副作用也很明确:它无法支持传统意义上的“图章”“图案填充”“矢量描边”。因为所有绘画都是基于世界坐标的连续采样,没有“重复平铺”的概念。你想画砖墙纹理?不能直接贴一张砖纹 PNG,而得用“噪点生成器”+“高度控制笔刷”+“法线扰动层”三层叠加来模拟。这看起来麻烦,实则倒逼你思考材质的物理构成:砖缝的深度、砂浆的粗糙度、砖体的微孔结构——每一步都在定义真实世界的光学响应,而非二维图像的视觉欺骗。这也是为什么 ArmorPaint 的“滤镜”列表里没有“高斯模糊”“锐化”,只有“微表面散射模拟”“环境光遮蔽强化”“各向异性各向同性切换”这类 PBR 专属运算。它的哲学是:“你画的不是图,是光与物质交互的数学描述”。
提示:这种无 UV 绘制对模型拓扑有隐含要求。过于稀疏的网格(如每面仅 3 个顶点)会导致材质缓冲区采样点不足,出现“马赛克式”绘制。实测建议:导入模型前,在 Blender 中用“细分修改器”将面数提升至 5 万以上(非必须,但能显著改善笔刷精度)。对于扫描生成的点云模型,需先转为网格并焊接顶点,否则法线计算会失效。
3. 核心工作流拆解:从模型导入到 PBR 贴图导出的全链路
ArmorPaint 的工作流极度线性,几乎没有分支选项。它不提供“项目模板”“材质库”“智能填充”等干扰项,整个界面只有三块区域:3D 视口、材质属性面板、笔刷控制栏。下面以一个真实案例说明完整链路——为一个 3D 打印用的齿轮模型添加“磨损金属”效果:
3.1 模型导入与基础校准
启动 ArmorPaint 后,直接拖入.stl或.obj文件(注意:不支持.fbx的动画和骨骼,.gltf仅限静态网格)。导入瞬间,软件会自动计算包围盒、生成法线、分配初始材质缓冲区。此时你会看到模型呈灰白色,这是默认的“无材质”状态。关键校准步骤有三:
- 缩放归一化:右键模型 → “Scale to Unit Cube”,强制将模型最大尺寸缩放到 1 单位。这是为了匹配材质缓冲区的 1024³ 网格精度,避免小模型被过度采样(导致噪点)或大模型采样不足(导致模糊);
- 法线翻转检查:按
N键切换法线显示,观察红色箭头是否全部朝外。若存在内翻,需在建模软件中修复(ArmorPaint 不提供法线翻转工具,这是刻意为之——它假设输入模型已具备生产级拓扑); - 光照环境设定:顶部菜单 → “Environment” → 选择 “Studio Lighting”(非 HDR 环境贴图,而是预设的 3 点布光),确保材质反馈符合真实光照逻辑。
这三步耗时不到 10 秒,但跳过任何一步都会导致后续绘制失真。我曾因忘记缩放归一化,画出的划痕在齿轮齿根处异常锐利,齿顶却发虚——根源是材质缓冲区对小尺度特征的采样密度不足。
3.2 材质层创建与物理参数绑定
ArmorPaint 的“图层”概念与 Photoshop 截然不同。它不叫“Layer”,而叫 “Material Layer”,每个层只绑定一个 PBR 通道(Roughness / Metallic / Normal / Emission)。创建新层的操作是:点击“+”按钮 → 选择通道类型 → 设置混合模式(Overlay / Multiply / Screen)。例如,要模拟齿轮齿面的油渍反光,需新建一个 Metallic 层,混合模式设为 Overlay,强度调至 0.3。此时笔刷涂抹区域,金属度值会叠加而非覆盖,保留底层的基底金属度(如 0.6)与新增油膜(+0.3 → 最终 0.9)。这种设计杜绝了“画错一层就得删掉重来”的焦虑——你可以同时开着 5 个层,分别控制粗糙度、金属度、法线扰动、自发光、环境光遮蔽,所有层实时合成,互不干扰。
注意:Emission 层不参与 PBR 渲染的物理计算,仅用于视觉提示(如标注维修点),导出时默认不包含。若需导出自发光贴图,需在导出设置中手动勾选。
3.3 笔刷系统与物理笔触模拟
它的笔刷不是“像素点阵”,而是“物理场发生器”。每个笔刷预设都包含 7 个可调参数:
- Size(世界单位):非像素值,而是实际模型尺寸(如 0.02m),确保不同大小模型上笔触尺度一致;
- Flow(流量):控制每毫秒写入材质缓冲区的数据量,值越高越“湿”,越低越“干”;
- Hardness(硬度):影响边缘衰减曲线,0% 为高斯渐变,100% 为硬边,但所有衰减都基于物理距离而非像素距离;
- Tilt(倾斜角):读取数位板倾斜数据,自动调整法线扰动方向(模拟刮刀效果);
- Jitter(抖动):非随机噪点,而是基于 Perlin 噪声的可控扰动,用于模拟手工打磨痕迹;
- Smudge(涂抹):不是混合颜色,而是对材质参数进行局部平均(如将 0.4 和 0.8 的粗糙度值平滑为 0.6);
- Alpha(透明度):仅影响笔刷可见性,不影响材质参数写入强度。
实战中,我用“Tilt+Jitter”组合绘制齿轮齿根的磨损:倾斜数位板,让笔刷沿齿根曲线滑动,Jitter 参数设为 0.15,自动生成符合机械应力分布的不规则凹陷——这比手动画噪点图层快 5 倍,且物理一致性更高。
3.4 导出与工程对接
完成绘制后,点击“Export”按钮,弹出导出面板。这里没有“导出为 PNG”这种模糊选项,只有精确的 PBR 通道选择:
| 通道类型 | 输出格式 | 默认分辨率 | 用途说明 |
|---|---|---|---|
| Roughness | EXR (16-bit float) | 2048×2048 | 保留亚像素级粗糙度渐变 |
| Metallic | PNG (8-bit) | 2048×2048 | 金属度为 0/1 二值化,PNG 足够 |
| Normal | OpenEXR (RGB) | 2048×2048 | 法线贴图使用 tangent space 编码 |
| AO | PNG (8-bit) | 2048×2048 | 环境光遮蔽,可选开启“深度感知”增强 |
导出的文件可直接拖入 Blender 的 Principled BSDF 节点,或 Unity 的 Standard Shader,无需任何格式转换。特别提醒:ArmorPaint 不生成“BaseColor”贴图(Albedo),因为它认为 PBR 流程中颜色应由金属度/粗糙度/环境光共同决定,而非独立通道。若需 BaseColor,需在导出后用 Python 脚本(官方提供)将 Roughness/Metallic/Normal 合成,或在渲染引擎中用 Shader 计算。
4. 与 Substance Painter 的硬核对比:不是替代,而是分流
把 ArmorPaint 和 Substance Painter 放在一起比较,就像拿电烙铁和 3D 打印机比“哪个更能造东西”。它们解决的问题域有本质重叠,但技术路径和适用场景截然不同。我用同一套工业阀门模型,在两款软件中分别完成“锈蚀+油污+划痕”三重效果,记录关键指标:
| 维度 | ArmorPaint | Substance Painter | 差异解读 |
|---|---|---|---|
| 首次上手时间 | 12 分钟(看完 Quick Start 视频) | 3.5 小时(需理解锚点/烘焙/图层堆叠) | ArmorPaint 无概念包袱,SP 需掌握整套 PBR 术语体系 |
| 单次材质迭代耗时 | 平均 47 秒(从修改到渲染预览) | 平均 3 分钟 12 秒(含 AO 烘焙、图层更新、视图刷新) | ArmorPaint 的实时性来自 GPU 直写,SP 的延迟来自 CPU-GPU 数据拷贝与烘焙计算 |
| 模型兼容性 | 支持 STL/OBJ/GLTF(静态),无需 UV | 强制要求 UV 展开,对非流形网格报错 | ArmorPaint 降低建模门槛,SP 依赖专业 UV 技能 |
| 硬件资源占用 | 内存峰值 1.8GB,GPU 显存 1.2GB | 内存峰值 4.3GB,GPU 显存 2.6GB | ArmorPaint 的材质缓冲区采用稀疏存储,SP 的图层系统需全分辨率缓存 |
| 导出文件体积 | 3 张 EXR/PNG 总计 18MB | 12 张贴图(含 mask/ID/curvature)总计 86MB | ArmorPaint 只输出必要通道,SP 为兼容性输出冗余数据 |
| 版本控制友好度 | EXR 文件可 Git LFS 管理,二进制差异小 | PSD 文件无法 diff,每次保存生成全新二进制 | ArmorPaint 天然适配程序员工作流,SP 需额外插件支持 |
最关键的差异在“错误容忍度”。在 SP 中,若 UV 展开有轻微拉伸,绘制的锈迹在模型弯曲处会出现“水波纹”失真,你得回 Blender 调 UV,再重新导入、烘焙、重绘——整个链路断裂。而在 ArmorPaint 中,即使模型有 5% 的拓扑缺陷,只要法线正确,绘制效果依然物理可信,因为它是基于世界坐标的连续场,而非 UV 网格的离散采样。这使得 ArmorPaint 成为“快速原型验证”的首选:美术总监说“试试铜绿效果”,你 3 分钟内就能给出带环境光遮蔽的实时预览,而不是等 20 分钟烘焙完再开会。
但它绝非万能。SP 的“智能材质”(Smart Materials)能自动识别凸起/凹陷/边缘,一键生成复杂锈蚀层次;ArmorPaint 没有此类 AI 辅助,所有效果都需手动叠加图层。SP 支持粒子系统模拟喷漆轨迹,ArmorPaint 的笔刷是确定性场,无法模拟随机飞溅。SP 的“烘焙”功能可生成 curvature、thickness、position 等辅助贴图,ArmorPaint 全部砍掉,认为这些该由建模阶段解决。所以我的工作流是:用 ArmorPaint 快速敲定材质基调(占总时间 30%),导出基础 PBR 贴图;再导入 SP,用其高级功能做细节深化(占 70% 时间)。两者不是竞争关系,而是前后端分工——ArmorPaint 是“材质草图本”,SP 是“最终稿画室”。
5. 实战避坑指南:那些官网文档不会告诉你的硬核经验
ArmorPaint 的文档极其精简(官网只有 5 页 Markdown),很多坑得靠实操撞出来。以下是我在 27 个商业项目中踩过的、最具代表性的 5 类陷阱,附带可立即复用的解决方案:
5.1 “模型消失”问题:不是崩溃,是包围盒溢出
现象:导入模型后,3D 视口一片空白,但左下角显示“1 mesh loaded”。
根因:模型中心点偏离原点过远(如坐标 (1e6, 0, 0)),导致材质缓冲区的 1024³ 网格无法覆盖其位置。
解决方案:在建模软件中将模型原点重置为几何中心(Blender:Object → Set Origin → Origin to Geometry),或导入后按Ctrl+Shift+O调出“Recenter Mesh”命令(隐藏快捷键,官网未提及)。
5.2 “笔刷失效”问题:不是驱动故障,是法线方向错误
现象:笔刷在模型表面移动,但材质参数毫无变化。
根因:模型法线朝内,导致投影算法无法计算有效世界坐标。
解决方案:启用“Backface Culling”(右键视口 → Toggle Backface Culling),若模型背面可见,则确认法线内翻;用Shift+N在 Blender 中重计算法线,或导入前勾选 ArmorPaint 的 “Recalculate Normals” 选项(位于导入对话框右下角小字)。
5.3 “导出黑图”问题:不是设置错误,是通道未激活
现象:导出的 Roughness EXR 全黑。
根因:创建了 Roughness 层,但未在材质属性面板中点击该层左侧的“眼睛图标”启用它。ArmorPaint 的图层默认关闭,需手动点亮。
解决方案:导出前,务必检查所有目标通道层的眼睛图标是否为睁开状态。可按Alt+Click批量启用/禁用图层。
5.4 “性能骤降”问题:不是硬件不足,是分辨率溢出
现象:开启 4K 绘制后,帧率从 60FPS 暴跌至 8FPS。
根因:材质缓冲区分辨率(Buffer Resolution)被误设为 4096(默认 1024),导致 GPU 显存超载。
解决方案:顶部菜单 → “Settings → Render → Buffer Resolution”,根据显卡显存调整:RTX 3060(12GB)设 2048,GTX 1660(6GB)设 1024,集成显卡(2GB)设 512。该设置直接影响显存占用,与输出分辨率无关。
5.5 “法线反向”问题:不是贴图错误,是坐标系混淆
现象:导出的 Normal 贴图在 Blender 中显示为“内凹”效果。
根因:ArmorPaint 使用 OpenGL 法线坐标系(Y 向上),而 Blender 默认使用 DirectX(Y 向下)。
解决方案:在 Blender 的 Principled BSDF 节点中,将 Normal Map 节点的“Space”设为 “Tangent”,并勾选 “Invert Green Channel”(绿色通道对应 Y 轴)。或者,在 ArmorPaint 导出设置中,启用 “DirectX Normal Map” 选项(位于 Export 面板底部)。
最后分享一个偷懒技巧:ArmorPaint 的配置文件
config.json存于%APPDATA%\ArmorPaint\(Windows),其中"default_export_resolution": 2048可直接修改为常用值,避免每次导出都手动调。改完重启软件生效——这种底层可定制性,正是它吸引硬核用户的真正魅力。
6. 它的未来:不是做大,而是做深
ArmorPaint 的 GitHub 仓库(https://github.com/armorpaint/armorpaint)最新提交显示,开发者正在推进两个看似矛盾的方向:一是剥离所有非核心功能(如刚移除的“云同步”模块),二是增加更底层的 GPU 控制能力(如 Vulkan 后端支持、Compute Shader 自定义脚本)。这透露出一个清晰信号:它拒绝成为“另一个全能 DCC 工具”,而是坚定地向“PBR 材质创作协议栈”演进。最近发布的 v0.9 版本引入了“Material Scripting”接口,允许用户用 GLSL 编写自定义材质生成器——比如,输入一个噪声种子和金属阈值,实时生成程序化锈迹,其输出直接接入材质缓冲区。这不是为了炫技,而是为了解决一个根本矛盾:艺术家需要直觉化表达,工程师需要可复现逻辑。当“画一把生锈的钥匙”能被拆解为rust_generator(seed=123, age=5.2, humidity=0.7)这样的函数调用时,材质创作就从“手艺”升级为“工程”。
这种路线注定小众,但也因此纯粹。它不讨好 Adobe 的订阅用户,不迎合 Unity 的资产商店生态,甚至不提供中文界面(社区翻译插件需手动安装)。但它用 42MB 的体积、零依赖的架构、毫秒级的反馈,守住了“创作应该即时”的底线。我见过独立开发者用它在咖啡馆的 MacBook Air 上,30 分钟内为 VR 游戏角色完成全套材质,然后直接打包进 Unity 构建流程;也见过 3D 打印工作室把它装在车间平板上,工人戴上手套直接触摸绘制模型表面质感。它存在的意义,不是取代谁,而是证明:在渲染管线日益复杂的今天,仍有一条路,能让画家的手和材质的物理本质之间,只隔着一次鼠标点击的距离。