开始 3D 高斯渲染
相比于之前的点云光栅化,3DGS 有些不一样。我们的基本单位不再是没有体积的“点”,而是带有范围和透明度的“高斯球”。
在之前的点云渲染中,我们主要依赖两个参数:位置(Position)和颜色(Color)。
但在 3DGS 中,除了相机坐标系下的坐标
- Color (颜色)
- Opacity (透明度):控制这个高斯球是实心的还是半透明的。
- Sigma (
\Sigma , 协方差矩阵):决定了高斯球的形状和大小。
代码实现
我们要实现函数 gaussian_rasterization。
- def gaussian_rasterization(pos, colors, opacity_raw, height, width, fx, fy, cx, cy, camera2world, near=2e-3, far=100, pixelGuard=64)
第一步,我们需要将三维空间中的高斯球投影到二维屏幕上,得到它们的 UV 坐标。
- # 1. 投影 3D 点到 2D 屏幕坐标
- uv, x_cam, y_cam, z_cam = project_points(pos, height, width, fx, fy, cx, cy, camera2world)
- u = uv[:, 0]
- v = uv[:, 1]
接着我们引入视锥剔除。在计算机图形学中,渲染那些根本不在屏幕视野内的物体是极度浪费算力的。如果我们用 3DGS 建模了一栋巨大的豪宅,当前可能只看到了 10% 的区域。直接丢弃剩下 90% 不在屏幕内的点,这就是我们提升渲染性能的法宝。
对于普通的点云,如果一个点越过了屏幕边界,我们可以直接忽略它。但是,高斯球是有体积的。即使高斯球的中心点(均值)在图像边界之外,它庞大的“身躯”(方差范围)依然可能会覆盖到屏幕边缘的像素,对画面产生贡献。
为了解决这个问题,我们引入了一个非常关键的超参数 pixelGuard。
我们默认设定 pixelGuard = 64。这意味着我们在图像的四周额外拉起了一道 64 像素的缓冲区。只要高斯的中心落在这个带状区域内,我们就保留它。
- # 2. 软边缘视锥剔除 (pixelGuard): 在图像边缘扩展 pixelGuard 像素的保护带
- mask = (u > -pixelGuard) & (u < width + pixelGuard) & \
- (v > -pixelGuard) & (v < height + pixelGuard) & \
- (z_cam > near) & (z_cam < far)
- # 3. 过滤出有效的高斯点
- u_v = u[mask]
- v_v = v[mask]
- colors_v = colors[mask]
- opacity_raw_v = opacity_raw[mask]
现在,我们拿到了在屏幕范围内的高斯球的原始透明度 opacity_raw_v。
在深度学习和梯度下降优化中,参数 opacity_raw 的取值范围是负无穷到正无穷 (
我们需要对其进行重参数化(Reparameterization)。
- # 4. 透明度重参数化 (Sigmoid & Clamp 到 0.999 避免梯度消失)
- opacity_v = torch.sigmoid(opacity_raw_v)
- opacity_v = torch.clamp(opacity_v, min=0.0, max=0.999)