Renderer 模块
src/renderer/ 托管了 WebGPU 渲染器,该渲染器消费预处理后的 Splat,运行 GPU 基数排序器,并为每个可见模型发出单个间接绘制调用。该模块暴露了 GaussianRenderer,这是一个高级协调器,将预处理器、排序器、全局缓冲和渲染管线连接在一起。
职责
- 在
initialize()期间一次性创建静态 GPU 资源(管线布局、渲染管线、间接绘制缓冲)。 - 维护双预处理器(SH + 原始 RGB),以便具有不同颜色编码的模型可以共享同一个渲染器。
- 管理单个
GPURSSorter实例,并按点云/点数缓存PointCloudSortStuff。 - 提供按需增长并允许其多模型批处理的全局缓冲(
splat2D,排序器负载)。 - 通过
prepareMulti/renderMulti驱动预处理、排序和渲染,无论有多少模型可见,都只发出一次间接绘制。 - 提供可选的启用深度的渲染、统计信息和调试辅助工具(
readInstanceCountDebug、readPayloadSampleDebug、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)和可选的 ONNXcountBuffer,将 Splat 写入全局splat2D缓冲内的[baseOffset, baseOffset + numPoints)范围。- 预处理后,单个
GPURSSorter使用预处理填充的计数器执行间接基数排序。 renderMulti绑定全局绑定组并发出一次间接绘制。对于单模型渲染,render()仍然可以使用缓存的每云排序资源工作。
组件
| 组件 | 描述 |
|---|---|
GaussianRenderer |
公共渲染器实现。接受旧版 (device, format, shDeg) 参数或 RendererConfig 对象。 |
RenderArgs |
传递给 prepareMulti 的相机 + 视口 + 渲染设置。 |
RendererConfig |
初始化选项:device、format、shDegree、可选的 compressed、debug。 |
RenderStats |
轻量级统计信息(gaussianCount、visibleSplats、memoryUsage)。 |
DEFAULT_KERNEL_SIZE |
当模型未指定内核半径时使用的共享默认值。 |
资源管理
- 静态资源: 渲染管线(带深度和不带深度)、管线布局、间接绘制缓冲、预处理器、排序器。
- 逐点云缓存:
WeakMap<PointCloud, PointCloudSortStuff>,因此仅当点数更改时才重建排序资源。 - 全局缓冲:
ensureGlobalCapacity()分配共享的splat2D缓冲和排序器负载,大小为所有模型之和。容量以 1.25 倍增长因子增加,以分摊重新分配的开销。
渲染设置
buildRenderSettings() 将每云元数据(bbox/center/mipSplatting)与 RenderArgs 合并:
maxSHDegree会同时限制在渲染器和模型上。kernelSize、gaussianScaling、mipSplatting、showEnvMap、walltime、sceneCenter、clippingBox、sceneExtend每次调度都会推送到预处理器 Uniform 缓冲中。
可以在运行时切换深度渲染:
这将重新创建深度感知管线,同时保持非深度管线不变。
集成点
| 模块 | 交互 |
|---|---|
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的总和超过globalCapacity,ensureGlobalCapacity会重新分配缓冲。预计会出现短暂的峰值,但不会崩溃。 - 混合颜色模式: 确保
PointCloud.colorMode设置正确,以便渲染器选择正确的预处理器(SH vs RGB)。 - 深度伪影: 启用深度管线(
setDepthEnabled(true)),或者如果 Splat 必须纯粹通过排序从后到前渲染,则禁用它。 - 间接绘制停留在零: 在
renderMulti之前调用prepareMulti;预处理通过encoder.copyBufferToBuffer填充间接缓冲。