跳转至

Three.js Integration 模块

Three.js Integration 模块是 Visionary 的 WebGPU 高斯渲染器与常规 Three.js 场景图之间的胶水层。Visionary 不会合成两个 HTML 画布,而是在驱动 THREE.WebGPURenderer同一 WebGPU 设备上运行所有内容。这使得网格、Splat、深度和 Gizmo 覆盖层保持完美同步,同时留在熟悉的 Three.js 渲染循环中。

概览

  • 单设备、单画布架构。高斯 Splat 被渲染到 Three.js 使用的同一交换链纹理(和可选深度纹理)中。
  • GaussianThreeJSRenderer 协调混合管道:捕获场景深度,运行高斯预处理/Splatting,并合成 Gizmo。
  • GaussianSplattingThreeWebGPU 暴露了由 GaussianThreeJSRenderer 使用的低级集成,并且可以被需要直接渲染通道控制的工具复用。
  • CameraAdapter / DirectCameraAdapterTHREE.PerspectiveCamera 视图/投影数据转换为高斯渲染器使用的 WebGPU 友好数学格式。
  • GaussianModel 扩展了 THREE.Object3D,因此变换、可见性和动画设置会自动传播到 GPU 缓冲区。
┌──────────────────────────────┐       ┌──────────────────────────────┐
│ Three.js 场景图               │       │ Visionary 渲染栈             │
│  - 网格 / 灯光 / Gizmo       │       │  - GaussianRenderer (计算)   │
│  - GaussianModel 实例        │◀─────▶│  - CameraAdapter             │
│  - GaussianThreeJSRenderer   │       │  - 覆盖层合成器               │
└──────────────────────────────┘       └──────────────────────────────┘
                 ▲                                   │
                 └──── 共享的 GPUDevice / 命令编码器 ────────┘

核心职责

GaussianThreeJSRenderer (src/app/GaussianThreeJSRenderer.ts)

  • 驻留在场景图中(继承自 THREE.Mesh),因此它接收 onBeforeRender 回调。
  • 通过 renderThreeScene 将 Three.js 场景捕获到内部 RenderTarget + DepthTexture 中。
  • onBeforeRender 内安排高斯预处理(计算 + 排序),然后在 drawSplats 中绘制 Splat,复用相同的 GPUCanvasContext
  • 提供 自动深度模式(默认),将捕获的深度缓冲区反馈回 WebGPU 渲染通道,以便网格自动遮挡 Splat。
  • 提供可选的 Gizmo 覆盖层渲染(renderOverlayScene),该层在 Splat 之后合成。
  • 管理每个 GaussianModel 的运行时参数:SH 阶数、内核大小、不透明度/截止/增益、动画时钟、可见性等。

GaussianSplattingThreeWebGPU (src/three-integration/GaussianSplattingThreeWebGPU.ts)

  • 针对已经管理自己命令编码器的消费者的最小集成助手。
  • 复用来自 THREE.WebGPURendererGPUDevice,处理点云加载,并暴露一个 render() 方法,该方法期望调用者提供 GPUCommandEncoder、颜色/深度视图和同步的相机。
  • 附带 DirectCameraAdapter,这是应用其他地方使用的相机转换逻辑的独立版本。

CameraAdapter & GaussianModel

  • CameraAdapter 镜像了 DirectCameraAdapter,但打包用于在 Visionary 应用(动态模型、编辑器、导出器)中复用。
  • GaussianModel 保持 Object3D 变换和高斯渲染器缓冲区同步,每当 TRS 更改时自动同步变换。它还代理用于 ONNX/动态 Splat 的动画控制。

