重温1993:复古图形渲染技术重现辉煌
速览
本文探讨了1993年的图形渲染技术及其美学特征。分析了这些经典技术如何在现代AI生成内容中焕发新生。复古图形风格为当代视觉创作提供了独特的艺术视角。
AI 深度解读
Making Graphics Like it's 1993:复古 3D 渲染的硬核实践
背景
这篇文章源自 Hacker News 社区,作者分享了一个名为 Catlantean 3D 的个人项目。这是一个耗时一年多、利用业余时间开发的侧车项目(Side-project),计划于明年在 Steam 平台发布。
作者的核心目标非常明确:使用 20 世纪 90 年代初常见的图形技术,构建一个完整、可发售的第一人称射击游戏(FPS)。为了模拟那个时代的限制,作者给自己施加了一系列看似“愚蠢”但极具挑战性的约束条件:
- 从零构建:包括所有资产(Assets)在内的所有内容必须完全从头制作。
- 手工渲染:所有渲染逻辑必须手写,不依赖现代图形 API 的高级特性。
- 手工混音:所有声音混合处理必须手动完成。
- 分辨率限制:目标分辨率为 320x240。
- 色彩限制:仅允许使用 256 色。
- 确定性要求:游戏逻辑必须使用定点数(Fixed Point)以保证跨平台行为的一致性;渲染部分允许使用浮点数,因为渲染的确定性并不重要。
- 平台抽象层:虽然允许使用平台抽象层,但必须假装其功能极其有限,仅支持帧缓冲区写入、键鼠输入、音频缓冲区写入和文件系统 I/O。
- 成品标准:必须是一个经过打磨、有趣且完整的游戏,而非单纯的技术演示(Tech-demo)。
- 禁止 AI 生成:明确拒绝使用 AI 生成内容("no AI slop")。
作者承认这些限制是不合理的,但他坚持这样做,并希望通过这篇文章探讨开发博客中常被忽视的一个环节:资产创建(Asset Creation)。
核心内容
1. 从 Mode 13h 到 Mode-X 的技术选择
文章首先回顾了 VGA 硬件上著名的 Mode 13h 图形模式,即 320x200 分辨率、256 色的图形模式。从程序员的角度看,这种模式极其简单:它拥有一个线性的帧缓冲区(Frame Buffer),每个像素由一个字节表示,该字节作为索引指向包含 256 种实际 RGB 值的调色板(Palette)。绘制像素只需在特定地址写入一个字节,无需考虑着色器或显存(VRAM)。
这种“每像素一字节,字节即调色板索引”的机制带来了严格的限制。与现代游戏可以随意使用数百万种颜色不同,在 256 色的限制下,资产创作变成了一个完全不同的问题:每一个颜色的选择都必须经过深思熟虑。像 Doom 和 Duke Nukem 这样的游戏很好地展示了如何在这种限制下创造出清晰、锐利的视觉效果。限制迫使开发者做出 deliberate(深思熟虑的)选择,而这些选择往往能带来良好的视觉结果。
Catlantean 3D 试图重现这种感觉,但作者选择了一个细微的变体:VGA Mode-X,即 320x240 分辨率。虽然 320x200 在 4:3 的显示器上会产生非方形像素(Non-square pixels),这更具“原汁原味”的复古感,但作者出于个人偏好,选择避免处理像素变形的问题。
2. 调色板的精心构建
一切始于 768 字节(256 色 x 3 通道 RGB)的调色板。作者通过无数次的试错迭代,精心挑选了这些颜色,其逻辑如下:
- 特殊用途色:预留一种鲜艳的粉色用于透明度,一种纯白,一种纯黑。
- 游戏机制色:由于游戏中需要大量的血迹,因此需要多种红色;同时需要绿色和蓝色的变体,以对应游戏中的红、绿、蓝钥匙及颜色编码的门。
- 环境色调:游戏背景设定在 Catlantis(一个因崇拜猫而模仿古埃及的讽刺性土地),因此需要大量的沙漠色调(黄色和棕色)。
- 科技与占领氛围:由于 Catlantis 被赛博狗人(Cybernetic dog-men)占领,场景中涉及大量技术设施,因此需要大量的灰色。
- 视觉平衡:使用一些米色(Beige)来打破灰色的单调,并在颜色变暗时作为更温暖的替代色。
- 主观填充:其余颜色在创建纹理时根据需要填充,主要依据是“看起来对劲”。
调色板并非一次性完成,而是在资产创建、测试和迭代的过程中不断调整。
3. 光线衰减与性能优化
Catlantean 3D 是一个传统的射线投射器(Raycaster)。地图由大小相同的瓦片(Tiles)组成,包含墙壁和空地。渲染器使用 DDA 算法(Digital Differential Analyzer)遍历每一列屏幕的瓦片地图,确定射线与地图几何体的交点,并根据采样坐标渲染带有纹理的墙壁列。地板和天花板随后作为水平扫描线渲染,填充屏幕剩余部分。
文章重点讨论了射线投射中最被忽视的方面:光照(Lighting)。
如果仅使用调色板而不加特效,画面会显得平淡无奇。为了营造深度感,作者希望实现以下效果:
- 距离玩家越远的几何体,光线越暗。
- 地图瓦片的每一侧颜色略有不同(模拟光照方向)。
在现代硬件加速渲染器中,这可以通过着色器轻松实现:根据顶点距离乘以浮点因子来降低颜色向量。但在基于调色板的渲染器中,没有“颜色”的概念,只有索引。如果要找到某种颜色的更暗变体,必须遍历调色板寻找符合“更暗”标准的颜色。
性能瓶颈:如果为屏幕上每个像素都遍历整个调色板,速度将不可接受。
解决方案:预处理查找表 作者采用了一种预处理策略,在运行时通过快速查找来确定颜色变体。
- 构建阴影矩阵:将调色板展开为一行,选择 32 个阴影等级(Shade Levels)。这意味着每种颜色需要 31 个更暗的变体。
- 计算目标颜色:已知每种颜色的 RGB 值和阴影索引,可以计算出目标更暗颜色的 RGB 值:
// 第一个阴影索引 (0) 为原始颜色 float darkening_factor = (32 - shade_index) / 32.0f; target_darker_color.r = current_color.r * darkening_factor; target_darker_color.g = current_color.g * darkening_factor; target_darker_color.b = current_color.b * darkening_factor; - 最近邻搜索:计算出的
target_darker_color可能不存在于调色板中。因此,需要遍历调色板,找到与该目标颜色“最接近”的颜色。
4. 颜色距离算法的演进
在定义“最接近”时,作者经历了重要的算法迭代:
-
初期尝试:欧几里得距离(Euclidean Distance) 起初,作者使用 RGB 空间中的欧几里得距离作为度量标准。然而,数学上的“接近”并不符合视觉感知。几乎所有颜色都倾向于向灰色靠拢,导致许多深色阴影看起来寒冷、死板,缺乏生命力。
-
最终方案:Oklab 色彩空间 + 色调偏移 作者将颜色转换到 Oklab 色彩空间,并利用其感知距离公式(Perceptual Distance Formula)。Oklab 的设计初衷就是使距离计算更符合人类对颜色差异的感知。
此外,作者还应用了一种在像素艺术中常见的概念:色调偏移(Hue Shifting)。随着颜色变暗,向更暖的色调施加微小的偏移。虽然这通常不是必需的,但它确实让游戏画面看起来更好。
作者坦言,这种“更好”很难理性解释,更多是一种主观的“看起来对劲”。
关键要点
- 复古限制的价值:严格的资源限制(如 256 色、低分辨率)并非单纯的障碍,它们能迫使开发者做出深思熟虑的设计选择,从而产生独特且清晰的视觉风格(如 Doom 的美学
