外观
9.3 神经辐射场 (NeRF) 与三维高斯泼溅 (3DGS)
在前面的章节中,我们学习了如何通过相机几何投影与 BEV 栅格化将多视角图像转化为离散的特征网格。然而,物理世界中的真实物体往往拥有极其细腻的微观几何结构(如毛发、树叶、反光金属与透明玻璃)。如果仅用粗糙的立方体体素来描述世界,分辨率将严重受限,且无法呈现物体随视角变化而产生的逼真高光反光。
2020 年,加州大学伯克利分校的 Ben Mildenhall、Matthew Tancik 等人提出了震撼计算机视觉界的 神经辐射场(Neural Radiance Fields, NeRF)。NeRF 放弃了显式的多边形网格或体素,将整个连续三维空间压缩为一个全连接神经网络,开创了隐式可微体渲染的新纪元。
2023 年,INRIA 与蔚蓝海岸大学的 Bernhard Kerbl 等人进一步推出了 三维高斯泼溅(3D Gaussian Splatting, 3DGS)。3DGS 结合了显式三维高斯椭球基元与硬件级 GPU 瓦片光栅化,在维持照片级渲染质量的同时,将渲染帧率直接拉升到了惊人的

图 9.3-1:NeRF 用稀疏输入视角拟合连续辐射场,再从未见相机位姿合成新视角。 出处:NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis,Ben Mildenhall et al.,2020。
9.3.1 物理与光学基石:体积辐射传输与新视角合成演进
要理解辐射场与高斯渲染的数学内核,我们首先需要从经典大气光学中的光线体积传输物理定律讲起。
1. 经典物理中的光线衰减与微积分体渲染
想象一束清晨的太阳光穿过充满薄雾的森林:
- 光线在空气中直线传播时,每穿过一小段微元微小的距离
,就会有一部分光子被空气中的微小水滴粒子吸收或散射(这一性质在物理学中被称为体积不透明度 / 体积消光系数 ,单位为 ); - 与此同时,悬浮在空中的发光微粒自身也在向周围辐射出色彩光芒(称为辐射发光度
)。
当一束光线最终穿过薄雾射入我们的眼睛时,视网膜接收到的总颜色,正是光线上所有微元发射出的光芒,沿着传播路径经历层层衰减后累加积攒的积分总和!

图 9.3-2:沿射线从近到远,每个样本的颜色权重由此前透射率连乘与本点不透明度共同决定。
2. 从隐式连续函数到显式高斯基元的演进
- NeRF(连续隐式场):用一个神经网络输入空间坐标
与观察角度 ,输出该点的密度 与 RGB 颜色 。渲染时必须沿光线密集采样数百个点执行多次网络推理,计算开销巨大(单帧渲染耗时数秒); - 3DGS(显式各向异性高斯球):将连续空间离散化为数百万个可自由拉伸、旋转、半透明的三维高斯椭球(3D Gaussians)。通过将三维椭球直接“泼溅(Splatting)”投影到二维屏幕上,利用 GPU 硬件并行排序完成极速合成。

图 9.3-3:Instant-NGP 用多分辨率哈希编码显著缩短 NeRF 等神经图形基元的训练时间,并展示不同训练时长的输出质量。 出处:Instant Neural Graphics Primitives with a Multiresolution Hash Encoding,Thomas Müller et al.,2022。
9.3.2 核心数学推导一:NeRF 体积渲染积分与离散数值求积
设从相机光心

