浏览器里的文生 3D:TRELLIS.2 跑在 WebGPU 上
一句话结论:文生 3D 的默认路线是"上传图片到云、等排队、下载模型"。2026 年 10 月的一个开源实现把整条流水线搬进了浏览器标签页:提示词或照片 → 4B 参数的 TRELLIS.2 → 带 PBR 的 GLB,全程用 WebGPU 在你自己的显卡上跑,不经过服务器。在 RTX 4070 + Chrome、权重已缓存的情况下:照片转 GLB 148 秒,第二次 134 秒,提示词转 GLB 180 秒。第一版要 712 秒。
披露:本文编译自 LostBeard(SpawnDev.ILGPU.ML 作者)的发布文(dev.to,2026-10-17)。作者是项目维护者,时间数据来自其本机单次测量;模型许可证各不相同(TRELLIS.2 为 MIT,DINOv3 / SD Turbo / RMBG-1.4 各有自己的许可),商用时需逐个核对。
一、它不是"又一个在线生成器"
先看它到底做了什么:
| 环节 | 用的模型 | 在哪跑 |
|---|---|---|
| 文本 → 图片 | SD Turbo | 浏览器(WebGPU) |
| 抠图 | RMBG-1.4 | 浏览器 |
| 图片 → 3D | TRELLIS.2-4B(微软,MIT) | 浏览器 |
| 网格简化 / UV / 烘焙 | 自研 C# 代码 | 浏览器(WASM AOT) |
| 输出 | PBR GLB(baseColor + metallicRoughness) | 可直接进 Blender / Unity / three.js |
TRELLIS.2 内部的结构值得记一下:先用 DINOv3 提图像特征,再用三个 1.3B 参数的 flow transformer 分别生成稀疏结构、形状和贴图,然后由稀疏 VAE 解码器解出双网格(dual-grid)mesh。整条链路跑完约 3 分钟,输出可以拖进任何支持 glTF 2.0 的工具。
关键差别在"不上传":你的草稿图、产品照、未公开的模型参考,不会离开本机。对需要保密的工业件、还没发布的产品,这一点比"快 30 秒"重要得多。
二、三个数字:712 秒 → 148 秒
作者在 RTX 4070 + Chrome、权重已缓存的条件下测了三种情况:
| 场景 | 耗时 |
|---|---|
| 照片 → GLB,新开页面 | 148 秒 |
| 照片 → GLB,同页第二次 | 134 秒 |
| 提示词 → GLB | 180 秒 |
| 当天第一版可用实现 | 712 秒 |
从 712 秒压到 148 秒,靠的不是换模型,而是五个工程改动。这五条对任何"把大模型塞进浏览器"的项目都通用。
三、五个工程问题,五条可复用的解法
1. GPU kernel 用 C# 写,编译成 WGSL
每个 kernel 都是一个 C# 方法,由 SpawnDev.ILGPU 编译成 WGSL(桌面端还能编成 CUDA / OpenCL / CPU),同一份源码多目标。两个关键 kernel:
- 寄存器分块的 GEMM:128×128 输出块、256 线程、每线程 8×8 累加器;一个 kernel 同时覆盖 bf16 与 f16 权重,并支持 gather 行。
- Flash attention:8 个 lane 共享一个 query、每线程 4 个 query,用 subgroup shuffle 做归约;不支持 subgroup 的设备走共享内存变体。
在 4070 的 WebGPU 上,这组 kernel 跑到 GEMM 约 8 TFLOPS、attention 约 5.6 TFLOPS。
这条对工程选型的含义:WebGPU 不是"只能跑小模型"。真正的门槛是你能不能把 kernel 写对,而不是算力上限。
2. 10 GB 权重 vs 浏览器存储配额
浏览器的站点存储配额经常小于模型本身。RangeStreamModelSource.PlanCacheAsync 的做法是:算出一个"最能填满配额"的权重文件子集,缓存进 OPFS;剩下的每次运行用 HTTP Range 流式拉取——4 个 16 MB 请求并发,从 fetch 直接进 GPU buffer,不经过 .NET 堆。
var ranged = new RangeStreamModelSource(hubModelSource);
await ranged.PlanCacheAsync(Trellis2Weights.HubWeightFiles(), freeQuotaBytes - 300_000_000L);
using var gen = new Trellis2ImageTo3D(accelerator, Trellis2Weights.FromModelSource(ranged));
byte[] glb = await gen.GenerateGlbAsync(rgbaPixels, width, height);
注意 - 300_000_000L 这个尾巴:给配额留安全余量。浏览器配额会被其他标签页、缓存、清理策略影响,留 300 MB 是保守但必要的做法。
3. Shader 编译是串行的
WebGPU 在首次使用时编译 pipeline,一次一个。GEMM 与 attention 这种大 kernel 每个都要几秒,而它们在运行开头全挤在一起。WebGPUAccelerator.PrecompileAsync(5.3.8 新增)用 createComputePipelineAsync 在加载权重的同时后台编译:4 个 shader 从串行 1571 ms 降到并行 511 ms。
4. 300 万面的网格不能直接简化
双网格输出的面数约 300 万。把这么多三角形直接喂给边折叠(edge collapse)简化器,在浏览器里会卡死。解法是两级:
- 先在 GPU 上做自适应八叉树 + 二次误差聚类,把面数降到约 50 万;
- 再做边折叠,最终输出约 15 万面。
5. Blazor WASM AOT
非 GPU 的阶段(简化、UV 图集打包)是纯 C#,在 .NET 解释器下很慢。开 AOT 之后:
| 阶段 | 解释器 | AOT |
|---|---|---|
| 网格简化 | 41.3 s | 2.6 s |
| UV 图集 | 16.8 s | 0.8 s |
代价是体积:GitHub Pages 拒绝 100 MB 以上的文件,而 AOT 后的 dotnet.native.wasm 超过这个限制。部署方案是只保留 gzip 副本,再用一个小的 loadBootResource 钩子配合 DecompressionStream 在浏览器里解压。
四、怎么用:三条现实建议
1)先确认硬件。 官方建议桌面独显;移动端和集显不在推荐范围。10 GB 权重是可选下载并会缓存,第一次打开会明显更慢。
2)把它当"草稿生成器",不是"资产生产线"。 输出是约 15 万面的 GLB,带 PBR 贴图,适合概念稿、场景占位、产品页 360 预览;不适合直接做精密零件或需要严格尺寸的模型。生成结果仍要走一遍验收:面数、法线朝向、UV 是否重叠、贴图是否齐全。
3)注意许可证是分层的。 代码是 MIT,但 TRELLIS.2 / DINOv3 / SD Turbo / RMBG-1.4 各有各的许可,权重不随包分发、首次使用时从 Hugging Face 下载。"代码开源"不等于"生成结果可随便商用",这条在 AI 3D 里尤其容易踩。
五、它改变了什么,没改变什么
改变了:生成 3D 草稿的隐私边界。以前"不上传"只能用本地桌面软件;现在一个标签页就能做到,这对工业、医疗、还没发布的产品设计是实质差别。
没改变:3D 资产能不能交付仍然取决于生成之后的事——拓扑是否干净、尺度是否正确、贴图是否按预期打包、有没有在看不见的面上"发明"结构。这些检查我们此前在 AI 3D 资产的数字验收 和 五项交接检查 里写过,工具换成浏览器也一样要过。
一句话收尾:"在浏览器里跑 4B 模型"已经不是演示,而是能用的工程。 下一步的竞争点不在"能不能生成",而在"生成完的东西,能不能被下游放心接走"。
Sources
- LostBeard, Text to 3D, 100% in the browser: TRELLIS.2 on WebGPU from C#, dev.to, 2026-10-17:https://dev.to/lostbeard/text-to-3d-100-in-the-browser-trellis2-on-webgpu-from-c-21d3
- 演示:https://lostbeard.github.io/SpawnDev.ILGPU.ML/text-to-3d(约 10 GB 权重为可选下载并缓存)
- 源码(MIT):https://github.com/LostBeard/SpawnDev.ILGPU.ML
同主题阅读
主工具:生成的 GLB 想先看一眼?用在线 3D 模型查看器 直接打开,支持 STL / OBJ / GLB / FBX,文件在浏览器里解析。
本文属于「Web3D / 游戏引擎 / 元宇宙」专题。BimAnt 编译整理,转载请注明出处。文中时间数据为作者单机单次测量,你的显卡与浏览器版本会得到不同结果。