Point Cloud 模块架构
Point Cloud(点云)模块是数据摄入与 GPU 执行之间的规范桥梁。它接收 GenericGaussianPointCloudTS 对象(来自 IO 或 ONNX 路径),实例化预处理和渲染管线所需的 GPU 缓冲区,跟踪每个模型的 Uniform,并暴露绑定组及动态钩子,以便每个下游阶段都能消费一致的契约。
管线图
┌──────────────┐ ┌───────────────────────────┐ ┌────────────────────┐
│ IO / ONNX │ ───► │ PointCloud / DynamicPC │ ───► │ Preprocess Compute │
│ (数据源) │ │ • GPU 缓冲区 │ │ (预处理计算) │
└──────────────┘ │ • Uniform + 模型参数 │ │ • 深度排序阶段 │
│ • 绑定组句柄 │ └─────────┬──────────┘
└───────────────────────────┘ │
┌─────────────▼──────────┐
│ Renderer / Indirect MW │
│ (渲染器 / 间接绘制) │
└────────────────────────┘
静态资源遵循 IO 路径,而实时场景通过 DynamicPointCloud 直接注入 GPU 缓冲区。两者最终都使用相同的绑定组布局,使预处理、排序和渲染模块无需关心数据来源。
构造路径
- 元数据摄入 –
PointCloud从GenericGaussianPointCloudTS实现中读取计数、SH 阶数、边界框以及可选的center/up向量。这些值将填充公共字段,如numPoints、shDeg、bbox和方向辅助属性。 - 高斯与 SH 存储 – 除非提供
externalBuffers,否则 CPU 缓冲区将被上传到 WebGPU 缓冲区,标记为gaussians/storage和sh/storage,用途为STORAGE | COPY_DST(见point_cloud.ts构造函数)。 - 投影 Splat 缓冲区 – 使用
BUFFER_CONFIG.SPLAT_STRIDE分配专用的 2D 缓冲区(splat2DBuffer),以确保有足够空间存放投影属性、排序键和间接绘制元数据(GPUBufferUsage.STORAGE | COPY_SRC | COPY_DST | INDIRECT)。 - Uniform 缓冲区 – 生成两个
UniformBuffer实例: uniforms: 16 字节,用于点数和 SH 阶数,由预处理着色器消费。modelParamsUniforms: 128 字节,对齐到 16 字节边界,携带变换、偏移、着色控制和精度描述符。- 绑定组 – 该模块从
getBindGroupLayout/getRenderBindGroupLayout获取缓存的布局,并立即创建pointcloud/bg(计算)和pointcloud/render/bg(渲染)实例,以便管线可以直接绑定它们而无需额外连线。
绑定组契约
- 计算 (
@group(0)) binding 0: 高斯存储 (read-only-storage)。binding 1: SH 存储 (read-only-storage)。binding 2: 2D Splat 缓冲区 (storage– 也用作间接绘制目标)。binding 3: 绘制 Uniform (uniform)。- 渲染 (
@group(0)) binding 2: 对投影 Splat 缓冲区的只读访问,用于顶点阶段光栅化。
布局存在于每个 GPUDevice 的 WeakMap 缓存中,保证确定的绑定顺序,避免在多个点云共存时发生布局频繁变动。
模型参数 Uniform
PointCloud 在 CPU 内存中保留权威的变换/配置块,并通过 updateModelParamsBuffer(也被 setTransform 和 updateModelParamsWithOffset 调用)写入。该结构对应 WGSL 的预期:
- 字节 0–63: 列主序模型矩阵。
- 字节 64–95: 多实例渲染的元数据(
baseOffset,numPoints)和着色控制(gaussianScaling,maxShDeg,kernelSize,opacityScale,cutoffScale,rendermode)。 - 字节 96–119: 精度描述符(
gaussDataType,colorDataType, 每通道缩放和零点),用于在着色器中解码 INT8/UINT8 数据。 - 字节 120–127: 保留填充。
由于每当 updateModelParamsBuffer 运行时缓冲区都会重建,下游系统只需保留对 modelParamsUniforms.buffer 的引用,并将其写入渲染器中负责模型 Uniform 的任何绑定组。
DynamicPointCloud 流程
DynamicPointCloud 继承了 PointCloud 的所有功能,但更改了构造函数契约:
- 接受现有的
GPUBuffer句柄(gaussianBuffer,shBuffer)以及描述间接管线实时绘制计数的countBuffer(可选)。 - 根据提供的
colorChannels(3, 4, 12, 27, 48)计算 SH 阶数,并暴露colorMode(如果是 4 通道则为rgb,否则为sh)。 - 存储可选的
precisionInfo(高斯/颜色),以便可以通过setPrecisionForShader将量化元数据注入模型参数块。 - 管理一个嵌入的
TimelineController,暴露诸如startAnimation,setTimeScale,setTimeUpdateMode,setAnimationIsLoop, 和resetFrameTime等辅助函数,以便动画管理器可以以一致的时间语义驱动 ONNX 模型。 - 异步的
update方法将相机矩阵与模型变换组合,计算调整后的帧时间(考虑循环/离线预览模式),并调用 ONNX 生成器,后者直接写入绑定的 GPU 缓冲区——在稳定状态下无 CPU 拷贝。
精度与缓冲区交换
replaceStorageBuffers(基类)交换高斯/SH 缓冲区并重建计算绑定组,同时保留投影 Splat 缓冲区和 Uniform。applyFP16(动态子类)是一个便捷包装器,用于替换缓冲区,将高斯/颜色精度标记为float16,并刷新着色器元数据。setPrecisionForShader使用DataView设置器重写模型参数缓冲区的第 96–119 字节,以便着色器可以按需解码 INT8/UINT8 负载。
这些路径允许预处理模块运行转换着色器(例如 convert_precision.wgsl),然后重新绑定结果而无需重新实例化 PointCloud。
资源生命周期与诊断
getSplatBuffer发布原始 GPU 存储加元数据,预处理模块使用它来驱动计算调度大小。- 参数设置器(
setGaussianScaling,setMaxShDeg,setKernelSize,setOpacityScale,setCutoffScale,setRenderMode)更新缓存状态并复用updateModelParamsBuffer来刷新更改。 DynamicPointCloud.countBuffer()暴露可选的绘制计数缓冲区,以便渲染器可以配置间接绘制。getPerformanceStats展示时间轴相关的遥测数据(isPlaying, 动画速度, ONNX 链接),用于 UI 覆盖层或调试工具。dispose目前仅清除时间轴监听器;GPU 缓冲区仍归外部所有,以避免重复释放共享资源。
数据流摘要
[GenericGaussianPointCloudTS] ──► PointCloud 构造函数 ──► {gaussianBuffer, shBuffer, splatBuffer}
│
├─► UniformBuffer (绘制)
└─► UniformBuffer (模型参数)
[ONNX Generator] ──► DynamicPointCloud.update ──► 直接 GPU 写入 ──► 相同的绑定组
通过标准化缓冲区生命周期、绑定组布局和精度元数据,点云模块确保 IO 加载器、ONNX 管道、预处理内核、排序器和渲染器都达成单一契约,保持 Visionary 的 WebGPU 技术栈可预测且可扩展。