内容
<h1 align="center">文本转3D技能</h1>
<p align="center">
<strong>输入一句话,获得一个可用的GLB模型,配备骨骼和动画,全部在您自己的AMD APU上生成,无需云服务和ROCm。</strong>
</p>
<p align="center">
<img src="https://img.shields.io/badge/GPU-Vulkan_(RADV)-A41E22" alt="Vulkan" />
<img src="https://img.shields.io/badge/AMD-Strix_Halo_gfx1151-ED1C24?logo=amd&logoColor=white" alt="Strix Halo" />
<img src="https://img.shields.io/badge/Base-Ubuntu_26.04-E95420?logo=ubuntu&logoColor=white" alt="Ubuntu 26.04" />
<img src="https://img.shields.io/badge/Output-glTF_2.0_binary-87B441" alt="GLB" />
<img src="https://img.shields.io/badge/License-MIT-blue" alt="MIT" />
</p>
---
## 这是什么
当您正在搭建一个关卡,需要一个桶、一个板条箱和一个市场摊位时,您不必在资源商店中搜索或自己建模。相反,您可以运行三个提示,几分钟后获得三个带有纹理的GLB模型,并将它们放入three.js或Godot中,根据您的预算调整多边形数量。
```
"一顶黄铜古董潜水头盔"
-> FLUX.2 klein 4B, ComfyUI, ROCm -> 1024x1024 PNG
-> TRELLIS.2 4B, 我们的Vulkan容器 -> 带纹理的GLB
```
两个阶段,因为TRELLIS.2是一个图像转3D模型,而不是文本转3D模型。图像阶段在ComfyUI堆栈上运行,该堆栈已经存在于此框中;3D阶段在一个容器中运行,该容器由本仓库构建。
第三个可选阶段为结果配备骨骼:一个测量的骨架,骨骼热皮肤和一个行走循环,以便生成的角色可以直接移动。
## 为什么3D部分使用Vulkan
Strix Halo没有针对每个工作负载的官方平滑ROCm故事,而3D引擎不需要它。`trellis.cpp`已经有一个Vulkan后端,因此网格部分在Mesa RADV下运行,对 `/dev/dri` 使用,没有 `/dev/kfd`,没有ROCm库,也没有 `--privileged`。容器大小为804 MB,启动时间不到一秒。
这里的引擎是 `trellis.cpp`,修剪到那一条路径。207 MB的上游检查变成了1.8 MB的源代码和 `src/` 目录下的22个文件:CUDA和HIP内核、15个PyTorch比较测试二进制文件、Tauri桌面应用程序、安全张量转换器和115 MB的展示渲染被删除。构建如果缺少 `ggml-vulkan` 会大声失败,而不是静默生成CPU二进制文件。如果没有它,构建会失败。删除的内容和原因:[`layers/image2mesh/engine/PROVENANCE.md`](layers/image2mesh/engine/PROVENANCE.md)。顶部更改的内容和测量:[`layers/image2mesh/CHANGES.md`](layers/image2mesh/CHANGES.md)。
## 先决条件
- AMD Strix Halo(Ryzen AI Max+,gfx1151)上的最新amdgpu内核。其他Vulkan GPU也应该有效;但只有这一个经过测试。
- Docker和Compose。
- [comfyui-strix-docker](https://github.com/hec-ovi/comfyui-strix-docker)正在运行,FLUX.2 klein权重在其模型下安装:`flux-2-klein-4b.safetensors`,`qwen_3_4b.safetensors`,`flux2-vae.safetensors`。
- 20 GB用于TRELLIS.2 GGUFs的磁盘空间,以及用于驱动程序的Python 3.10+(仅标准库,无pip安装)。
- 如果您想要骨骼绑定,请使用Blender 5.x。可以在PATH中的任何位置,或通过 `$BLENDER` 指向。仓库中的其他内容不需要它。
## 作为技能安装
```
/plugin marketplace add hec-ovi/text-to-3D-skill
/plugin install text-to-3d@text-to-3d-skill
/reload-plugins
```
或者克隆它,如果您要运行管道而不是仅读取技能:
```bash
git clone https://github.com/hec-ovi/text-to-3D-skill ~/.claude/skills/text-to-3d
```
插件路由仅安装 [`SKILL.md`](SKILL.md):一个能力表,带有ids(`generate`、`lowpoly`、`rig`、`preview`、`mcp`、`batch`),智能代理读取后决定运行什么。代码、权重和容器来自克隆。
要从另一个MCP客户端驱动它,[`.mcp.json`](.mcp.json)注册了此仓库附带的stdio服务器:
```json
{ "mcpServers": { "text-to-3d": { "command": "python3",
"args": ["layers/mcp/src/server.py", "--out-dir", "out"], "timeout": 900000 } } }
```
六种工具,每种工具返回一个id、一个路径和一个预览URL,而不是字节:`generate_model`、`generate_image`、`rig_model`、`list_models`、`get_preview`、`download_glb`。为什么从不使用字节,以及为什么没有SDK:[`layers/mcp/README.md`](layers/mcp/README.md)。
## 设置
```bash
# 1. 权重(~16 GiB磁盘空间,每个文件都针对HF API校验)
./scripts/fetch-models.sh
# 2. Vulkan引擎镜像
cd layers/image2mesh && docker build -f docker/Dockerfile -t text-to-3d/engine:vulkan . && cd ../..
# 3. 图像后端
cd ../comfyui-strix-docker && docker compose up -d && cd -
```
`fetch-models.sh`是可恢复和可重新运行的:完整的文件被跳过,部分文件继续运行,任何校验失败的文件都会被重新获取。 `--verify-only`检查磁盘上存在的内容,而不下载。
## 使用它
```bash
python3 layers/pipeline/src/pipeline.py --prompt "一顶黄铜古董潜水头盔" --out-dir out
```
打印一个JSON信封,包含GLB路径、其sha256、三角形计数和每个阶段的计时。 `--glb-path-only`仅打印路径。
```js
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
new GLTFLoader().load('/models/asset.glb', (gltf) => scene.add(gltf.scene))
```
纹理通过 `EXT_texture_webp` 以WebP形式存储在GLB中。如果需要PNG,可以使用 `-DT2M_WEBP=OFF` 重建。
在会话中生成多个资产?启动常驻服务器一次并传递 `--runner server`,这样模型加载在启动时支付,而不是每次调用。命令在 [`SKILL.md`](SKILL.md) 中。
## 搜索后再生成
生成需要几分钟;获取现有模型需要几秒钟。 `layers/assets` 搜索Poly Haven,这是一个有几百个模型的站点,所有模型都是CC0,无需密钥和账户,并将选择的模型转换为同一文件夹中的单个GLB:
```bash
python3 layers/assets/src/assets.py search --query "chair wood" --limit 5
python3 layers/assets/src/assets.py fetch --id painted_wooden_chair_01 --out-dir out
```
促使这个站点的是threejsassets.com,它没有API,也不允许在条款中自动访问,因此无法连接。为什么选择Poly Haven以及替代方案的许可成本: [`layers/assets/README.md`](layers/assets/README.md)。
## 低多边形,使其移动
> **移动是实验性的。** 骨骼、蒙皮和四个剪辑是真实的,文件是一个有效的绑定glTF,但生成的角色不能干净地动画。两个已知原因,两个都是测量过的而不是猜测的,在下面写出。把绑定当作一个起点,你在Blender中打开,而不是作为一个完成的资产。静态网格不是实验性的。
`--target-faces N` 设置二次简化目标。在512分辨率下,默认值为150K面;请求4000面可得到3810个三角形、304 KB的GLB,并在相同时间内添加纹理,因为压缩发生在UV展开和纹理烘焙到简化网格之前。
```bash
python3 layers/pipeline/src/pipeline.py --prompt "一个维京战士" --target-faces 6000 --out-dir out
python3 layers/rig/src/rig.py --glb out/<asset>.glb --subject humanoid --out-dir out
```
第二个命令为一个人类oid提供了19个Mixamo命名的骨骼,通过测量网格拟合骨骼热蒙皮权重,以及GLB中的 `idle` 、 `walk` 、 `run` 和 `jump` 剪辑。它在上面的5957面战士上耗时1.1秒。道具则完全没有骨架: `--subject prop` 在节点上放置TRS剪辑, `--socket <name>` 添加一个命名附件空节点,这是游戏引擎实际需要的。
简化后再绑定,而不是之前:简化蒙皮网格会丢弃权重。为什么骨架是测量的,而不是由神经绑定器预测的,以及为什么剪辑是作者而不是下载的,请参见 [`layers/rig/README.md`](layers/rig/README.md)。
### 有什么问题,具体来说
**烘焙光照跟随动画。** TRELLIS将参考图像的着色烘焙到基准颜色中,因此折痕阴影和裤腿上的高光是纹理上的像素,而不是照明。静止时看起来不错。腿摆动时,烘焙到大腿上的阴影仍然停留在大腿上,而大腿移动到光线下,结果看起来像网格撕裂了。它没有:几何体是完整的,验证是有效的,相同的带在未绑定的网格上是可见的。杠杆是图像阶段:一个角色在平坦、均匀的光线下请求,会少烘焙一些阴影,代价是重建器用来推断额头、鼻子和脸颊浮雕的阴影梯度。尚未做出此权衡。
**穿着衣服的人物会隐藏自己的手臂。** 在生成的角色中 `out/`,两个手臂返回 `LIMB_NOT_MEASURED`,肩线返回 `SHOULDERS_NOT_FOUND`:商务套装的肩膀与躯干轮廓融合,因此网格的水平带永远不会分成一个带有两侧手臂的躯干。骨骼随后来自模板而不是人物,骨骼热绑定顶点绑定到骨骼上,但骨骼并不完全位于肢体上。
这两个问题都不是Blender问题。Blender会执行所要求的操作;所要求的操作基于丢失的网格信息。
结果带有 `poseWarnings`,因为永久保存网格的姿势成为静止姿势,每个剪辑都在其基础上播放,因此一个中途跨步的人物四肢瘸行。运行 `out/` 中已有的角色,检查发现一个脚间距为其身高36%的角色,两个手臂从未与躯干分离,大多数角色都有弯曲的肢体。这是一个警告而不是错误,因为绑定无法修复姿势,文件和注释优于拒绝。
## 看看它
```bash
python3 layers/preview/src/serve.py --dir out --open
```
`http://127.0.0.1:8190`有两个布局在一个列表上。 **画廊** 是一个网格,每个GLB在浏览器中以512px渲染。 **单个** 将列表放在左侧,所选模型放在旋转台上,图片在第二个标签页后面。按名称过滤,按箭头键浏览,按滚轮缩放,翻转到线框。
两个布局都通过同一个工作室渲染:一个天空穹顶和三个软盒烘焙到环境地图,一个三点绑定,关键点位于相机45度偏移处,以便阴影落下可以看到它们,屏幕空间环境遮蔽,一个窄光晕和Khronos PBR中性色调遮蔽。遮蔽部分很重要,因为TRELLIS没有烘焙任何遮蔽到图集,因此如果没有它,每个凹槽、眼窝和面板间隙都被照亮得和旁边表面一样亮,形状就变平。
卡片艺术是GLB,而不是它来自的PNG。使用源图像很容易,但不诚实:它是FLUX绘制的,而网格列表会使重建的模型看起来很逊。
three.js是分发的,因此页面无需联网或构建步骤即可运行。每个模型都有一个稳定的ID,因此 `?id=<id>` 链接到一个资产, `GET /api/models?id=<id>` 从脚本中解析它。 `?model=<文件名>` 仍然有效。
## 性能
在gfx1151盒上,从1024x1024图像到512分辨率的带纹理GLB,输入和种子相同:
| | 固定上游(Vulkan) | 此仓库 |
| --- | --- | --- |
| 引擎时间 | 224.3 秒 | **191.7 秒** |
| 三角形 | 138524 | 138520 |
| 峰值GTT | 3612 MiB | 3616 MiB |
差异的32.6秒全部来自一个地方。配置文件显示,GLB写入阶段占了27%,任何流程阶段都比不上它,而其中62%的简化是单线程的 `unordered_map` 构建边列表,成本是GPU内核的两倍。 CSR邻接关系已经在更早的一行构建完成,因此每个顶点现在并行发出自己的边:1647毫秒变为24毫秒。完整方法、数字和未帮助的更改在 [`layers/image2mesh/CHANGES.md`](layers/image2mesh/CHANGES.md)。
输出的GLB通过Khronos glTF-Validator,0个错误,0个警告( `scripts/validate-glb.mjs` )。
## 布局
七个黑盒。每个拥有一个文件夹,声明一个契约,并独立更改。 [`docs/INDEX.md`](docs/INDEX.md) 将“您要更改的内容”映射到要打开的文件夹。
| 层 | 拥有 | 契约 |
| --- | --- | --- |
| [`layers/text2image`](layers/text2image) | 提示框架、ComfyUI图、klein权重 | [CONTRACT.md](layers/text2image/CONTRACT.md) |
| [`layers/image2mesh`](layers/image2mesh) | Vulkan引擎、容器、GLB验证 | [CONTRACT.md](layers/image2mesh/CONTRACT.md) |
| [`layers/pipeline`](layers/pipeline) | 阶段顺序、错误包装 | [CONTRACT.md](layers/pipeline/CONTRACT.md) |
| [`layers/rig`](layers/rig) | 骨骼、蒙皮、剪辑集、道具插槽 | [CONTRACT.md](layers/rig/CONTRACT.md) |
| [`layers/preview`](layers/preview) | three.js旋转台和其背后的服务器 | [CONTRACT.md](layers/preview/CONTRACT.md) |
| [`layers/assets`](layers/assets) | 搜索和获取库存CC0模型 | [CONTRACT.md](layers/assets/CONTRACT.md) |
| [`layers/mcp`](layers/mcp) | MCP工具表面stdio | [CONTRACT.md](layers/mcp/CONTRACT.md) |
边界上的每个内容都是模式验证的JSON信封,二进制有效载体通过引用路径、媒体类型、字节大小和sha256进行交叉。网格层重新哈希它收到的PNG,因此不匹配的失败运行而不是静默重建错误的图片。
## 测试
```bash
./scripts/test.sh # 七个层,226个测试,以及技能检查
```
无需GPU和权重:测试仅针对ComfyUI、引擎二进制文件和Blender,并驱动其他一切的真实CLI,包括五个错误GLB形状,从不带成功信封的网格层中脱出。需要GPU的测试除非 `T2M_RUN_GPU=1`,而rig层的五个真实Blender测试如果没有安装Blender,则会跳过并附上注释。
预览层贡献33个HTTP测试,以及39个DOM测试(vitest,jsdom,Testing Library,MSW),驱动接口使用真实的点击和按键。 DOM部分需要 `npm install` 在 `layers/preview` 中一次;如果没有它,它会跳过并附上注释而不是失败。
## 限制
* 每次提示一个对象。 TRELLIS.2重建单个主题;请求两个对象会得到一个混乱的对象。
* 面部不通过近距离检查。 296590个三角形和8000个三角形具有相同的熔化面,因此这是重建的上限而不是精简的上限。 默认情况下,角色获得四倍的图集纹理,这弥补了一些问题;头是人物的八分之一,图集按表面面积分配。 帽子、兜帽和风格化角色仍然是解决问题的正确方法。
* 发光对象返回为哑光,并且是纹理而不是渲染器。 TRELLIS.2烘焙了一个金属粗糙度图,测量上述红色跑车,平均粗糙度为0.72,金属度为0.33,图集为2048。 车漆的粗糙度为0.15到0.3,并带有它上面的透明涂层,因此文件本身说的是哑光,而查看器显示的是文件。 读取为有光泽的. 任何读取时看起来像抛光的图像不会在GLB中看起来像抛光。 如果参考图像中某物看起来像抛光,文件本身会说成哑光,查看器正在向您展示文件。
* 没有检查网格是否与提示匹配。 检查姿势,验证文件,测量三角形。 您要的是什么仍然取决于您的眼睛在画廊中。
* 绑定是实验性的。 它生成一个有效的绑定glTF,验证为0个错误和0个警告,并且剪辑播放,但生成的角色不能干净地动画。 打开它在Blender中,并期望修复权重。
* 绑定仅限一个直立的人类或一个道具。 没有四足动物,没有车辆,没有面部或手指,也没有编辑现有网格。
* 没有CPU路径。 `--require-gpu`始终传递,因此缺少Vulkan设备是一个错误,而不是20分钟的回退。
* 在 [`layers/image2mesh/bench/README.md`](layers/image2mesh/bench/README.md) 中描述的gfx1151盒子上测试。