帧流程 (混合渲染循环)

  1. 更新动态 (可选) gaussianRenderer.updateDynamicModels(camera, time) 运行支持 ONNX 的点云,以便变形始终匹配当前相机矩阵。
  2. 覆盖层 / Gizmo 通道 (可选) 辅助 Three.js 场景(Gizmo、助手、HUD)被渲染到 gizmoOverlayRT 中。
  3. 场景通道 renderThreeScene(camera) 将主 Three.js 场景渲染到半浮点渲染目标,捕获其深度缓冲区,然后通过 WebGPU 全屏通道将颜色缓冲区 Blit(传输)到画布(包括线性 → sRGB 转换)。
  4. 高斯预处理onBeforeRender 内部,渲染器收集可见的 GaussianModel,将变换同步到 GPU,并在共享设备上运行 GaussianRenderer.prepareMulti(...)
  5. 高斯绘制 + 合成 drawSplats(...) 直接将 Splat 渲染到当前交换链视图中。当自动深度启用时,先前捕获的深度纹理被插入,以便网格遮挡 Splat。如果存在 Gizmo 覆盖层,它将作为最终的全屏通道进行合成。

此顺序保证了确定性的深度,避免了冗余的场景渲染,并消除了对双画布或 WebGL 回退的需求。

自动深度模式亮点

  • 使用 THREE.RenderTarget + THREE.DepthTexture(HalfFloat 颜色,Float 深度),尺寸调整为绘制缓冲区大小。
  • 通过 WebGPU 渲染通道进行 Blit,以便我们控制色彩空间转换和格式兼容性。
  • setAutoDepthMode(false) 为高级用户提供手动控制:你可以通过 setOccluderMeshes 提供自己的遮挡物网格,但应首选自动深度。

为什么要用共享设备策略?

  • 零拷贝 – 高斯数据在预处理、排序和绘制之间从未离开 GPU 内存。
  • 状态一致 – 没有发散的相机数学或 DOM 覆盖层;所有内容都使用相同的矩阵、像素比和可见性状态。
  • 可扩展性 – 因为我们在 Three.js 的渲染循环中运行,所以后期处理堆栈、XR 会话、OrbitControls 等继续工作。
  • 诊断 – 渲染器暴露了如 diagnoseDepth()disposeDepthResources() 等钩子,以便在不拆除场景的情况下检查和重置管道。

快速开始 (Visionary App)

import { GaussianThreeJSRenderer } from 'src/app/GaussianThreeJSRenderer';
import { GaussianModel } from 'src/app/GaussianModel';

const threeRenderer = await initThreeContext(canvas);       // r155+ WebGPU 渲染器
const gaussianModels = loadedEntries.map(entry => new GaussianModel(entry));
gaussianModels.forEach(model => scene.add(model));

const gaussianRenderer = new GaussianThreeJSRenderer(threeRenderer, scene, gaussianModels);
await gaussianRenderer.init();
scene.add(gaussianRenderer); // 确保 onBeforeRender 钩子触发

function animate(timeMs: number) {
  requestAnimationFrame(animate);

  gaussianRenderer.updateDynamicModels(camera, timeMs * 0.001);
  gaussianRenderer.renderOverlayScene(gizmoScene, camera); // 可选
  gaussianRenderer.renderThreeScene(camera);
  gaussianRenderer.drawSplats(threeRenderer, scene, camera);
}

animate(0);

应用外壳之外

如果你已经拥有渲染循环,并且只需要将 Splat 绘制到 WebGPU 帧缓冲区中:

const gs = new GaussianSplattingThreeWebGPU();
await gs.initialize(webgpuRenderer.backend.device);
await gs.loadPLY('/assets/room.ply');

const encoder = device.createCommandEncoder();
gs.render(
  encoder,
  context.getCurrentTexture().createView(),
  camera,
  [width, height],
  depthTexture?.createView()
);
device.queue.submit([encoder.finish()]);

相关文档

  • Architecture – 命令流图,自动深度内部结构和诊断工具。
  • API Reference – 构造函数签名,生命周期钩子和 Three.js 桥接助手。
  • Renderer Module – 共享为桥接提供动力的核心 WebGPU 渲染器。
  • Camera Module – 详述此处镜像的 CameraAdapter 接口。
  • Controls Module – 解释 DOM 事件如何馈送到适配器管道。