跳转到内容

3D Gaussian Splatting — 用一堆 3D 模糊光斑重建场景

待复核

3D Gaussian Splatting(3DGS)是一种用几百万个”3D 模糊光斑”拼出一个真实场景的方法。日常类比:像在三维空间里喷一群彩色烟雾团,每个团有自己的位置、形状、颜色和浓度,叠在一起从任何角度看都像真的。

你给它一组同一场景拍的照片(几十到几百张),3DGS 会把每张照片对比”如果用这堆光斑拍这个角度会长什么样”,然后用梯度下降同时调整每个光斑的位置、形状、颜色,直到所有照片都对得上。

最后这堆光斑就是场景的”3D 拷贝”——从任意新视角去渲染,1080p 每秒 100 帧以上,看起来和原场景视频几乎一样。

不理解 3DGS,下面这些事都没法解释:

  • 为什么 2024 年起 Apple Vision Pro 的”空间场景”、Polycam 和 Luma AI 的 3D capture App 突然变得又快又像真的
  • 为什么 NeRF(2020 年神作)热度被超越——3DGS 训练快 10 倍、渲染快 1000 倍,质量还更好
  • 为什么仿真公司开始用 3DGS”重建路口”做闭环测试——比纯仿真真实,比录视频灵活
  • 为什么”光斑”这种听起来粗糙的表示,反而比一个 100M 参数的神经网络更精细

3DGS 把场景搞定的过程可以拆成 三步

  1. 每个光斑是一张可学习的小卡片:每个 3D Gaussian 存 59 个浮点数(位置 3 + 形状 4+3 + 颜色 SH 48 + 透明度 1)。类比:拼图里一张彩色透明胶片,记下放哪儿、转多少、什么颜色、多透明。

  2. GPU 并行投影 + 透明叠加:渲染时不是从相机射光线(NeRF 的方式),而是反过来——把每个光斑投影到屏幕,按深度从前到后做透明度混合(α-blending)。屏幕分成 16×16 的小方格并行算,几百万光斑也能 100+ FPS。

  3. 训练中自动加点 / 删点:从 COLMAP 标定时副产的几十万稀疏点开始,每 100 步看哪些光斑”还没拟合好”(屏幕梯度大)→ 复制或分裂成更小的;哪些光斑”几乎透明”(α<0.005)→ 直接删掉。点数从 100k 自适应长到 1-5M 再剪回来。

三步加起来叫 adaptive Gaussian splatting,2023 年 SIGGRAPH Best Paper

数学上一个 3D Gaussian 是这个连续函数:

G(x) = exp( -½ (x - μ)ᵀ Σ⁻¹ (x - μ) )

μ 是中心位置(3 个 float),Σ 是 3×3 协方差矩阵描述形状(球还是椭球还是扁饼)。

逐部分解释

  • 关键工程问题:Σ 必须半正定(不然不是合法的高斯),但梯度下降不会自动维持
  • 解法:把 Σ 写成 Σ = R S Sᵀ Rᵀ,R 由 4 个 quaternion 算出(旋转),S 是 3 个 scale(尺度)
  • 这样梯度怎么乱推,构造出的 Σ 永远合法——这一招让训练根本能跑
# 简化版,真实代码在 gaussian_renderer/__init__.py
for tile in screen.split_into_16x16_tiles():
gaussians = gaussians_overlapping(tile)
gaussians.sort_by_depth()
color = bg_color
for g in gaussians:
alpha = g.opacity * gaussian_2d_value_at(g, tile.pixel)
color = color + (1 - color.a) * alpha * g.view_dependent_color()
tile.write(color)

逐部分解释

  • 16×16 tile 是为了 GPU 并行:每个 tile 是独立 warp,互不干涉
  • 按深度排序后做”前到后”α-blending,对应物理上”近的物体先挡光”
  • 颜色是 view-dependent 的(用球谐 SH 表示)——同一个光斑从不同角度看颜色可以不一样,反光面就靠这个
  • 整个过程只是几次 GPU kernel 调用——不像 NeRF 要对每条 ray 跑 192 次 MLP。所以 1080p @ 100+ FPS
# 每 100 iter 跑一次(scene/gaussian_model.py 的 densify_and_prune)
for g in gaussians:
if screen_grad(g) > 0.0002:
if g.scale < 0.01 * scene_extent:
clone(g) # 小 Gaussian 复制一份
else:
split(g, N=2) # 大 Gaussian 分裂成 2 个更小的
if g.opacity < 0.005:
remove(g) # 看不见的删了

直觉:屏幕梯度大 = 这块还没拟合好。小光斑就在原地复制(细节加密),大光斑分裂成 2 个更小的(粗变细)。透明的直接删掉。

