跳转至

Renderer 模块

src/renderer/ 托管了 WebGPU 渲染器,该渲染器消费预处理后的 Splat,运行 GPU 基数排序器,并为每个可见模型发出单个间接绘制调用。该模块暴露了 GaussianRenderer,这是一个高级协调器,将预处理器、排序器、全局缓冲和渲染管线连接在一起。

职责

  • initialize() 期间一次性创建静态 GPU 资源(管线布局、渲染管线、间接绘制缓冲)。
  • 维护双预处理器(SH + 原始 RGB),以便具有不同颜色编码的模型可以共享同一个渲染器。
  • 管理单个 GPURSSorter 实例,并按点云/点数缓存 PointCloudSortStuff
  • 提供按需增长并允许其多模型批处理的全局缓冲(splat2D,排序器负载)。
  • 通过 prepareMulti / renderMulti 驱动预处理、排序和渲染,无论有多少模型可见,都只发出一次间接绘制。
  • 提供可选的启用深度的渲染、统计信息和调试辅助工具(readInstanceCountDebugreadPayloadSampleDebug、ONNX 计数跟踪)。

关键 API

import { GaussianRenderer, DEFAULT_KERNEL_SIZE } from 'src/renderer';
import type { RenderArgs, RendererConfig, RenderStats } from 'src/renderer';

const renderer = new GaussianRenderer({
  device,
  format: navigator.gpu.getPreferredCanvasFormat(),
  shDegree: 3,
  debug: true,
});
await renderer.initialize();

renderer.prepareMulti(encoder, device.queue, pointClouds, {
  camera,
  viewport: [canvas.width, canvas.height],
  maxSHDegree: 3,
  kernelSize: DEFAULT_KERNEL_SIZE,
});

const pass = encoder.beginRenderPass(passDesc);
renderer.renderMulti(pass, pointClouds);
pass.end();

有关完整表面区域,请参阅 API 参考

管线流程

initialize()  -> 创建管线、预处理器、排序器、间接缓冲
prepareMulti() -> 确保容量 -> 重置排序器状态 -> 逐模型 dispatchModel -> sorter.recordSortIndirect -> 修补 drawIndirect
renderMulti()  -> 绑定全局 splat + 排序器绑定组 -> drawIndirect()
  • prepareMulti 尊崇每个 PointCloud 的颜色模式(SH 或 RGB)和可选的 ONNX countBuffer,将 Splat 写入全局 splat2D 缓冲内的 [baseOffset, baseOffset + numPoints) 范围。
  • 预处理后,单个 GPURSSorter 使用预处理填充的计数器执行间接基数排序。
  • renderMulti 绑定全局绑定组并发出一次间接绘制。对于单模型渲染,render() 仍然可以使用缓存的每云排序资源工作。

组件

组件 描述
GaussianRenderer 公共渲染器实现。接受旧版 (device, format, shDeg) 参数或 RendererConfig 对象。
RenderArgs 传递给 prepareMulti 的相机 + 视口 + 渲染设置。
RendererConfig 初始化选项:deviceformatshDegree、可选的 compresseddebug
RenderStats 轻量级统计信息(gaussianCountvisibleSplatsmemoryUsage)。
DEFAULT_KERNEL_SIZE 当模型未指定内核半径时使用的共享默认值。

资源管理

  • 静态资源: 渲染管线(带深度和不带深度)、管线布局、间接绘制缓冲、预处理器、排序器。
  • 逐点云缓存: WeakMap<PointCloud, PointCloudSortStuff>,因此仅当点数更改时才重建排序资源。
  • 全局缓冲: ensureGlobalCapacity() 分配共享的 splat2D 缓冲和排序器负载,大小为所有模型之和。容量以 1.25 倍增长因子增加,以分摊重新分配的开销。

渲染设置

buildRenderSettings() 将每云元数据(bbox/center/mipSplatting)与 RenderArgs 合并:

  • maxSHDegree 会同时限制在渲染器和模型上。
  • kernelSizegaussianScalingmipSplattingshowEnvMapwalltimesceneCenterclippingBoxsceneExtend 每次调度都会推送到预处理器 Uniform 缓冲中。

可以在运行时切换深度渲染:

renderer.setDepthEnabled(true);
renderer.setDepthFormat('depth24plus');

这将重新创建深度感知管线,同时保持非深度管线不变。

集成点

模块 交互
Point Cloud (src/point_cloud) 提供绑定组布局、Splat 缓冲、变换和每模型参数。渲染器在 @group(0) 绑定 pointCloud.renderBindGroup()
Preprocess (src/preprocess) 两个 GaussianPreprocessor 实例驱动每个点云的 dispatchModel。它们写入全局 splat2D 缓冲和排序器计数器。
Sorting (src/sort) 单个 GPURSSorter 提供预处理和渲染绑定组布局以及基数排序管线。排序输出控制 drawIndirect
Shaders (src/shaders/gaussian.wgsl) 顶点着色器从存储缓冲读取所有属性;片元着色器实现具有预乘 Alpha 的高斯泼溅。

调试与统计

  • renderer.getRenderStats(pointCloud) 返回计数和粗略的内存估计。
  • readInstanceCountDebug() 将当前间接绘制实例计数复制到 CPU 以供检查。
  • readPayloadSampleDebug(n) 从全局排序器缓冲转储前 n 个负载索引。
  • debugONNXCount() 链接到预处理器调试流以验证 ONNX 驱动的计数。

常见问题与提示

  • 容量超限: 如果 pointCloud.numPoints 的总和超过 globalCapacityensureGlobalCapacity 会重新分配缓冲。预计会出现短暂的峰值,但不会崩溃。
  • 混合颜色模式: 确保 PointCloud.colorMode 设置正确,以便渲染器选择正确的预处理器(SH vs RGB)。
  • 深度伪影: 启用深度管线(setDepthEnabled(true)),或者如果 Splat 必须纯粹通过排序从后到前渲染,则禁用它。
  • 间接绘制停留在零:renderMulti 之前调用 prepareMulti;预处理通过 encoder.copyBufferToBuffer 填充间接缓冲。

相关文档

  • 架构 – 渲染管线设计、全局缓冲管理和多模型批处理架构。
  • API 参考 – 渲染器配置结构、生命周期方法和调试辅助工具。
  • 预处理模块 – 投影 Splat 和计数器缓冲的来源。
  • 排序模块 – 解释间接绘制负载在渲染前如何排序。