图 9.3-4:NeRF 的方法图串联相机射线采样、位置与方向编码、MLP 查询以及体渲染积分。 出处:NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis,Ben Mildenhall et al.,2020。
1. 连续辐射传输方程
根据比尔-朗伯定律(Beer-Lambert Law),光线从起点
相机光心最终接收到的期望色彩值
2. 离散数值求积公式(Numerical Quadrature)
由于神经网络无法直接求解连续解析积分,我们在射线区间
连续积分被离散化为极其优美的初等代数求和公式:
其中:
- 第
点的不透明度(Opacity): ; - 到达第
点的累积透射率: 。
初等代数直觉: 观察权重因子
: 描述了“光线能够活着穿过前面 层障碍物的概率”; 描述了“光线恰好在第 个采样点被拦截并显色的概率”。 这一前向累乘求和过程,完全等价于图形学中经典的前后 Alpha 图像透明度混合!
手算代入算例: 设射线上仅采样 2 个点,步长
- 第 1 点:密度
( ),发射红色 ; - 第 2 点:密度
(极度不透明, ),发射蓝色 。
- 计算第 1 点:
- 透射率:
(前面没有任何遮挡); - 不透明度:
; - 颜色贡献权重:
;
- 透射率:
- 计算第 2 点:
- 透射率:
; - 不透明度:
; - 颜色贡献权重:
;
- 透射率:
- 合成最终像素颜色:
结果合成出了一半红一半蓝的紫色!整个过程没有任何微积分难题,全部是清晰明了的初等代数代入。
深入推导:比尔-朗伯微分衰减模型与体积渲染积分变分严格推导(点击展开查看完整推导)
设光线沿射线
这是一阶非齐次线性常微分方程。求解对应齐次方程可得积分因子即累积透射率:
利用常数变易法代入边界条件
该公式确立了体渲染模型的物理严密性。
9.3.3 核心数学推导二:3DGS 各向异性高斯球与屏幕投影
3DGS 将空间表征为成百上千个三维高斯椭球。