整个 trick 和数据集中的”加难题 / 删冗余题”思路一致——把训练监控反馈到”参数池策划”上,让点数本身变成可学的对象。

  1. 协方差直接学会崩:直接对 6 个 Σ 分量做梯度下降会让矩阵失去半正定性,渲染出 NaN。必须用 quaternion+scale 重参数化。
  2. 不重置 opacity 会陷局部最优:Gaussian 一旦”生根”位置就难调。论文每 3000 iter 把所有 opacity 重置成 0.01,强迫不该存在的重新学回来——这是核心 trick。
  3. densify_grad_threshold = 0.0002 是绝对值跨场景通用:不随场景大小调整。Mini-Splatting 等 2024 后作把它换成自适应,原文却没把这一条写成 limitation。
  4. viewer 闭源、CUDA 核 license 仅限学术:写明 “non-commercial research only”。企业用 3DGS 做产品有 license 风险,2024 年 Inria 出了商业 license 但要单独谈。

适用

  • 静态场景的实时新视角合成(VR / AR / capture App / 影视 previs)
  • 需要”训练完能编辑光斑”的场景(删一个物体、平移一组、换颜色)
  • 单卡 RTX 3090+ 的训练 / 渲染环境
  • 想学”GPU kernel + 可微分渲染”工程的范本

不适用

  • 动态场景(人物、车辆动)→ 用 4D-GS / Deformable-3DGS
  • 需要 mesh 几何(进 Blender / Unity 做物理 / 碰撞)→ 用 SuGaR 抽 mesh
  • 远离训练视角的外推(视角差很多)→ 没有 implicit prior 的硬伤
  • 移动端 / Web 端实时(官方只支持 NVIDIA desktop,第三方有 SuperSplat 等)
  • 2001 年:Zwicker 等人提出 EWA splatting,用椭圆点投影做体渲染——方向对,但当年没 PyTorch、没 CUDA tile sort
  • 2020 年:Mildenhall 等人 NeRF 横空出世,“用 MLP 当辐射场”成为新视角合成的范式(训练 12 小时,渲染 0.1 FPS)
  • 2022 年:Müller 等人 Instant-NGP 用 hash grid 把训练加速到 5 秒,但渲染仍 ~10 FPS
  • 2023 年 8 月:Kerbl 等四位 Inria 研究者把 EWA 的 splatting 思想 + NeRF 的 α-blending 数学 + 现代 CUDA tile rasterizer 一次拼齐,3DGS 拿 SIGGRAPH Best Paper
  • 2024 年起:4D-GS / SuGaR / Mip-Splatting / DreamGaussian 一年内涌现,3DGS 成为 novel-view synthesis 事实标准
  • explicit 表示在工程上往往赢:当渲染速度 / 可编辑性 / 调试性重要时,explicit(每个原子可见可改)通常值得额外的工程复杂度
  • 可微分一切:把”光栅化”这种传统图形算法做成可微分,就能用梯度下降优化整个 pipeline——是当前”图形 ↔ 学习”融合的核心思路
  • 自适应参数量是元能力:densify-and-prune 思想可以迁移到 mixture-of-experts、dataset curation、model pruning——哪儿梯度大就在哪儿加容量
  • 重参数化是工程刚需Σ = R S Sᵀ Rᵀ 这种”约束自动满足”的技巧,在任何”参数有约束”的优化里都该想到
  • 视频教程:Two Minute Papers — 3D Gaussian Splatting(5 分钟动画讲完核心思想)
  • 项目主页 + 视频 demo:graphdeco-inria/gaussian-splatting(star 17k+,官方训练 / 推理 / viewer 全套)
  • 论文 14 页 PDF:arXiv 2308.04079(v1 = 终版,进 SIGGRAPH 没大改)
  • 修缺陷的姊妹篇:Yu et al. “Mip-Splatting”(CVPR 2024 Best Paper)——把 3DGS 的 zoom 抗锯齿问题修了
  • ddpm —— 同时期的视觉生成代际工作(2D 图像),帮你对比”辐射场 vs 像素”两条线
  • ddpm —— 都是 2020-23 视觉生成代际工作,但 DDPM 是 2D 图像生成,3DGS 是 3D 重建
  • dit —— 同期”用 transformer 做生成”路线;3DGS 走”用图形学原语”路线,对照鲜明
  • stable-diffusion —— DreamGaussian (ICLR 2024) 用 SDS loss 把 stable diffusion 嫁到 3DGS 上做 text-to-3D
  • clip —— 多模态接口的语义先验,被 3DGS 后作(DreamGaussian / GaussianDreamer)反复借用
  • flash-attention —— 同样是”重写底层 GPU kernel 换 10 倍速度”的工程经典,思路并行
  • attention —— transformer 路线的”原子操作”;3DGS 的 Gaussian 是图形学的”原子操作”,对仗