分块优化:包围盒与 Tile 划分

在 3D 图形学和高斯溅射(Gaussian Splatting)中,为了提高渲染和计算的效率,我们需要将连续的像素空间离散化。这篇文章的核心,就是带你搞懂如何为每一个高斯(Gaussian)计算包围盒,并将其映射到屏幕的网格(Tile)中。


从像素空间跨入 Tile(瓦片)空间

现在,我们手头已经有了高斯在像素空间(Pixel Space)下的边界坐标(比如 u_{min}, u_{max}, v_{min}, v_{max})。为了并行计算,我们需要把屏幕划分成一个个的小网格,我们称之为 Tile(瓦片)。

如何将像素坐标转换为 Tile 索引?代码非常直观:

  1. # 从像素坐标转换到 Tile 索引并转换为 int64
  2. u_min_tile = (u_min / tile_size).to(torch.int64)
  3. u_max_tile = (u_max / tile_size).to(torch.int64)
  4. v_min_tile = (v_min / tile_size).to(torch.int64)
  5. v_max_tile = (v_max / tile_size).to(torch.int64)

计算每个高斯相交的 Tile 数量

知道了每个高斯起点和终点所在的 Tile 索引后,我们需要计算这个高斯到底跨越了几个 Tile。

  1. # 计算每个高斯在水平(u)和垂直(v)方向跨越的 Tile 数量 (+1 避免 Fencepost 误差)
  2. n_u = u_max_tile - u_min_tile + 1
  3. n_v = v_max_tile - v_min_tile + 1

获取全局最大跨度

为了后续能够在显存中分配合适大小的数据结构,我们需要知道在所有的被渲染的高斯中,单个高斯最多能跨越多少个 Tile。

  1. # 获取全局单个高斯跨越的最大 Tile 数 (用于统计或后续阶段验证)
  2. nu_max_item = int(n_u.max().item())
  3. nv_max_item = int(n_v.max().item())