解决 Nintendo 64 上的叠加混合问题"}],

对于许多复古游戏爱好者来说,第五代主机在处理视觉效果——特别是爆炸、等离子束和魔法咒语时——始终存在一种可察觉的差异。如果你将 PlayStation (PSX) 上的 Silent Bomber 与 Nintendo 64 (N64) 上的 Star Fox 64 进行比较,PSX 的效果通常感觉更加“明亮”且充满活力。

这种视觉差异并非艺术选择的问题,而是硬件处理叠加混合(additive blending)方式的根本区别。虽然 N64 在技术上支持该功能,但一个关键的硬件缺失使得开发者在当时几乎无法使用它。

叠加混合的原理

叠加混合是一个将源像素(正在绘制的精灵或效果)的颜色值加到目标像素(现有的帧缓冲)的颜色值上的过程。在数学上,这可以表示为 result = src + dst

因为结果是叠加的,输出只会变得更亮,而永远不会变暗。这使得它成为模拟基于光效的理想技术。在 PlayStation 上,GPU 可以无缝处理这一点。如果红、绿或蓝通道的和超过了最大可能值(例如 8 位系统中的 255),PSX GPU 只会简单地将该值“钳位”(clamp)到 255。

N64 的致命缺陷:整数回绕

Nintendo 64 使用了 Reality Display Processor (RDP),它具有高度灵活的“颜色组合器”(Color Combiner)。这允许开发者使用类似 (P * A) + (Q * B) 的公式来定义复杂的混合操作。

在 N64 上设置叠加混合在代码中非常简单。使用 libdragon 库,它看起来像这样:

RDPQ_BLENDER(( IN_RGB, IN_ALPHA, MEMORY_RGB, ONE ))

然而,RDP 有一个关键缺陷:它不会对结果进行钳位。RDP 不会在达到最大值时停止,而是允许数值发生回绕(wrap around)。如果一个颜色值达到 256,它会重置为 0。

在实践中,这意味着爆炸最明亮的部分——本应是纯白色的部分——会突然跳变为黑色或深色,产生破坏效果的刺眼视觉伪影。

工程化解决方案

为了实现真正的叠加混合而又不产生回绕,开发者必须确保源像素和目标像素之和永远不会超过缓冲区的最大值。主要有两种方法可以实现,每种方法都有其权衡。

RSP 方法

可以使用 Reality Signal Processor (RSP),即 N64 的向量协处理器,来手动处理混合和钳位。然而,RSP 并不设计用于光栅化;使用它进行旋转、缩放或 3D 几何处理比使用 RDP 要复杂得多。

32 位缓冲区策略

一种更优雅的解决方案涉及操纵帧缓冲的精度。大多数 N64 游戏为了节省内存带宽,在最终输出时使用 16 位帧缓冲。通过改为渲染到 32 位 RGBA 8888 缓冲区,开发者可以获得显著更多的余量。

为了防止数值即使在 32 位缓冲区中也发生回绕,可以使用一种称为“强度缩放”(intensity scaling)的技术。通过指示颜色组合器以 1/8 的强度绘制所有颜色(使用雾效 alpha 值作为乘数),最终的叠加之和将被保持在回绕阈值以下。

// 利用雾效 alpha 值以 1/8 的强度绘制所有颜色
rdpq_set_fog_color(RGBA32(0, 0, 0, 256/8));
rdpq_mode_blender(RDPQ_BLENDER(( IN_RGB, FOG_ALPHA, MEMORY_RGB, ONE )));

让它重获新生:最终转换

虽然 32 位缓冲区可以防止回绕,但图像现在变得太暗了。最后一步是将 32 位缓冲区转换回 16 位 RGBA 5551 缓冲区以进行显示,并在转换过程中将任何超过 5 位范围(0-31)的值钳位到该范围内。

在 CPU 上执行此转换速度极慢(每帧大约 70ms)。然而,通过利用 RSP 的 128 位向量指令,转换可以优化到每帧大约 3.1ms 运行。现代工具如 RSPL(一种编译为 RSP 微代码的类 C 语言)使得这种实现对于今天的 Homebrew 开发者来说是可行的。

权衡与硬件约束

这种技术并非“免费的午餐”。N64 开发者避免使用 32 位 缓冲区的主要原因是该主机机的内存吞吐量极低。向 32 位缓冲区绘制内容需要比 16 位缓冲区在 RDRAM 与 RDP 之间往返传输两倍的字节数,这会显著影响整体性能。

尽管如此,对于特定应用或局部效果,这种方法提供了 N64 视觉调色板中缺失的那块“辉煌”的叠加混合效果。正如一位社区成员所指出的,这是饱和算术(saturation arithmetic)需求的一个经典案例——这一概念在音频混音中也很常见,其中未能对超出范围的值进行钳位,会导致数字剪切(digital clipping)和刺眼的伪影。

通过结合高精度渲染目标、强度缩放和 RSP 加速的钳位处理,我们终于可以赋予 N64 那些它本应享有的明亮爆炸效果。

Sources