理解 Voxel Space:定义 90 年代初期地形的 2.5D 引擎

在 1990 年代初期,3D 游戏的格局与今天截然不同。CPU 的速度比现在慢了几个数量级,而且对于普通消费者来说,GPU 加速的概念几乎不存在。那个时代的多数 3D 游戏依赖于渲染单色的填充多边形——这个过程计算量巨大,且视觉效果往往非常简单。

在这种环境下,NovaLogic 在 1992 年发布了 Comanche。这款游戏拥有令人惊叹的地形,其纹理、阴影和着色效果似乎领先了时代多年。这得益于一种被称为 Voxel Space 的技术,这是一种 2.5D 渲染方法,弥补了传统 2D 精灵(sprites)与全 3D 多边形环境之间的鸿沟。

核心概念:高度图与颜色图

与使用复杂网格和着色器的现代 3D 引擎不同,Voxel Space 依赖于两个主要的数据结构:高度图(height map)和颜色图(color map)。

  • 高度图: 一个 2D 网格,其中每个值代表该特定坐标处地形的高度。在 Comanche 中,这通常是一个 1024x1024 的单字节映射图。
  • 颜色图: 一个对应的 2D 网格,用于存储地形的颜色。

这种方法最巧妙的设计之一在于,颜色图通常包含“预烘焙”的阴影和着色。正如社区成员所指出的,这创造了一种 3D 斜角效果,而无需引擎实时计算光照,从而显著降低了 CPU 负载。

然而,这种系统有一个根本性的局限:它每个位置只允许一个高度值。这意味着虽然山脉和山谷很容易表示,但像悬崖、建筑物或树木等复杂的几何形状无法使用这种特定方法进行渲染。

渲染算法的工作原理

Voxel Space 引擎的工作原理类似于光线投射(ray casting)。它不是计算三角形,而是对高度图和颜色图进行光栅化,并在屏幕上绘制垂直线。

基本过程

  1. 清除屏幕: 重置帧。
  2. 画家算法: 为了确保正确的遮挡关系(即较近的对象遮挡较远的对象),引擎传统上从场景的后方向前方进行渲染。
  3. 透视投影: 引擎确定地图上的哪条线对应于观察者的距离,并考虑视野(FOV)以使物体在远离时显得更小。
  4. 垂直线绘制: 对于线的每一段,引擎从映射图中检索高度和颜色,并在屏幕上根据投影高度绘制一条垂直线。

添加旋转

为了允许玩家向非北方方向观察,引擎会对坐标应用三角函数旋转。通过计算观察角度($\phi$)的 sincos,引擎可以确定采样高度图的正确段,无论摄像机如何转向。

性能优化

由于这些引擎运行在受限的硬件(如 80286 CPU)上,开发者必须采用几种巧妙的技巧来维持可玩的帧率。

从前向后渲染与 Y-Buffer

虽然基本算法使用画家算法(从后向前),但一种更高效的方法是从前向后进行渲染。这可以消除绘制那些最终会被较近地形覆盖的像素的需求。为了防止视觉错误,使用了一个 Y-buffer 来存储每个列绘制的最高 Y 位置。如果新线的高度没有之前在该列绘制的线更高,它就会被丢弃。

细节级别(LOD)

为了进一步节省周期,引擎可以实现距离($z$)的可变步长。通过随着距离摄像机的距离增加而增加步长,引擎在远处渲染较少的细节,同时在前景保持高精度。

历史背景与技术辩论

Voxel Space 的遗产是一个充满怀旧感和技术好奇心的课题。一些开发者回忆起使用查找表来避免缓慢的浮点数乘法,从而从 16MHz 处理器中“压榨出最后一滴性能”的巨大满足感。

然而,在技术术语的使用上存在细微差别。正如一位贡献者所指出的:

从技术上讲,这与 voxels(“体素”,即在所有三个轴上均匀分割 3D 空间)无关。这只是一个高度图,一组棱柱……并不完全不同于 Doom 地图。

尽管存在术语辩论,但该技术的影响是不可磨灭的。有趣的是,据报道,Comanche 的开发受到了程序员在医疗行业经验的影响,特别是 CT 和 MRI 扫描,这些技术利用了真正的体素数据。

Voxel Space 方法总结

特性 Voxel Space (2.5D) Modern 3D (Polygonal)
数据源 高度/颜色图 顶点网格/纹理
渲染方式 垂直线投射 三角形光栅化
光照 在颜色图中预烘焙 实时着色器/光线追踪
复杂度 $O(Distance imes Width)$ $O(Polygons)$
约束 每个 X,Y 处单一高度 任意几何形状

Sources