
1. 从NeRF到3DGS一场渲染效率的降维打击如果你这两年一直在关注三维重建或者神经渲染方向大概率已经被两个词反复刷屏NeRF和3D Gaussian Splatting后面我统一叫3DGS。NeRF刚出来那会儿整个圈子都沸腾了用几张贴图就能重建出带光照、带视角依赖的复杂场景效果确实惊艳。但真正上手跑过的人都知道NeRF的训练和渲染速度是个硬伤——训练一个场景动辄几个小时甚至一两天渲染一帧也要好几秒想拿来做实时交互基本是做梦。3DGS在2023年SIGGRAPH上横空出世直接把这个问题按在地上摩擦。它用一组三维高斯椭球来显式表达场景配合基于瓦片的光栅化渲染管线在保持甚至超越NeRF画质的前提下把训练时间压缩到几分钟渲染速度拉到100 FPS以上。这个跨度不是优化是换了一条赛道。我写这篇东西是想把3DGS到底解决了什么问题讲透。不是那种论文摘要式的复述而是从实际做项目、跑代码、调参数的角度把它的核心思路、关键设计、实操要点和踩坑经验都摊开来说。如果你正在做三维重建、SLAM建图、数字孪生或者单纯想搞清楚3DGS凭什么这么火这篇应该能帮你省下不少翻文档的时间。2. 3DGS到底解决了哪些核心痛点2.1 NeRF的三大瓶颈慢、隐式、难编辑要理解3DGS的价值得先看清楚NeRF的局限。NeRF的核心思路是用一个多层感知机MLP把空间坐标和视角方向映射到颜色和密度然后通过体渲染积分得到像素值。这个设计很优雅但问题也很明显。第一是训练慢。因为每条光线要采样几十上百个点每个点都要过一遍MLP计算量巨大。原始NeRF在单卡上训练一个场景要一到两天就算后续的Instant-NGP用哈希编码把训练压到几分钟渲染质量又会有波动而且对显存的占用依然不友好。第二是隐式表达。场景信息全部藏在MLP的权重里你没法直接拿到“这个物体在哪里”“那个表面长什么样”。想对场景做编辑、分割、物理仿真都得绕一大圈。做SLAM的时候你想把建图和定位耦合起来隐式表达会让优化变得非常别扭。第三是渲染和训练耦合。NeRF的渲染过程本身就是网络前向传播想加速就得改网络结构或者做烘焙灵活性差。而且体渲染的采样策略对结果影响很大调参成本高。2.2 3DGS的核心突破显式表达加可微光栅化3DGS换了个思路。它不再用隐式网络而是用一堆三维高斯椭球来显式表示场景。每个高斯有自己的位置、协方差矩阵决定形状和朝向、不透明度以及用球谐函数表示的颜色。渲染的时候把这些高斯投影到屏幕空间按深度排序然后用alpha混合的方式合成像素。这个设计直接解决了NeRF的几个痛点训练快没有MLP前向传播梯度可以直接传到每个高斯的参数上优化效率高得多。官方代码在A6000上训练一个场景大概几分钟到十几分钟。渲染快基于瓦片的光栅化管线充分利用GPU并行能力轻松跑到实时帧率。显式可编辑每个高斯都是独立的图元你可以删、可以改、可以加做场景编辑和下游任务方便很多。表达能力强高斯椭球可以自适应地拉伸、旋转对薄结构、高频细节的拟合能力比点云强不少。注意3DGS不是万能的。它对反光、透明、镜面反射这类材质的处理仍然有局限因为球谐函数只能表达视角依赖的颜色没法真正模拟光线传输。这是它和NeRF共同的短板也是后续很多工作的改进方向。2.3 和SLAM、CUDA生态的关系热词里出现了SLAM、CUDA这些词说明很多人关心3DGS在机器人和工程落地中的位置。简单说3DGS给SLAM提供了一种新的建图表达方式。传统SLAM用点云或体素建图稠密度和渲染质量有限3DGS可以在线增量式地构建高质量地图同时支持新视角合成。像SplaTAM、Gaussian-SLAM这些工作就是往这个方向走的。CUDA则是绕不开的底层依赖。3DGS的光栅化器是用CUDA写的训练和渲染都依赖GPU。你装环境的时候CUDA版本、PyTorch版本、显卡架构三者必须匹配否则轻则报错重则编译失败。后面我会专门讲这块的坑。3. 核心原理拆解高斯椭球是怎么工作的3.1 三维高斯分布的数学表达一个三维高斯分布由均值向量和协方差矩阵定义。在3DGS里均值就是高斯中心的位置协方差矩阵控制它的形状和朝向。为了保证协方差矩阵始终是半正定的论文把它分解成旋转矩阵和缩放矩阵的乘积Σ R S S^T R^T。旋转用四元数表示缩放用三个轴的长度表示。这样优化的时候不会出现非法矩阵。这个分解很关键。你直接优化协方差矩阵的六个元素很容易优化出非正定的矩阵导致渲染出错。拆成旋转和缩放之后每个参数都有明确的物理意义梯度下降也更稳定。3.2 从三维到二维的投影渲染的时候每个高斯要从世界坐标投影到相机坐标再投影到屏幕空间。投影后的二维协方差矩阵可以用雅可比矩阵做近似计算。这里有个细节投影后的高斯在屏幕空间也是一个椭圆光栅化器会计算每个像素被这个椭圆覆盖的程度然后做alpha混合。3.3 自适应密度控制3DGS训练过程中会动态调整高斯的数量和分布。具体来说每隔一定迭代次数它会检查每个高斯的梯度大小和位置。梯度大的高斯说明该区域重建不足需要分裂成两个更小的高斯梯度小但体积大的高斯说明该区域过表达需要克隆或者删除。这个机制让高斯分布能自适应地贴合场景几何既保证细节又控制数量。3.4 球谐函数与视角依赖颜色每个高斯用球谐函数系数来表示颜色。球谐函数是一组定义在球面上的基函数阶数越高能表达的视角依赖越复杂。3DGS默认用三阶球谐每个颜色通道16个系数总共48个系数。这样从不同角度看同一个高斯颜色会变化能模拟一定的镜面反射和高光效果。实操心得如果你的场景主要是漫反射材质可以把球谐阶数降到0阶或1阶能显著减少参数量和显存占用训练也更快。我试过在室内场景用0阶球谐画质损失很小但显存省了将近三分之一。4. 实操环境搭建CUDA、PyTorch与依赖的版本博弈4.1 显卡、驱动、CUDA版本的匹配逻辑3DGS对CUDA版本很敏感。官方代码要求CUDA 11.6以上但不同版本的PyTorch对CUDA的支持范围不同。你得先确定显卡型号再查它支持的CUDA版本然后选对应的PyTorch最后装匹配的CUDA Toolkit。举个例子RTX 4060 Ti是Ada Lovelace架构计算能力8.9需要CUDA 11.8以上才能充分发挥。如果你装的是CUDA 11.6可能能跑但性能打折甚至编译报错。RTX 50系显卡比如5070是Blackwell架构计算能力sm_120需要CUDA 12.8以上老版本的PyTorch根本不支持。我整理了一个常见显卡和CUDA版本的对应关系供你参考显卡系列架构计算能力最低CUDA版本推荐CUDA版本RTX 20系Turing7.510.011.8RTX 30系Ampere8.611.111.8 / 12.1RTX 40系Ada Lovelace8.911.812.1 / 12.4RTX 50系Blackwell12.012.812.84.2 用conda隔离环境的具体步骤我强烈建议用conda建独立环境别在系统Python里瞎折腾。步骤如下conda create -n gs python3.10 conda activate gs然后装PyTorch。注意要去PyTorch官网查对应的CUDA版本命令别直接pip install torch那样装的是CPU版或者不匹配的版本。比如CUDA 12.1对应的命令是pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121接着装3DGS的依赖pip install plyfile tqdm pip install submodules/diff-gaussian-rasterization pip install submodules/simple-knn这两个submodule是3DGS的核心CUDA扩展编译的时候会调用nvcc。如果报错说找不到cuda.h说明CUDA Toolkit没装或者环境变量没配好。4.3 编译CUDA扩展时的常见报错与解决最常见的报错是“nvcc not found”或者“CUDA_HOME not set”。解决办法是确认CUDA Toolkit装好了然后把路径加到环境变量export CUDA_HOME/usr/local/cuda-12.1 export PATH$CUDA_HOME/bin:$PATH export LD_LIBRARY_PATH$CUDA_HOME/lib64:$LD_LIBRARY_PATH另一个坑是gcc版本。CUDA 12.1最高支持gcc 12如果你系统gcc是13编译会报错。可以用conda装一个低版本gccconda install -c conda-forge gcc12 gxx12注意如果你在WSL2里跑3DGS记得装WSL专用的NVIDIA驱动不是在WSL里装Linux驱动。CUDA Toolkit可以在WSL里装但驱动必须用Windows端的。这个搞反了会一直报“no CUDA-capable device detected”。5. 数据准备与训练流程从拍照到出模型5.1 自己制作数据集的完整流程3DGS需要的是多视角图像加相机位姿。位姿可以用COLMAP做SfM得到。流程如下拍摄围绕物体或场景拍一圈重叠度至少60%光照尽量均匀避免运动模糊。COLMAP重建用COLMAP做稀疏重建得到相机内参、外参和稀疏点云。格式转换3DGS官方代码需要特定目录结构包括images文件夹和sparse/0文件夹下的COLMAP输出。训练运行train.py指定数据路径和输出路径。拍摄的时候有个经验别用广角镜头凑太近边缘畸变会让COLMAP匹配失败。我一般用50mm等效焦距光圈f/8左右保证景深足够。如果场景纹理少比如白墙可以贴一些临时标记点辅助匹配。5.2 训练参数的关键配置3DGS的训练脚本有一堆参数我挑几个最影响结果的讲iterations默认30000。一般场景够了复杂场景可以加到40000。position_lr_init位置学习率初始值默认0.00016。调大收敛快但容易震荡。densify_until_iter控制密度增长到多少迭代停止默认15000。太早停会导致细节不足。densify_grad_threshold梯度阈值默认0.0002。调小会增加高斯数量画质提升但显存吃紧。我一般先用默认参数跑一遍看结果再针对性调。如果发现某些区域糊就降低densify_grad_threshold如果高斯数量爆炸就提高阈值或者提前停止密度增长。5.3 训练过程中的显存监控与优化3DGS训练时显存占用会随着高斯数量增长而上升。一个中等场景大概需要8到12GB显存复杂场景可能超过24GB。如果显存不够可以降低图像分辨率用-r 2参数下采样减少球谐阶数提高densify_grad_threshold控制高斯数量用更小的batch但3DGS本身是全图训练的这个不太好调实操心得训练过程中可以用nvidia-smi -l 1实时监控显存。如果发现显存快满了赶紧中断调参数重跑别等OOM了再后悔。我有一次跑一个室外大场景没注意显存跑到两万迭代崩了白等一个小时。6. 常见问题与排查技巧实录6.1 编译与运行时报错速查报错信息可能原因解决办法nvcc not foundCUDA Toolkit未安装或PATH未配置安装CUDA Toolkit并配置环境变量CUDA_HOME not set环境变量缺失export CUDA_HOME/usr/local/cuda-xxno kernel image available显卡计算能力与编译架构不匹配设置TORCH_CUDA_ARCH_LIST或升级CUDAout of memory显存不足降低分辨率、减少高斯数量、换更大显存显卡COLMAP failed to match图像重叠度低或纹理少重拍、增加重叠、贴标记点渲染结果有漂浮物高斯未收敛或密度控制不当增加训练迭代、调整密度阈值6.2 画质问题的排查思路如果训练出来的模型有雾状漂浮物通常是背景高斯没被正确约束。可以检查一下训练数据里有没有拍到纯天空或纯背景这些区域容易产生大量低不透明度的高斯。解决办法是在数据准备阶段把背景裁掉或者训练时加一个背景正则项。如果模型边缘有锯齿可能是球谐阶数不够或者高斯数量不足。试着提高球谐阶数到3阶或者降低densify_grad_threshold让更多高斯生成。如果某些视角渲染出来模糊检查COLMAP的位姿是否准确。位姿误差会直接导致渲染错位。可以用COLMAP的model_analyzer看重投影误差一般要控制在1像素以内。6.3 跨版本CUDA迁移的注意事项有时候你在一台机器上编译好了换一台机器跑CUDA版本不同就得重新编译。因为diff-gaussian-rasterization是编译成.so文件的和CUDA版本绑定。迁移的时候把整个conda环境打包带走不一定管用最好在新机器上重新建环境、重新编译。如果非要用同一个环境跨机器确保两台机器的CUDA版本、驱动版本、显卡架构一致。否则就老老实实重装。7. 3DGS在SLAM和机器人方向的落地思考SLAM方向对3DGS的兴趣主要在于建图质量。传统视觉SLAM建出来的是稀疏点云做导航够用但做渲染和交互就差远了。3DGS可以在线构建稠密的高质量地图同时支持新视角合成这对AR/VR、机器人仿真很有价值。不过目前3DGS做SLAM还有几个挑战。一是训练速度虽然比NeRF快但要做到实时增量式建图还是有压力。二是位姿优化和地图优化的耦合需要仔细设计不然容易漂移。三是显存占用大嵌入式平台跑不动。我个人的判断是3DGS在SLAM里的落地会先从离线建图和后处理开始逐步往在线方向走。短期内用3DGS做地图的精细重建和可视化用传统SLAM做定位是比较务实的方案。最后分享一个小技巧如果你只是想快速体验3DGS的效果不想自己拍数据可以用官方提供的预训练模型或者公开数据集比如Mip-NeRF 360。跑通流程之后再换自己的数据能省很多调试时间。另外训练的时候记得开--eval模式这样会留出测试集方便你客观评估画质而不是只靠肉眼看。