1. 为什么我要自己编译 ArmorPaint 而不是直接下安装包
ArmorPaint 这个开源 3D 纹理绘制工具,玩独立游戏或者做手办渲染的朋友应该不陌生。它最大的卖点就是轻量、GPU 加速、支持 PBR 材质实时预览,而且能在 Windows、Linux、macOS 上跑。官方渠道其实提供了付费的预编译版本,但源码本身是开源的,这就给了我们一个选择:自己从源码编译。
我最初动这个念头,是因为官方发布的二进制包在我的工作机上总是出现显卡驱动兼容问题——打开就黑屏,或者笔刷延迟高得离谱。后来发现,官方构建用的图形后端和我的硬件组合不太对付,而自己编译时可以选择不同的渲染后端和编译选项,相当于给软件做了一次“量身定制”。另外,团队里几个美术同事用的机器配置参差不齐,统一分发一个自己编译的版本,能省掉很多“你装这个驱动、他改那个设置”的沟通成本。
这篇文章就是把我前前后后编译了七八次、踩了无数坑之后,整理出来的一份完整记录。我会从环境准备讲起,把每个关键步骤背后的原因说清楚,再分享几个只有实际动手才会遇到的坑。如果你也受够了官方包的各种小毛病,或者单纯想体验一下从源码构建的乐趣,这篇内容应该能帮你省下不少时间。
需要提前说明的是,ArmorPaint 的编译流程在不同操作系统上差异挺大,我主要是在 Windows 和 Linux 两个平台上反复折腾,所以下面的内容会以这两个平台为主。macOS 的流程类似 Linux,但有一些额外的依赖处理,我会在对应章节里提一下。
2. 编译前的环境准备:别急着敲命令
2.1 硬件与驱动的隐性门槛
ArmorPaint 的核心是 GPU 渲染,所以显卡驱动的重要性怎么强调都不为过。我遇到过最诡异的一个问题:编译过程一切顺利,但运行起来画面全是马赛克。排查了半天,最后发现是显卡驱动版本太老,不支持某个 Vulkan 扩展。所以第一步,先确认你的显卡驱动是较新的版本。
对于 NVIDIA 用户,建议去官网下载最新的 Studio 驱动或者 Game Ready 驱动,两者在 ArmorPaint 里表现差不多,但 Studio 驱动在长时间绘制时稳定性更好一些。AMD 用户要注意,开源驱动和闭源驱动的表现差异很大,Linux 下建议用较新的 Mesa 版本。Intel 核显用户也不是不能用,但显存共享主内存,绘制大尺寸纹理时会比较吃力,编译时可以考虑关闭一些高级特性来换取流畅度。
内存方面,官方建议 8GB 起步,但我实测下来,如果要处理 4K 纹理,16GB 是底线。编译过程本身倒是不怎么吃内存,但链接阶段如果内存不足,会报一些莫名其妙的错误,很容易误导排查方向。
2.2 编译工具链的版本选择
ArmorPaint 是用 Haxe 语言写的,通过 Kha 框架跨平台编译。所以你需要的不只是 C++ 编译器,还要有 Haxe 工具链和 Kha 的依赖。
Haxe 的版本选择有个小坑:不是越新越好。我试过用最新的 Haxe 5.x 编译,结果 Kha 框架的某些宏展开报错。后来退回到 Haxe 4.3.x 系列,一切正常。所以建议锁定 Haxe 4.3.3 这个版本,它是目前和 ArmorPaint 兼容性最好的。
Kha 框架本身也需要从源码获取,因为 ArmorPaint 依赖了一些 Kha 的特定提交。直接克隆 Kha 的仓库,然后切换到 ArmorPaint 的 git 子模块指定的那个 commit,这是最稳妥的做法。如果你直接用 Kha 的最新主分支,大概率会遇到 API 不匹配的问题。
在 Windows 上,你还需要 Visual Studio 的 C++ 构建工具。注意不是完整的 Visual Studio IDE,而是 Build Tools 就够了。安装时勾选“使用 C++ 的桌面开发”工作负载,确保 MSVC 编译器和 Windows SDK 都装上。我建议用 Visual Studio 2022 的 Build Tools,版本太老可能不支持某些 C++17 特性。
Linux 下相对简单,gcc 或者 clang 都可以,但要注意 gcc 版本不要低于 9,否则某些 C++17 的文件系统库会缺失。另外需要安装一些开发库:libx11-dev、libxrandr-dev、libxi-dev、libxcursor-dev、libgl1-mesa-dev、libasound2-dev 等等。这些在 Ubuntu 上可以用一条 apt 命令搞定,后面我会给出具体命令。
2.3 获取正确的源码版本
ArmorPaint 的源码在 GitHub 上,但直接克隆主分支不一定能编译通过,因为开发分支可能处于中间状态。我的经验是,去 releases 页面找最新的稳定 tag,或者用 git submodule 的方式把 Kha 和 ArmorPaint 一起拉下来。
具体操作是这样的:先克隆 ArmorPaint 仓库,然后执行git submodule update --init --recursive,这样会把 Kha 和其他子模块都拉到正确的版本。如果你只克隆了 ArmorPaint 而忘了子模块,编译时会报找不到 Kha 的头文件。
还有一个细节:ArmorPaint 的某些版本依赖特定的 Kha 提交,而这个提交可能不在 Kha 的主分支上。所以千万不要手动去克隆 Kha 的最新代码替换子模块,那样会引入不兼容的变更。老老实实用子模块机制,让 git 帮你管理版本对应关系。
3. Windows 平台编译全流程:从零到可执行文件
3.1 安装 Haxe 与 Haxelib 的注意事项
在 Windows 上安装 Haxe,最简单的方法是去官网下载安装包。安装完成后,记得把 Haxe 的安装目录加到系统 PATH 环境变量里,否则命令行里敲haxe会提示找不到命令。
安装完 Haxe 后,还需要安装 haxelib(Haxe 的包管理器)。通常安装包会自带,但有时候需要手动初始化。打开命令行,执行haxelib setup,它会让你指定一个库存储目录,默认在用户目录下的 haxelib 文件夹,直接回车确认就行。
接下来安装 ArmorPaint 需要的 Haxe 库。在项目根目录下通常会有一个khafile.js或者类似的配置文件,里面列出了依赖。但更直接的方法是看 ArmorPaint 的 README 或者haxelib.json。常见的依赖包括:kha、hxbit、armory 等。你可以用haxelib install <库名>逐个安装,但更推荐用haxelib git <库名> <仓库地址> <分支或提交>的方式来安装 Kha,因为需要特定版本。
这里有个坑:haxelib 的全局库目录可能会因为权限问题导致安装失败。如果你在 Windows 上遇到“Access denied”之类的错误,试着用管理员身份运行命令行,或者把 haxelib 的库目录设置到用户目录下。
3.2 配置 Kha 的编译目标
Kha 框架支持多种编译目标:C++(原生)、HTML5、Krom(GPU 后端)等。ArmorPaint 主要用的是 Krom 后端,这是一个基于 Vulkan 或 Direct3D 的渲染后端。所以在编译时,我们需要指定目标为krom。
在 ArmorPaint 的目录下,通常会有一个make.bat或者make.js脚本。运行node make.js或者直接执行对应的批处理文件,Kha 会开始编译。但在这之前,你需要确保 Kha 的Kha工具已经正确配置。Kha 目录下有一个Kha可执行文件(Windows 上是Kha.exe),它是编译的入口。
我建议先进入 Kha 目录,执行Kha.exe看看有没有输出帮助信息,确认工具本身能跑。然后回到 ArmorPaint 目录,执行..\Kha\Kha.exe krom或者类似的命令。具体的命令取决于你的目录结构,关键是让 Kha 知道要编译哪个项目、用什么后端。
3.3 解决 MSVC 编译中的常见报错
Windows 上最容易出问题的地方是 MSVC 的编译环境。Kha 在编译 C++ 代码时,会调用cl.exe。如果你是在普通的命令行里运行,而不是在“Developer Command Prompt for VS”里,可能会找不到cl.exe。解决办法是手动把 MSVC 的 bin 目录加到 PATH,或者直接用 VS 的开发人员命令行。
另一个常见报错是 Windows SDK 版本不匹配。Kha 生成的 C++ 代码可能依赖某个特定版本的 SDK,如果你的系统装了多个版本,编译时可能会链接到错误的库。可以在项目配置里显式指定 SDK 版本,或者干脆只保留一个版本的 SDK。
还有一个比较隐蔽的问题:路径中有空格或中文。Kha 和 Haxe 在处理路径时,对空格和特殊字符的支持不太好。所以强烈建议把项目放在一个纯英文、无空格的路径下,比如D:\dev\ArmorPaint。我一开始放在D:\我的项目\ArmorPaint下,结果编译脚本各种报错,换成纯英文路径后立刻就好了。
3.4 编译产物的结构与运行测试
编译成功后,你会在build目录下找到生成的可执行文件。Windows 上通常是ArmorPaint.exe或者Krom.exe加上一些资源文件。注意,这个可执行文件不能单独拿出来运行,它依赖同目录下的data文件夹和kha相关的动态库。
第一次运行前,建议先检查一下显卡驱动是否支持 Vulkan。你可以用 GPU-Z 或者 Vulkan Caps Viewer 这类工具查看。如果 Vulkan 不可用,可以尝试切换到 Direct3D 后端,但需要在编译时指定不同的参数。
运行起来后,先别急着画图。打开一个简单的示例场景,测试一下笔刷、图层、材质预览这些基本功能是否正常。如果发现画面撕裂或者笔刷延迟,可能是垂直同步或者 GPU 优先级的问题,可以在设置里调整。
4. Linux 平台编译:依赖管理与权限处理
4.1 发行版差异与依赖安装
Linux 下编译 ArmorPaint,最大的挑战是依赖管理。不同的发行版包名不一样,但核心依赖是类似的。以 Ubuntu 22.04 为例,你需要安装以下开发包:
sudo apt update sudo apt install build-essential git nodejs npm sudo apt install libx11-dev libxrandr-dev libxi-dev libxcursor-dev sudo apt install libgl1-mesa-dev libasound2-dev libpulse-dev sudo apt install libvulkan-dev vulkan-tools这些包分别对应窗口系统、OpenGL、音频和 Vulkan 支持。如果你用的是 Fedora,包名会变成libX11-devel、mesa-libGL-devel之类的,用 dnf 安装即可。Arch 用户通常只需要装base-devel和对应的 lib 包。
Haxe 在 Linux 下可以通过包管理器安装,但版本可能比较老。我建议去 Haxe 官网下载二进制包,解压后把路径加到 PATH。haxelib 的安装和 Windows 类似,haxelib setup然后安装依赖。
4.2 编译脚本的权限与路径问题
Linux 下编译时,Kha 生成的Kha可执行文件需要有执行权限。如果你是从 Windows 拷贝过来的项目,或者用 git clone 后没有保留权限,可能会遇到“Permission denied”。解决办法很简单:chmod +x Kha。
另一个问题是文件路径的大小写敏感。Windows 下不区分大小写,但 Linux 区分。如果源码里某个#include "Kha.h"写成了#include "kha.h",在 Windows 上能过,在 Linux 上就会报找不到文件。这种情况在第三方库中偶尔会出现,需要手动修正。
还有,Linux 下默认的临时目录是/tmp,如果编译过程中产生的临时文件太大,可能会占满/tmp分区。可以设置TMPDIR环境变量指向一个有足够空间的分区。
4.3 音频与输入设备的后端选择
ArmorPaint 在 Linux 下默认使用 ALSA 或 PulseAudio 作为音频后端。如果你的系统没有正确配置音频,编译时可能会报链接错误。确保libasound2-dev和libpulse-dev都装好了。
输入设备方面,数位板用户需要注意:Linux 下数位板支持依赖libxinput和相关的驱动。编译时确保libxi-dev已安装。如果数位板压感不正常,可能需要额外配置 Xorg 的输入设备,这部分和 ArmorPaint 本身无关,但会影响使用体验。
4.4 打包与分发时的动态库处理
编译完成后,Linux 下的可执行文件通常依赖系统里的动态库。如果你想分发给其他人,需要把依赖的.so文件一起打包,或者用patchelf修改 rpath。我一般用ldd查看依赖,然后把非系统级的库复制到lib目录下,再用启动脚本设置LD_LIBRARY_PATH。
对于团队内部使用,我写了一个简单的启动脚本,自动设置环境变量并启动 ArmorPaint。这样美术同事只需要解压压缩包,双击脚本就能用,不用关心底层的库依赖。
5. 编译过程中最容易踩的五个坑
5.1 子模块版本错乱导致的链接错误
这个坑我踩了两次。第一次是手动克隆了 Kha 的最新代码,结果 ArmorPaint 编译时找不到某个函数。第二次是子模块更新后没有重新初始化,导致 Kha 的版本和 ArmorPaint 期望的不一致。
正确的做法是:每次切换 ArmorPaint 的分支或 tag 后,都执行一次git submodule update --init --recursive。如果子模块的远程地址变了,可能还需要git submodule sync。编译前用git submodule status确认所有子模块的 commit 和主项目记录的一致。
5.2 Haxe 库路径冲突与版本覆盖
Haxe 的库管理有个特点:全局库目录下同一个库只能有一个版本。如果你之前装过 Kha 的其他版本,再安装 ArmorPaint 需要的版本时,可能会提示冲突。这时候要么卸载旧版本,要么用haxelib dev把库指向本地目录。
我推荐的做法是:为 ArmorPaint 单独创建一个 haxelib 库目录,通过haxelib setup切换过去。这样不同项目的依赖互不干扰。虽然麻烦一点,但能避免很多版本冲突问题。
5.3 显卡驱动与渲染后端的匹配问题
前面提过驱动太老会导致画面异常,但还有一种情况:驱动太新,而 ArmorPaint 使用的 Vulkan 版本较旧,也可能出问题。比如某些新驱动默认启用了 Vulkan 1.3 的特性,而 ArmorPaint 只请求了 1.1 的上下文,导致初始化失败。
解决办法是在编译时指定 Vulkan 版本,或者在运行时通过环境变量强制使用兼容模式。具体参数可以在 Kha 的文档里找到。如果实在搞不定,可以尝试切换到 OpenGL 后端,虽然性能差一些,但兼容性更好。
5.4 内存不足导致的编译中断
编译 ArmorPaint 的 C++ 代码时,链接阶段非常吃内存。我有一次在 8GB 内存的虚拟机上编译,链接到一半就报“out of memory”。后来把虚拟内存调大,或者关闭其他占内存的程序,才顺利通过。
如果你经常需要编译,建议至少 16GB 物理内存。如果内存实在不够,可以尝试分步编译,或者用-j1参数限制并行编译的任务数,减少峰值内存占用。
5.5 杀毒软件误报与文件锁定
Windows 上,某些杀毒软件会把 Kha 生成的可执行文件误判为威胁,直接隔离或删除。我遇到过编译成功后ArmorPaint.exe突然消失的情况,查了半天才发现是杀毒软件干的。解决办法是把项目目录加到杀毒软件的排除列表里。
另外,如果编译过程中杀毒软件正在扫描生成的文件,可能会导致文件被锁定,编译报“无法写入”的错误。临时关闭实时保护,或者把编译目录排除,能避免这类问题。
6. 编译完成后的优化与定制化调整
6.1 调整编译参数提升运行性能
自己编译的最大好处就是可以针对自己的硬件优化。Kha 的编译配置里有一些参数可以调整,比如是否启用 LTO(链接时优化)、是否使用特定的 SIMD 指令集、纹理压缩格式等。
对于 NVIDIA 显卡,可以尝试启用-flto和-march=native,让编译器生成更适合当前 CPU 的代码。但要注意,-march=native编译出来的二进制不能在其他 CPU 上运行,所以只适合自己用。如果要做团队分发,还是用通用的指令集。
纹理压缩方面,ArmorPaint 支持多种格式。如果你的显卡支持 BC7 压缩,可以在编译时启用,能显著减少显存占用。但这个选项默认可能是关闭的,需要手动在 Kha 的配置里打开。
6.2 裁剪不需要的功能模块
ArmorPaint 包含了一些实验性功能,比如 VR 模式、插件系统等。如果你用不到这些,可以在编译时禁用,减小二进制体积,也能减少潜在的兼容性问题。
具体做法是修改khafile.js里的条件编译标志,把不需要的模块排除掉。但要注意,有些模块之间有依赖关系,禁用了一个可能导致另一个也失效。建议每次只禁用一个,编译测试通过后再继续。
6.3 自定义启动画面与默认配置
如果你要分发给团队使用,可以定制启动画面和默认配置。ArmorPaint 的启动画面是一张图片,替换掉data目录下的对应文件就行。默认配置可以在源码里修改,比如默认笔刷大小、默认颜色空间等。
我一般会预设好团队常用的笔刷和材质库,这样美术同事打开就能直接干活,不用再花时间配置。这些定制化内容在官方安装包里是固定的,但自己编译就能随意调整。
6.4 版本管理与回滚策略
自己编译的版本也需要版本管理。我建议每次编译成功后,把可执行文件和资源打包,用日期或 commit hash 命名,存档保留。这样如果新版本出了问题,可以快速回滚到旧版本。
同时,记录每次编译的配置和依赖版本。我习惯在项目根目录放一个BUILD_NOTES.md,里面写清楚这次编译用了哪个 Haxe 版本、哪个 Kha 提交、修改了哪些编译参数。下次再编译时,照着笔记操作,能避免很多重复排查。
7. 关于分发与协作的一些实际经验
编译好的 ArmorPaint 分发给同事时,最常遇到的问题不是软件本身,而是运行环境差异。有的同事显卡驱动旧,有的缺少 VC++ 运行库,有的系统区域设置导致路径乱码。我的做法是写一个简单的检测脚本,在启动前检查关键依赖,如果缺失就弹出提示,告诉用户去装什么。
对于 Windows 分发,我把所有依赖打包成一个自解压压缩包,里面包含 VC++ 运行库的安装程序。用户解压后运行install.bat,脚本会自动检测并安装缺失的运行库,然后创建桌面快捷方式。这样即使是不太懂电脑的美术同事,也能顺利装上。
Linux 分发相对麻烦一些,因为不同发行版的库版本差异大。我通常只针对团队使用的统一发行版编译,如果个别同事用其他发行版,就让他们自己编译或者用容器运行。容器方案虽然重一些,但能保证环境一致,适合对稳定性要求高的场景。
还有一点:自己编译的版本不要随意公开分发,因为可能包含未测试的代码或者不符合某些许可证的依赖。团队内部使用没问题,但对外发布还是建议用官方渠道的版本,或者至少做好充分的测试和合规检查。
8. 我个人的一些使用体会
从第一次编译失败到后来能稳定产出可用的二进制包,我大概花了两周左右的业余时间。最大的感受是:编译开源项目,耐心和记录比技术本身更重要。很多问题不是不会解决,而是忘了上次是怎么解决的,又得重新排查一遍。
现在我的做法是,每次编译都写一份简短的记录,包括遇到的报错、尝试过的方案、最终有效的解决办法。这些记录积累下来,就成了团队内部的一份“编译手册”。新同事遇到类似问题,直接查手册就能解决,不用再来问我。
另外,自己编译并不意味着要抛弃官方版本。我通常会把官方版本作为备用,自己编译的版本作为主力。如果自己编译的版本出了奇怪的问题,可以快速切换到官方版本对比,判断是代码问题还是环境问题。这种“双版本”策略,在实际工作中帮我省了不少时间。
最后说一个细节:ArmorPaint 的源码更新挺频繁的,但并不是每次更新都值得重新编译。我一般只关注那些修复了关键 bug 或者增加了实用功能的提交。如果只是文档更新或者代码风格调整,就没必要折腾了。毕竟编译一次少则十几分钟,多则半小时,时间成本还是要考虑的。