浏览器里的文生 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)简化器,在浏览器里会卡死。解法是两级:

  1. 先在 GPU 上做自适应八叉树 + 二次误差聚类,把面数降到约 50 万;
  2. 再做边折叠,最终输出约 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

同主题阅读

主工具:生成的 GLB 想先看一眼?用在线 3D 模型查看器 直接打开,支持 STL / OBJ / GLB / FBX,文件在浏览器里解析。

本文属于「Web3D / 游戏引擎 / 元宇宙」专题。BimAnt 编译整理,转载请注明出处。文中时间数据为作者单机单次测量,你的显卡与浏览器版本会得到不同结果。