渲染 | Gaussian Splatting 源码解析
❗️此坑还没填完
TODO: GS 组成
- point cloud
- render flow
- optimize
仓库结构
仓库由 C++/CUDA 和 Python 组成,CUDA 包括 diff-rasterization ,Python 包括 optimize 。CUDA 部分依赖 glm ,只用了 glm 的 vector 数据类型。
Rendering (C++/CUDA Part)
Python-CUDA 接口
CUDA 向 Python 暴露的就三个方法,rasterize_gaussians
, rasterize_gaussians_backward
和 mark_visible
。 Python 再包装上 torch.autograd.Function
,最后以 GaussianRasterizer
和 GaussianRasterizationSettings
这俩个接口。
Python 和 CUDA 映射如下:
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
m.def("rasterize_gaussians", &RasterizeGaussiansCUDA);
m.def("rasterize_gaussians_backward", &RasterizeGaussiansBackwardCUDA);
m.def("mark_visible", &markVisible);
}
Frustum Culling
相关定义主要在 cuda_rasterizer/auxiliary.h
in_frustum()
做俩次变换投影到 ImageSpace,比较深度(z 坐标),这里的 z 值是到相机原点平面的深度,在屏幕平面后的点舍弃(z<0.2)。
函数中注释了对 x 和 y 方向的判断,因为 Gaussian Splatting 严格是无限大,和传统 culling Frustum 不太一样。 需要通过置信度阈值来筛选置信度,不能简单地通过投影后的二维距离来判断。
不过 mark visible 似乎根本就没有调用?
Chunk Management
相关定义主要在 cuda_rasterizer\rasterizer_impl.h
把内存按切分成一个个 chunk(内存块),每个 chunk的第一个地址是起始地址,起始地址都是对齐的。比如按 16 字节切分,起始地址就是 0x00, 0x10, 0x20 ... ;0x00~0x0F ,0x10~0x1F ,0x20~0x2F 是切好的一个个 chunk,chunk 也可以用起始地址标识。
下面方法先获取指针所指位置 chunk(起始地址/对齐地址),再在起始地址上偏移相应元素得到新地址,是一个多对一的函数映射。
static void obtain(char*& chunk, T*& ptr, std::size_t count, std::size_t alignment)
{
std::size_t offset = (reinterpret_cast<std::uintptr_t>(chunk) + alignment - 1) & ~(alignment - 1);
ptr = reinterpret_cast<T*>(offset);
chunk = reinterpret_cast<char*>(ptr + count);
}
diff GS Chunk 内管理着三种 buffer 数据 :GeometryState, ImageState, BinningState,都以 128 字节作为 chunk size 切割分块。
- GeometryState 点云的基本信息,位置(means2D)、协方差(cov)、颜色(rgb)、透明度(conic_opacity)等(这个似乎是投影过后的)
- ImageState 渲染到图像上的数据,主要是存储渲染过程中的 partial sum
- BinningState 用来管理点云列表排序
通过 fromChunk()
从统一的 chunk 获取对应的 strut 实例。
Forward
Gaussian Splatting 表示
类似 NeRF,GS 的 color 是 view-denpendence 的,和观察的视角有关。也就是一个视角到 Color 的函数映射。NeRF 使用神经网络表示该函数;GS 是 pure explict 结构,采用球谐函数表示。
preprocess
TODO
Optimize (Python Part)
相关定义主要在 train.py
- Densification
- Split
- Clone
- Opacity Reset
默认训练超参数如下:
Params | Value |
---|---|
iterations |
30k |
densify_until_iter |
15k |
densify_from_iter |
0.5k |
densification_interval |
0.1k |
opacity_reset_interval |
3k |
分阶段优化方案
- 0 只优化 GS 的参数
- desinify_until_iter ~ densify_until_iter,优化 GS 的参数和数量
- 每 densification_interval 优化数量
- 每 opacity_reset_interval 重置透明度上限(如果开启 white background 则每 iter 都会重置透明度上限)
- densify_until_iter ~ iterations,只优化 GS 的参数
Split & Clone
TODO
Reset Opacity
相关文件 scene\gaussian_model.py
reset_opacity()
将 Opacity clamp 到 \((-\infty, 0.01)\)