3DGS笔记
3dgs
在 3DGS 出现之前,隐式神经辐射场(NeRF)能够渲染出极其逼真的画面,但因为需要沿光线进行密集的体积采样(Volumetric ray-marching),渲染速度非常慢(通常只能按秒甚至分钟计算一帧).而传统的点云渲染虽然快,但容易出现破洞,走样,且缺乏连续性.
3DGS 结合了这两者的优点:它用连续的数学表达式保证了极高的图像质量,同时又采用了显式的,对 GPU 极其友好的数据结构,实现了真正的高清实时渲染( fps,甚至超过 100 fps).
方法
表示法
在 EWA Volume Splatting 中,每个高斯核的位置和协方差矩阵是固定的死数据.但在 3DGS 中,它们变成了神经网络优化器里的 可学习参数 (Learnable Parameters).
这里有一个非常硬核的数学坑,也是 3DGS 论文在系统设计上的亮点:如果在代码里直接用梯度下降去硬更一个 的协方差矩阵 ,优化器极容易把它更成一个非正定矩阵.在概率论中,协方差矩阵一旦非正定,这个高斯椭球在物理上就崩溃了(变成了复数或负体积).
3DGS 放弃了直接优化 ,而是把 强行拆解成了两个独立的数据结构:一个 3D 缩放向量 (Scale) 和一个四元数 (Rotation/Quaternion).根据线性代数公式 ,每次前向传播时临时把它们组装成协方差矩阵.这样,无论梯度下降怎么瞎更新 和 ,算出来的 永远是合法的正定矩阵!
密度控制
EWA 处理的医学 CT 数据是固定大小的体素网格.但在 3DGS 中,我们只有从运动恢复结构(SfM)算法中白嫖来的极少数稀疏特征点作为初始值.
随着梯度下降的进行,如果某个高斯核在屏幕上的位置梯度很大(说明它拼命想移动去填补某个缺失的画面细节,这叫”欠重建”),系统就会在代码层面直接 Clone 它,让它一分为二,去填补空缺.如果一个高斯核变得非常庞大,遮蔽了太多本该有精细纹理的地方(“过度重建”),系统就会把它 Split 成两个小一圈的高斯体.
光栅化
EWA 的原版代码是相对低效的,它需要为每个 Splat 计算包围盒,然后在屏幕上一个像素一个像素地累加.3DGS 面对的是现代 GPU(CUDA 架构),并且它不仅要正向渲染,还要能够把误差梯度反向传播给几百万个高斯核.如果用传统方法,显存会瞬间爆炸.
- 图块化 (Tile-based):将屏幕切成 的小块.
- 极速排序 (Radix Sort):不给像素排序,而是用 GPU 底层的基数排序算法,给所有跨越该图块的高斯核按深度 进行极速排序.
- 无锁并行 (Lock-free blending):每个图块分配一个 CUDA 线程块 (Thread Block).线程把排序好的高斯数据加载到极速的共享内存 (Shared Memory) 中,然后顺着视线从前向后做 Alpha 混合.一旦 累加到 1(说明这块区域的光已经被前面的高斯核挡死了),后面的高斯核直接扔掉不作计算(Early Stop).
- 反向传播的内存魔术:为了求导,它不需要把每一步的中间状态存在显存里.正向算完后,反向传播只需按从后往前的顺序再遍历一次,利用数学恒等式就能算出每个高斯核的梯度,打破了以往方法对梯度计算数量的硬性限制.
3dgs怎么工作的?
输入
3dgs有三个输入
- 一堆照片:比如 50 张照片.这些是真实的监督信号(Ground Truth).
- 相机的位姿:系统需要知道每一张照片是在 3D 空间的哪个位置,朝哪个方向拍的.
- 稀疏点云:这是用来初始化高斯核的种子.
通常,把这 50 张照片扔进一个叫 COLMAP 的开源软件(这是一个标准的运动恢复结构 SfM 算法).COLMAP 跑完之后,会直接吐出需要的每张照片的精确相机位姿,以及一个附带生成的稀疏点云.
系统把 COLMAP 吐出来的稀疏点云加载进来.假设点云有 1 万个点,系统就在这 1 万个位置上,生成 1 万个初始的 3D 高斯核.每个高斯核有一个小小的初始体积和半透明度.
训练
3dgs不训练模型,而是优化参数.
可以把模型看作是一个巨大的 Excel 表格:
- 每一行代表一个高斯核.
- 每一列是它的参数:位置 ,缩放比例 ,旋转四元数 ,不透明度 ,以及决定颜色的球谐函数系数.
训练循环 (Training Loop) 也就是前向传播和反向传播的交替:
- 抽取机位(前向传播):系统随机从那 50 个已知的相机位姿中挑出一个(比如第 10 张照片的机位).
- 渲染假照片:系统把当前的 3D 高斯核,通过 EWA 里的透视投影公式和那套极速的图块化光栅化算法,在这个机位上”画”出一张图.
- 计算误差:把刚画出来的”假照片”和那张真实的第 10 张照片进行逐像素的对比,算出一个误差值(通常是 Loss 加上 D-SSIM 结构相似度度量).
- 反向传播:这是核心!计算误差对每一个高斯核参数的偏导数(梯度).这告诉系统:”如果我把这高斯核往左移一点,或者变得更红一点,误差会不会变小?”
- 更新参数:根据算出的梯度,微调每一个高斯核的参数.
- 自适应密度控制 (每 100 步触发一次):检查哪些高斯核的位置梯度太大(需要分裂/克隆),哪些高斯核太透明了(需要删除),动态改变表格的行数(高斯核的总数).
输出
输出的通常是一个 .ply 格式的文件,里面密密麻麻记录了几百万个高斯体的最终位置,最终缩放,最终旋转,最终透明度和最终颜色.
渲染
- 设定任意机位:通过鼠标或键盘,在软件(比如一个基于 OpenGL 或 WebGL 的查看器)里随意设定一个虚拟摄像机的位置和朝向.
- 运行光栅化:查看器读取那份
.ply参数表,再次调用 3DGS 极速的图块化栅格化算法.- 把高斯核投影到当前屏幕.
- 按 16x16 的图块进行极速排序(Radix Sort).
- 在每个像素上,顺着视线把高斯核的颜色按 Alpha 混合累加起来(早期停止).
- 输出帧:屏幕上立刻显示出当前视角的画面.