Preprocessing 模块 API 参考
本文档描述了 src/preprocess 模块暴露的公共接口,重点关注渲染器用于多模型分发的具体 GaussianPreprocessor 类。
模块导出
// src/preprocess/index.ts
export interface IPreprocessor {
initialize(device: GPUDevice, shDegree: number): Promise<void>;
getBindGroupLayout(device: GPUDevice): GPUBindGroupLayout;
}
export interface PreprocessResults { /* 为将来使用保留 */ }
export { GaussianPreprocessor } from './gaussian_preprocessor';
渲染设置结构 (Render Settings Shape)
传递给 dispatchModel 的 settings 字段使用以下结构:
interface RenderSettings {
gaussianScaling: number;
maxSHDegree: number;
showEnvMap: boolean;
mipSplatting: boolean;
kernelSize: number;
walltime: number;
sceneExtend: number;
center: Float32Array; // vec3
clippingBoxMin: Float32Array; // vec3
clippingBoxMax: Float32Array; // vec3
}
这些值严格按照上述顺序打包到 80 字节的渲染设置 Uniform 中(有关偏移量,请参阅架构文档)。
DispatchModelArgs
dispatchModel 接收以下形状的参数(与 GaussianRenderer.prepareMulti 调用它的方式一致):
interface DispatchModelArgs {
camera: PerspectiveCamera;
viewport: [number, number];
pointCloud: PointCloud;
sortStuff: PointCloudSortStuff; // 来自 GPURSSorter
settings: RenderSettings;
modelMatrix: Float32Array; // 4×4 变换矩阵
baseOffset: number; // 全局 Splat 缓冲区内的切片偏移
global: { splat2D: GPUBuffer }; // 共享输出缓冲区
countBuffer?: GPUBuffer; // 可选的 ONNX 生成的计数缓冲区
}
GaussianPreprocessor
class GaussianPreprocessor implements IPreprocessor {
constructor();
initialize(device: GPUDevice, shDegree: number, useRawColor?: boolean): Promise<void>;
dispatchModel(args: DispatchModelArgs, encoder: GPUCommandEncoder): void;
getBindGroupLayout(device: GPUDevice): GPUBindGroupLayout;
debugCountValues(): Promise<void>;
}
initialize(device, shDegree, useRawColor = false)
- 创建两个
UniformBuffer实例(相机:272 B,设置:80 B)。 - 构建架构文档中描述的管道布局(4 个绑定组)。
- 将请求的 SH 阶数注入
preprocess.wgsl并编译着色器模块。 - 当
useRawColor为true时,设置USE_RAW_COLOR管道常量(绕过 SH 评估并将 SH 缓冲区解释为直接 RGBA)。
dispatchModel(args, encoder)
记录一个计算通道 (compute pass),该通道将一个点云写入由 baseOffset 定义的全局 Splat 缓冲区切片中。在内部,它:
- 从暂存缓冲区打包并刷新相机 + 设置 Uniform。
- 调用
PointCloud.updateModelParamsWithOffset(modelMatrix, baseOffset),如果存在,还会调用pointCloud.setPrecisionForShader()。 - 刷新点云的模型参数缓冲区,并可选地使用
encoder.copyBufferToBuffer从countBuffer覆盖num_points(字节偏移量 68)。 - 为第 1 组(高斯/SH 缓冲区 + 全局 Splat 输出)和第 3 组(设置 + 模型参数)创建临时绑定组,并复用其他插槽的预构建绑定组。
- 调度
ceil(pointCloud.numPoints / 256)个工作组。
该方法不返回值;结果写入 args 中引用的 GPU 缓冲区。
getBindGroupLayout(device)
返回相机 Uniform 绑定组布局(第 0 组)。这主要供需要将预处理器的相机 Uniform 嵌入其自己的管道布局的系统使用。其他绑定组布局是该类的内部布局。
debugCountValues()
如果 dispatchModel 使用动态 countBuffer 运行,预处理器会存储对源/目标缓冲区的引用。调用 debugCountValues() 使用 debugCountPipeline(参见 src/utils/debug-gpu-buffers.ts)打印 ONNX 计数和模型参数 Uniform,这在诊断间接绘制不匹配时非常方便。
Uniform 辅助函数
packCameraUniforms(camera, viewport)
- 将视图矩阵、视图逆矩阵、投影矩阵(应用
VIEWPORT_Y_FLIP后)、投影逆矩阵、视口大小和camera.projection.focal(viewport)写入暂存缓冲区。 - 调用
UniformBuffer.setData(Float32Array)和flush(device)。
packSettingsUniforms(pointCloud, settings)
- 将
RenderSettings结构序列化为具有小端写入的DataView。 - 在写入场景中心之前填充到所需的 16 字节对齐。
- 调用
UniformBuffer.setData(dataView)和flush(device)。
相关类型
PointCloud(参见doc/modules/03-point_cloud)——拥有高斯/SH 缓冲区、绘制 Uniform 和模型参数 Uniform。PointCloudSortStuff(来自src/sort/radix_sort.ts)——提供sorter_bg_pre、sorter_uni、sorter_dis以及预处理和渲染使用的乒乓缓冲区。PerspectiveCamera——提供packCameraUniforms使用的视图/投影矩阵和焦距计算。
错误处理
- 如果视图或投影矩阵是奇异的(行列式 < 1e-6),
packCameraUniforms内的矩阵求逆将抛出异常。 initialize传播 WebGPU 管道创建错误(例如,不支持的着色器功能)。dispatchModel假设提供的缓冲区足够大;调用者必须确保全局容量(Splat 缓冲区 + 排序器)超过点数总和。
用法快照
const preprocessorSH = new GaussianPreprocessor();
await preprocessorSH.initialize(device, 3, false);
const preprocessorRGB = new GaussianPreprocessor();
await preprocessorRGB.initialize(device, 0, true);
const encoder = device.createCommandEncoder();
let offset = 0;
for (const pc of pointClouds) {
const pre = pc.colorMode === 'rgb' ? preprocessorRGB : preprocessorSH;
pre.dispatchModel({
camera,
viewport: [width, height],
pointCloud: pc,
sortStuff: globalSortStuff,
settings: buildRenderSettings(pc, renderArgs),
modelMatrix: pc.transform,
baseOffset: offset,
global: { splat2D: globalSplatBuffer },
countBuffer: 'countBuffer' in pc ? pc.countBuffer?.() : undefined,
}, encoder);
offset += pc.numPoints;
}