3D Gaussian Splatting 这波热度,从 2023 年 SIGGRAPH 最佳论文一路烧到今天,确实把实时三维重建和渲染的体验往上拉了一大截。但你要是真拿它跑过真实大场景,一定会遇到一个很直观的尴尬:远处大平面、渐变墙面、光滑地面这些“颜色连续变化”的区域,用一堆固定颜色的小高斯去拼,经常拼出斑驳、糊成一片,甚至出现像马赛克一样的颗粒感。最近我读了一篇专门针对这个痛点的论文,标题很直白——SuperGaussians: Enhancing Gaussian Splatting Using Primitives with Spatially Varying Colors。简单说就是:别再让每个高斯基元只带一个单一颜色了,给它一个能在空间上连续变化的颜色函数,让一个基元能表达渐变、反射和复杂光照。这篇笔记就把我对这篇论文的理解、它解决的问题、方法核心,以及我读完之后的一些实战判断全部拆开聊。
这篇内容适合两类人看:一类是正在做三维重建、渲染或者 NeRF/3DGS 相关研究的同学,想快速搞清楚这个方向在干嘛;另一类是把 3DGS 用在工程落地里的朋友,比如做自动驾驶仿真、商品展示、大场景扫描的,你们可能更关心“这玩意儿到底能不能帮我解决画质问题、要不要跟进”。
1. 先把背景讲清楚:为什么3DGS会“边缘锋利、区域模糊”
1.1 从3DGS的基本管线说起
想理解 SuperGaussians,先得把 3D Gaussian Splatting 的底子盘明白。整个场景被表示成一大堆三维高斯分布,每个高斯本质上是一个带模糊边界的“软椭球”,它在空间里有一个中心点,有一个协方差矩阵决定这个椭球的形状和朝向,还有一个不透明度参数决定它对外贡献多少。
渲染的时候,这些三维高斯会被投影到二维图像平面上,变成一个一个的二维高斯斑块,然后按照到相机的距离排序,从远到近做 alpha blending。这一步和传统的体渲染不太一样,它没有沿着光线做积分,而是直接离散地把高分子逐个“泼”到屏幕上,所以速度极快,实时光栅化就能跑。
颜色这一块,原始 3DGS 每个高斯保存的是球谐系数(Spherical Harmonics,SH)。SH 解决的是视角相关问题,也就是说,从不同角度看同一个高斯,颜色会变化。这在表达镜面反射、高光的时候很有用。但注意,SH 是整体作用于这个高斯覆盖的所有空间区域的,它并不管这个高斯内部不同位置之间颜色有没有差异。
1.2 真实场景里我看到的几个通病
我自己拿 3DGS 跑过不少真实场景的数据,包括室外街景和室内房间,问题非常稳定地出现在几个地方。
第一个是大面积渐变表面。比如一面从白到浅蓝慢慢过渡的墙面,或者天空渐变的区域。3DGS 的做法只能用一堆位置相近、颜色稍有不同的高斯去“拼接”出这个渐变来。但如果高斯数量不够,或者密化策略没有在这些区域触发足够多的分裂,那渲染出来就是一块一块的色块,边界还能看到明显的接缝。
第二个问题是高光和反射处容易糊。真实场景里的地板、桌面、车漆表面,颜色随位置变化极快。传统 3DGS 要么堆很多细小高斯去硬顶,要么就是渲染出一片亮斑,缺少那种颜色沿着表面连续流动的感觉。尤其是镜面反射里的环境细节,几乎只能用一堆乱的浮游物去“骗”过去。
第三个问题,也是我在工程里最头疼的,是高频纹理处的浮游物和过拟合。3DGS 为了把一个渐变区域拟合好,往往需要在纹理丰富的地方额外长出许多小高斯,这些小高斯当你换一个视角看时经常穿帮,形成半透明的薄片或飞点。本质上就是因为每个基元的颜色表达能力太弱,场景只能用增加基元数量的方式去补,一补就容易过拟合。
这里有个生活化的类比:3DGS 像是一群手拿纯色小纸片的拼图工人,每人只发一个颜色的纸片,拼一个渐变天空的时候只能靠密密麻麻贴几百张小纸片。而 SuperGaussians 相当于给每个工人发了一支渐变喷枪,一个人就能喷出从深蓝到浅白的连续过度,拼图效率自然不一样。
2. SuperGaussians的核心思路:把单色基元变成“渐变色基元”
2.1 怎么做“空间变化颜色”——核心设计
标题里的 Spatially Varying Colors 翻译过来就是“空间变化的颜色”,核心改动就是把每个高斯原语(Primitive)的颜色从固定值或者全局 SH 改成关于局部空间坐标的函数。
从论文描述的思路来看,作者应该是给每个高斯建立了一个局部坐标系,然后在这个局部空间里定义颜色。你可以理解为:每个高斯基元内部带了一张“迷你贴图”,但这个贴图不是生成好的离散像素,而是一个连续的数学函数。渲染时,屏幕上某一个像素命中了某个高斯,先求出这个命中点在高斯局部坐标系里的坐标,再把坐标代入颜色函数,得到该点对应的颜色,最后参与 alpha blending。
这个颜色函数具体选什么形式,是这篇论文实现层面的关键。从题目和这个方向比较通用的做法推断,最合理的是用低阶多项式或者一系列正交基函数去表示。比如局部坐标是三维的,给它配一组合适的基函数,学习这些基函数的系数,就能近似出任意平滑变化的颜色场。
为什么不直接上神经网络?很简单,渲染速度受不了。3DGS 最大的卖点就是实时,如果每个高斯的每个采样点都要过一个小 MLP,哪怕网络再小,乘加次数也会爆炸。而多项式或基函数的方式就是一次线性组合,计算量几乎可以忽略。这一点我觉得作者选得很聪明,既提升了表达能力,又守住了性能底线。
2.2 渲染与优化的改动
渲染流程大体没变,还是“投影高斯 -> 排序 -> 逐像素混合”,只是中间把常量颜色替换成了函数查询结果。但这里有个细节需要留意:高斯分布是有响应范围的,离中心越远,权重越低,通常超过三倍标准差贡献就几乎为零了。所以颜色函数理论上不需要在整个无限空间都定义得很准,只要在中心附近这个局部区域靠谱就行。这也是为什么用局部坐标做低阶函数表达是合理的,反正远处的影响可以忽略。
训练优化方面的改动也比较直接。颜色函数的系数变成可学习参数,和其他参数一起交给梯度下降优化。反向传播时,梯度不仅流回高斯的位置、协方差和不透明度,还会流回这些颜色系数。密化策略、剪枝策略、不透明度重置这些 3DGS 自带的流程基本都能复用,只需要针对新参数做一点配合调整。
2.3 和SH球谐的区别:别再混淆了
我读这篇论文之前,一度想过一个问题:3DGS 本来就有 SH,为什么要再搞一个空间变化颜色?这是个非常关键的区分点。
SH 解决的是“看的角度不同,颜色不同”,它的输入是观察方向,是一个全局性子。而 SuperGaussians 解决的是“同一视角下,高斯内部不同位置颜色不同”,它的输入是空间位置。这两种可以同时存在,一个管视角动态,一个管空间分布。甚至可以想象把两者叠加:在空间变化颜色的基础上,再叠加一组 SH 系数来拟合视角相关的高光偏移。
如果用一个简单的表格对比,会更清楚:
| 维度 | 传统3DGS的SH | SuperGaussians的空间变化颜色 |
|---|---|---|
| 输入变量 | 观察方向 | 局部空间坐标 |
| 解决什么问题 | 视角相关的高光、反射 | 基元内部的空间颜色渐变 |
| 表达粒度 | 每个高斯整体 | 高斯内部逐点 |
| 计算开销 | 查SH基函数再线性组合 | 类似,低阶基函数线性组合 |
| 能否替代对方 | 不能 | 不能 |
读到这里你应该明白了,SuperGaussians 不是推翻 SH,而是在 SH 之外再补上一层空间维度的表达能力。这在设计上游刃有余,也是它能在很多场景里明显提升画质的原因。
3. 从论文实验看效果:提升在哪里,代价是什么
3.1 作者一般怎么验证这类改进
做三维重建方向的人应该都熟,这类论文的标准动作是在几大公开数据集上跑对比。比如 Mip-NeRF 360、NeRF Synthetic、Tanks and Temples,再加几个自采的复杂场景。评价指标也无非 PSNR、SSIM、LPIPS 这三件套。
从 SuperGaussians 的思路来看,它的优势场景非常明确:大平面、渐变墙、光滑地面、有反射的物体表面。在这些场景下,肉眼提升是相当可观的。传统 3DGS 在这些地方容易出现的色块接缝、渐变断层,SuperGaussians 应该都能明显缓解。而在高频纹理区域,比如树叶、毛发这种乱糟糟的地方,优势可能不那么突出,毕竟这种场景靠的还是基元数量。
我特别想说的是,这类论文不能只看平均指标。平均 PSNR 可能只比 3DGS 高零点几个 dB,但视觉观感可能差一大截。因为渐变区域和高光区域正好是人眼最敏感的地方,一旦修好了,整体观感立刻升级。这是我评估这类工作最看重的点。
3.2 耗时与内存这笔账怎么算
任何对 3DGS 的改进,都不能不顾性能谈效果,否则直接用 NeRF 不就行了?所以我在读的时候特别关心额外的代价。
从方法设计来看,把常量颜色换成空间变化颜色,最直接的变化是每个高斯的参数量增加了。原来一个颜色就是三个浮点数,现在要存一组基函数系数。如果选的是三阶多项式,三维坐标对应的项数大概是几十个,每个通道一组,算下来每个高斯要多出百来个浮点数。单个看不多,但高斯数量动辄几十万甚至上百万,总内存增加是客观存在的。
训练时间方面,多了一次基函数求值和梯度回传,但相比整体优化流程来说,这个增量很小。要知道 3DGS 训练的大头在光栅化和密度化,颜色查询就是一次向量点乘,不至于让训练时间翻倍。渲染阶段就更不用担心了,如果实现得好,帧率影响几乎可以忽略。
这笔账算下来我觉得是划算的:用可控的显存和训练时间增加,换来主观画质,尤其是平滑区域画质的明显提升,对很多场景来说是非常值得的投入。
4. 深度拆解:这个idea背后的“为什么能work”
4.1 高斯响应域与颜色表达的错位
3DGS 其实一直存在一个“表达能力错位”。一个三维高斯在空间里是连续分布的,它有一个实实在在的影响范围,中心响应大、边缘响应小。但颜色却是一个“定值”或者说一个整体参数,等于说高斯的空间连续性和颜色的空间连续性没有对齐。
你可以想象一个很大的红色高斯,它覆盖了一整面墙的左上角区域,但这个区域里墙面颜色实际是从红到暗红渐变。传统 3DGS 里,这个高斯只能贡献一种红色,剩下的渐变只能由其他高斯的叠加来弥补。于是算法唯一的解法就是在这个区域裂出更多小高斯,用数量换细节。
SuperGaussians 的逻辑就是:你已经有一个连续体了,为什么不让它上面的属性也连续变化?把颜色变成位置的函数,等于直接补上了这个错位。
4.2 为什么平面、高光受益最大
平面为什么是重灾区?因为平面在几何上很简单,只需要少量大高斯就能覆盖,但颜色上往往是渐变的。传统方法的困境是:几何覆盖够了,颜色表达不够。这就需要要么把大高斯拆碎,损失效率并引入浮游物,要么忍受颜色断层。
有了空间变化颜色后,一个大高斯就能同时覆盖几何和颜色渐变,减少了高斯基元数量的需求,也降低了过拟合风险。高光区域的逻辑类似,高光其实就是一个颜色突变带,它随着观察角度移动。空间变化颜色配合适当的 SH,能在不增加太多基元的情况下,把这个突变带描述得更自然。
从这个角度说,这篇论文做的是一件“解耦”的事:让几何分辨率由高斯分布负责,让颜色细节由颜色函数负责,两者不再互相拖后腿。
4.3 哪些场景可能翻车
我必须泼一点冷水。空间变化颜色并不是万能的,它有几个潜在翻车点。
第一个是高频几何。如果场景里有很多细小的几何结构,比如树叶缝隙、栏杆、密集植被,颜色函数的高频表达能力可能让优化过程变得更加不稳定。因为几何已经很难拟合了,再给每个基元一个灵活的颜色函数,优化器可能用颜色去“弥补”几何误差,结果就是基元位置乱飞,颜色场变得很怪异。
第二个是缺少正则化。如果颜色函数没有任何平滑约束,理论上它可以产生极高频率的振荡。这会让训练初期非常不稳定,甚至出现大片彩色噪点。所以实际落地时,给颜色函数的系数加一点 L2 正则,或者限制基函数阶数,是非常必要的。
第三个是训练收敛速度。参数变多了以后,如果初始化不好,前几个 epoch 的颜色场会很乱,需要更长的时间才能稳定下来。如果你用的是预训练好的 3DGS 模型来做 warm start,那这个问题不大,但如果从零开始训练,需要有点耐心。
5. 读论文时会踩的坑:复现与理解提示
5.1 阅读时容易被绕晕的概念
这篇论文有一个需要特别注意的名词:Primitives。在 3DGS 语境里,Primitive 指的就是一个高斯基元,但如果你是从 NeRF 那边转过来的,可能会误以为它指的是某种更复杂的几何体。其实不用过度纠结,就理解成“一个高斯分布”就行。
另外就是 Spatially Varying Colors 和 View-dependent Colors 的分工。读论文的时候如果没想清楚这条线,很容易被绕进去:为什么颜色已经可以随空间变化了,还要保留 SH?答案是空间变化只描述“表面颜色”,不描述“反射高光随视角的变化”,这两者物理上本来就是独立的。
还有一个容易忽略的点是“局部坐标”的变换。颜色函数的输入是局部空间的坐标,不是世界坐标。什么意思?每个高斯有自己的中心和朝向,世界坐标要先减去中心、再按协方差的旋转缩放矩阵变换到局部空间。这个变换如果做错了,颜色函数学出来的模式是乱的,渲染必崩。论文里应该会在公式部分详细讲这个变换,建议复现时优先看这里。
5.2 复现时需要调整的训练细节
如果你们团队打算把这套思路集成到自己的代码里,我基于经验给出几个调整优先级。
第一个是颜色基函数的阶数。从二阶或三阶开始比较稳。太低了提升不明显,太高了容易振荡。先跑一个简单场景,比如一个纯色渐变墙,看看肉眼效果能改善到什么程度,再逐步加阶数。第二个是正则化系数。给颜色系数加个很小的 L2 正则,比如 1e-4 量级,尤其是在训练后期,可以明显抑制浮游物。
第三个是密化策略的配合。传统 3DGS 里,如果某个地方的梯度大,就分裂一个高斯。引入空间变化颜色以后,部分“颜色误差”已经被颜色函数吃掉了,所以同等的梯度阈值下,触发密化的时机可能会变晚。这意味着你可能需要把密化阈值适当调低,让高斯基元数量下降百分之二十到三十,仍然保持相同的画质。这个特性其实是优点,但如果你沿用原来的密化参数,内存和显存不会降下来,白白浪费了改进的红利。
第四个是初始化。如果直接从官方 3DGS 的预训练模型继续训练 SuperGaussians,效果通常不错,但如果你从零开始,建议在最开始的迭代里冻结颜色函数的训练,只优化位置和形状,等几何稳定了再放开颜色参数。这一步能救很多训练崩坏的场面。
5.3 我实测中的一些手感与判断
老实说,我还没有把这套方法完整复现完,但类似思路我试验过。之前为了处理一个室内场景的渐变背板,我尝试过一个简化版本:不引颜色基函数,而是给每个高斯额外存一个颜色偏移量,这个偏移量由它附近的局部坐标做插值。效果已经有肉眼可见的提升,蓝紫色的渐变背板不再出现横向带状断层。
所以我对这篇论文的判断是:方向非常正确,工程可行性强,尤其适合用在物体扫描和室内建模这类“规则表面多、颜色渐变丰富”的场景里。反过来,如果你们项目主要处理的是城市场景里大片的树木茂密区域,优先级可以往后放一放,那里最缺的还是几何精度。
另外说一句,如果你现在用的是最新版本的一些开源 3DGS 框架,比如带并行光栅化优化的那种,改造起来会更快。因为核心改动基本集中在颜色属性的存储和查询上,光栅化核心的排序、混合流程都可以不动,工程侵入性很小。
6. 我对这篇论文的总体评价
这篇 SuperGaussians 最让我欣赏的一点,是它在“不改渲染大框架、不牺牲速度”的前提下,切中了 3DGS 在真实场景里一个非常明确的痛点。给基元加上空间变化颜色,听起来是个小改动,但它让高斯表达从“连续几何 + 离散颜色”变成了“连续几何 + 连续颜色”,这个底层逻辑的转变才是真正有价值的。
如果后续要做扩展,我觉得有几个方向值得关注。一是把空间变化颜色和正则化场景建模结合起来,进一步提高基元效率,让高斯数量进一步下降。二是把它用到表面重建、纹理烘焙这些下游任务上,因为颜色函数是一种连续的解析表达,比离散属性更适合做 UV 空间的纹理提取。三是跟 LOD 和流式传输结合,基元数量降下来之后,大场景的加载和传输压力也会小很多。
从一个从业者的角度看,这篇论文值得花一个下午仔细读一遍。它不搞花哨的注意力模块,也不堆参数量,就是老老实实把基元的颜色表达能力补齐。这种简单直接的思路,放到工程里往往比那些复杂结构更耐用。评分的话,我会给方法设计满分,给实验覆盖度四星半,唯一扣掉的半星是希望看到更多关于训练稳定性和退化场景的分析。