图 9.3-5:3DGS 从稀疏 SfM 点初始化三维高斯,交替优化与密度控制,再通过可微光栅化生成图像。 出处:3D Gaussian Splatting for Real-Time Radiance Field Rendering,Bernhard Kerbl et al.,2023。
1. 三维高斯概率分布与各向异性协方差矩阵
一个三维高斯椭球以空间均值中心
为了保证协方差矩阵
2. 投影到 2D 屏幕上的 2D 协方差矩阵
根据 Zwicker 等人(2001)的 EWA 表面泼溅理论,三维高斯球经透视投影变换
在二维像素平面上,所有落入视锥的高斯椭球被切分为
深入推导:局部射影投影雅可比矩阵 $\mathbf{J}$ 与 EWA 椭球重采样证明(点击展开查看完整推导)
设相机坐标系下高斯中心为
根据多维随机变量线性变换协方差性质
9.3.4 纯底层 PyTorch 代码实现:体渲染数值积分器与 3D 高斯投影引擎
下面我们使用纯底层 PyTorch 算子实现 NeRF 离散体渲染数值求积引擎与 3D 高斯椭球的 2D 投影协方差求解器。
python
import torch
import torch.nn as nn
import torch.nn.functional as F
class VolumeRenderingIntegrator:
"""
NeRF 离散体渲染积分求积引擎
实现射线上离散采样的累积透射率与颜色合成
"""
@staticmethod
def render_rays(sigmas: torch.Tensor, colors: torch.Tensor, deltas: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
"""
:param sigmas: (B, N_samples) 采样点体积密度
:param colors: (B, N_samples, 3) 采样点 RGB 颜色
:param deltas: (B, N_samples) 相邻采样点步长
:return: (rendered_colors, accumulated_weights)
"""
# 1. 计算单点不透明度 alpha_i = 1 - exp(-sigma_i * delta_i)
densities = sigmas * deltas
alphas = 1.0 - torch.exp(-densities) # (B, N_samples)
# 2. 计算累积透射率 T_i = prod(1 - alpha_j)
# 为防止数值下溢,在 log 空间中累加: T_i = exp(-cumsum(sigma * delta))
cum_densities = torch.cumsum(densities, dim=-1)
# 在序列前端补 0: T_1 = exp(0) = 1.0
cum_densities_shifted = F.pad(cum_densities[..., :-1], (1, 0), value=0.0)
transmittance = torch.exp(-cum_densities_shifted) # (B, N_samples)
# 3. 颜色权重 w_i = T_i * alpha_i
weights = transmittance * alphas # (B, N_samples)
# 4. 沿射线求和合成色彩: (B, N_samples, 1) * (B, N_samples, 3) -> (B, 3)
rendered_colors = (weights.unsqueeze(-1) * colors).sum(dim=1)
return rendered_colors, weights
class Gaussian3DProjector:
"""
3D 高斯泼溅 (3DGS) 屏幕空间 2D 协方差投影引擎
"""
@staticmethod
def project_covariances(
scales: torch.Tensor,
rotations: torch.Tensor,
camera_pts: torch.Tensor,
f_x: float,
f_y: float
) -> torch.Tensor:
"""
:param scales: (N, 3) 三维缩放因子 (s_x, s_y, s_z)
:param rotations: (N, 3, 3) 三维旋转矩阵 R
:param camera_pts: (N, 3) 相机坐标系下的中心点 (t_x, t_y, t_z)
:return: (N, 2, 2) 投影到屏幕的 2D 协方差矩阵 Sigma'
"""
N = scales.size(0)
# 1. 重构 3D 协方差矩阵 Sigma = R * S * S^T * R^T
s_mat = torch.diag_embed(scales) # (N, 3, 3)
m_mat = torch.bmm(rotations, s_mat) # (N, 3, 3)
sigma_3d = torch.bmm(m_mat, m_mat.transpose(1, 2)) # (N, 3, 3)
# 2. 计算射影雅可比矩阵 J
tx = camera_pts[:, 0]
ty = camera_pts[:, 1]
tz = camera_pts[:, 2].clamp_min(1e-4)
j_mat = torch.zeros(N, 2, 3, device=scales.device)
j_mat[:, 0, 0] = f_x / tz
j_mat[:, 0, 2] = -(f_x * tx) / (tz ** 2)
j_mat[:, 1, 1] = f_y / tz
j_mat[:, 1, 2] = -(f_y * ty) / (tz ** 2)
# 3. 屏幕投影 Sigma' = J * Sigma_3D * J^T
sigma_2d = torch.bmm(torch.bmm(j_mat, sigma_3d), j_mat.transpose(1, 2)) # (N, 2, 2)
# 4. 补偿抗锯齿低通滤波
sigma_2d[:, 0, 0] += 0.3
sigma_2d[:, 1, 1] += 0.3
return sigma_2d
# ===================================================================
# 单元测试与手算算例精确校验
# ===================================================================
if __name__ == "__main__":
# 1. 测试 NeRF 体渲染积分器 (验证正文中的双点紫色手算算例)
batch_rays = 1
num_pts = 2
test_sigmas = torch.tensor([[0.693147, 10.0]])
test_colors = torch.tensor([[[1.0, 0.0, 0.0], [0.0, 0.0, 1.0]]])
test_deltas = torch.tensor([[1.0, 1.0]])
rendered_rgb, pt_weights = VolumeRenderingIntegrator.render_rays(
test_sigmas, test_colors, test_deltas
)
r_val, g_val, b_val = rendered_rgb[0].tolist()
print(f"[NeRF Test] 渲染色彩输出: ({r_val:.3f}, {g_val:.3f}, {b_val:.3f}), 期望: (0.500, 0.000, 0.500)")
print(f"[NeRF Test] 采样点权重分量: {pt_weights[0].tolist()}")
assert abs(r_val - 0.5) < 1e-3 and abs(b_val - 0.5) < 1e-3, "体渲染手算代入校验失败!"
# 2. 测试 3D 高斯屏幕投影引擎
num_gaussians = 3
dummy_scales = torch.tensor([[0.1, 0.1, 0.1]] * num_gaussians)
dummy_rot = torch.eye(3).unsqueeze(0).expand(num_gaussians, -1, -1)
dummy_cam_pts = torch.tensor([[0.0, 0.0, 2.0], [1.0, -0.5, 4.0], [-2.0, 1.0, 5.0]])
sigma_2d_out = Gaussian3DProjector.project_covariances(
dummy_scales, dummy_rot, dummy_cam_pts, f_x=1000.0, f_y=1000.0
)
print(f"[3DGS Test] 2D 屏幕投影协方差形状: {sigma_2d_out.shape}")
assert sigma_2d_out.shape == (num_gaussians, 2, 2), "2D 协方差矩阵维度不符!"
assert (sigma_2d_out[:, 0, 0] > 0).all() and (sigma_2d_out[:, 1, 1] > 0).all(), "协方差对角线方差非正!"
print("✓ NeRF 体积渲染数值求积与 3DGS 屏幕投影引擎单测全部通过!")9.3.5 本节小结
回顾本节内容,我们建立了三维神经辐射场与高斯渲染的完整物理与数学图谱:
- 体积辐射传输方程:光线沿射线的能量积分与累积透射率
揭示了透明介质与半透明遮挡的本质; - NeRF 的连续隐式革命:以神经网络拟合连续场,通过分层离散数值求积实现了照片级新视角合成;
- 3DGS 的显式实时突破:利用各向异性三维高斯椭球分解
与屏幕射影雅可比投影,将高保真渲染推向百帧实时新时代。

