第 1 章

屏幕之前的战争

屏幕上的光点正在移动。操作员盯着那枚光点,右手攥着光笔,左手悬在一排开关上方。他的整个身体微微前倾,后背离开椅背已有好一阵子。室内只有风扇的嗡鸣和继电器偶尔发出的咔嗒声。

那枚光点代表一架飞行器——更准确地说,代表雷达回波中一个尚未被识别的空中目标。它正从北大西洋方向朝北美大陆逼近,速度、高度、航向均符合远程轰炸机的特征。操作员的光笔触到屏幕,拖出一个矩形选框,将光点框入其中。旋风计算机开始计算拦截航线。

这是1953年,麻省理工林肯实验室。冷战进入第十个年头,苏联在四年前试爆了第一颗原子弹,北美防空司令部的前身——大陆防空司令部——正在拼命搭建一套能够实时追踪空中目标、计算拦截方案的自动化系统。旋风计算机是这个系统的神经中枢。它重达两万磅,占地两千平方英尺,装有五千多根真空管,每秒钟能执行大约四万次加法运算。以今天的标准看,它甚至不如一张生日贺卡里的音乐芯片。

但在当时,它是世界上第一台能够实时处理雷达数据并生成图形显示的电子计算机。那枚光点和它周围的矢量线——海岸轮廓、防空识别区边界、拦截航线——构成了人类历史上第一批实时交互图形。操作员不是在阅读一份打印出来的数据报表,不是在等待成批处理的计算结果。他在看。他在用手指做出反应。屏幕上的图形随他的手部动作而变化,变化发生在他动作的瞬间,而非数小时之后。

这个瞬间里埋着一枚种子。它要过四十年才会长成我们今天称为“游戏引擎”的东西,但它的遗传密码已经写定:一个人盯着一块屏幕,屏幕上的图形实时响应这个人的输入,形成一个闭合的反馈回路。这个回路的每一次循环都包含三个步骤——接收输入、更新状态、重新绘制——它们后来会成为每一帧游戏循环的骨骼。

但在1953年,没有人想到电子游戏。操作员想到的是核战争。旋风计算机的诞生本身就是一个制度压力的产物。

1940年代末,美国海军航空局需要一台飞行模拟器——一个能够实时计算空气动力学参数并驱动仪表盘读数变化的机器。麻省理工的杰伊·福雷斯特接下了这个项目。福雷斯特是个瘦削的、说话慢条斯理的中西部人,但他对计算速度的追求近乎偏执。当时主流的计算机使用水银延迟线存储器,数据以声波的形式在水银管中来回传播,读取速度受制于声速。福雷斯特判断这条路走不通。

他转而研发一种全新的存储技术:磁芯存储器——用细小的铁氧体磁环在导线上编织成矩阵,每个磁环可以存储一个比特。磁芯存储器的读写速度比水银延迟线快了几个数量级,而且它是随机存取的,不需要等待数据在介质中“旅行”到读取头。这项发明让旋风计算机成为了世界上第一台真正意义上的实时计算机。但它也把福雷斯特和他的团队拖进了另一个漩涡。

1949年8月,苏联试爆原子弹。美国空军接手了旋风项目,把它从飞行模拟器改造成防空指挥系统的核心。

需求变了:不再是为单个飞行员模拟飞行姿态,而是追踪整个北半球上空的所有飞行器,从中辨认出哪些是轰炸机,哪些是民航客机,哪些是雁群。这个系统后来被命名为SAGE——半自动地面防空环境。它把二十多个雷达站的数据汇总到旋风计算机(以及后续建造的二十多台同类机器),在屏幕上生成统一的空情图,由操作员用光笔标记目标、分配拦截力量。

SAGE系统从未真正用于实战。它建成的时候,洲际弹道导弹已经开始取代轰炸机成为主要威胁,而SAGE对弹道导弹几乎毫无用处。

但它在另一个维度上产生了影响:它训练了整整一代工程师,让他们习惯了这样一种想法——计算机的屏幕可以是双向的。你可以看它,它也可以看你。你可以用手指在上面画东西,它会回应你。

这批工程师中的许多人后来流向了大学、研究机构和私人企业。他们带走了磁芯存储器的设计图纸、光笔的电路原理、实时操作系统的调度算法,以及一种难以名状但真实存在的信念:人与机器之间可以存在一种即时、直观、图形化的对话方式。

这个信念在1963年找到了它最纯粹的早期表达。伊凡·苏泽兰那年二十五岁。他在麻省理工的博士论文答辩会上展示了一套叫做Sketchpad的系统。

他坐在一台TX-2计算机前——这台机器是旋风计算机的直系后代,同样诞生于林肯实验室——手握一支光笔,在一块九英寸的阴极射线管屏幕上画了一条线段。在画出第一条线段后,他命令计算机将其变为等边三角形,接着复制、旋转、缩放它。随后,他画了一个铰链结构并拖动一端,整个结构便按照力学约束自动调整姿态。他画了一个灯泡符号,告诉计算机“把这个存为灯泡”,之后每次他画出类似形状,计算机都会自动替换为标准符号。

答辩委员会沉默了。他们意识到自己正在目睹一种全新的人机关系的诞生。

在此之前,计算机的输入输出几乎完全是符号化的:打孔卡片进去,打印纸出来,或者电传打字机上的字符流。图形——如果存在的话——是计算结果的可视化副产品,是给人类看的,不是给人类操作的。Sketchpad改变了这一点。

图形本身成为了操作的对象。你可以直接触摸它——当然不是用手指,而是用光笔,但原理是一样的——你可以移动它、修改它、约束它。计算机在每一帧都在重新计算图形的几何关系,以确保你拖动任何一个顶点时,所有关联的线段、弧线、约束条件都同步更新。这是实时交互图形的基本范式。

苏泽兰在论文中定义了“主显示循环”的概念——一段反复执行的代码,不断读取输入设备的状态,更新内部数据模型,然后重新绘制屏幕。这个概念后来会成为每一个游戏引擎的核心架构。但在1963年,苏泽兰用它来画工程图纸。

他的资助方是美国国防部高级研究计划局(ARPA),他们看到的是更高效的武器设计工具。苏泽兰本人很快被ARPA招募,担任信息处理技术办公室的主任。在这个职位上,他掌握着一笔每年约一千五百万美元的预算,有权决定资助哪些计算机研究项目。他做出的最重要的决定之一,是给犹他大学的大卫·埃文斯拨款,建立一个计算机图形学研究中心。这笔拨款改变了计算机图形学的历史走向。

大卫·埃文斯在来到犹他大学之前已经在计算机行业摸爬滚打了十多年。他在本迪克斯公司领导过商用计算机的设计,对硬件有深刻的理解。苏泽兰卸任ARPA职务后也加入了犹他大学,与埃文斯共同领导这个后来被简称为“犹他图形学小组”的研究集体。在接下来的十年里,这个小组像一座熔炉,锻造了未来三十年计算机图形学的关键人物与概念。

帧缓冲的概念在这里被系统化。简单说,帧缓冲就是一块专门用来存储屏幕上每一个像素颜色值的内存区域。在此之前,计算机图形通常是矢量图形——屏幕上画的是线条,由电子束直接扫描出线段的轨迹。

帧缓冲的思路则完全不同:先把整个画面在内存中画好,然后一次性输出到屏幕。这个看似简单的概念改变了一切。它意味着图形不再受限于线条的数量和复杂度,你可以用像素填满整个屏幕,每一个像素都可以独立控制。它同时也意味着,图形生成和图形显示可以分离——计算机可以在帧缓冲中慢慢绘制复杂的场景,而显示器以固定的刷新率读取帧缓冲的内容。

这个分离后来成为现代图形管线的基石。隐藏面消除的算法在这里被发明。当计算机试图绘制一个三维场景时,它需要决定哪些表面是可见的,哪些被前面的物体遮挡。这个问题听上去简单,但在计算上极其棘手。

犹他小组的约翰·沃诺克——他后来创立了Adobe公司——开发了最早的实用隐藏面消除算法。他的思路是将屏幕递归地分割成小块,直到每个小块中的可见关系变得简单到可以直接判断。这个“分而治之”的策略后来启发了无数图形算法。

纹理映射在这里被首次实现。埃德·卡特穆尔——他后来成为皮克斯的联合创始人——在1974年完成了博士论文,展示了如何将一幅二维图像“贴”到三维曲面上。他用的素材是他的左手——他用石膏翻模了自己的手,然后用扫描仪数字化了手背的皮肤纹理,再写程序将纹理映射到计算机生成的“数字手”上。这只手后来出现在1976年的电影《未来世界》中,成为计算机图形学历史上最著名的影像之一。卡特穆尔在论文中还解决了另一个关键问题:纹理在透视变形下的正确采样。

他的解决方案后来被称为“卡特穆尔–罗姆滤波”,至今仍是纹理映射的基础算法。

Phong光照模型在这里被提出。裴祥风——一个来自越南的研究生——在1973年的博士论文中提出了一个计算光照的数学模型。在此之前,计算机生成的三维物体表面看起来像塑料,因为当时的着色方法只计算了漫反射——光线均匀散射,表面没有高光。Phong的模型加入了镜面反射分量:当观察者的视线接近反射光线的方向时,表面亮度急剧增加。这个简单的修改让计算机生成的球体第一次出现了逼真的高光点。Phong的论文只有七页,但它定义的光照模型在接下来的四十年里被几乎每一个实时渲染系统采用。

Phong本人于1975年因白血病去世,年仅三十二岁。他没有活着看到自己的算法被写入每一块图形处理器的微码。这些成就的清单可以继续列下去:反走样、阴影生成、环境映射、粒子系统——几乎所有现代计算机图形学的基础概念都可以追溯到犹他大学那栋灰色混凝土大楼里的某个办公室或实验室。

而这个小组的存在本身,则取决于一个冷战制度安排:ARPA的资助机制。ARPA在1960年代的使命是确保美国在军事技术上领先苏联,它的项目官员们相信,资助基础研究——而不只是武器开发——是维持技术优势的最有效方式。这种信念让犹他图形学小组得以在几乎没有短期产出压力的情况下,进行了长达十年的基础研究。

但这个制度安排也划定了研究的边界。ARPA的钱流向了大学,流向了能够通过同行评审的学术研究。它没有流向购物中心里的投币游戏机。

1961年,麻省理工的一群学生在一台PDP-1计算机上写了一个叫Spacewar!的程序。PDP-1是数字设备公司生产的小型计算机——相对于旋风计算机而言的“小型”——它只有一台冰箱那么大,价格约十二万美元,配备了一块圆形阴极射线管显示器。Spacewar!在这块屏幕上呈现了两个针形飞船,各由一个玩家控制,在中央恒星的引力场中互相射击。飞船的矢量图形在黑色背景上旋转、加速、开火,星空的随机点阵在背景中闪烁。

Spacewar!不是第一个计算机游戏。在此之前,已经有井字棋、跳棋之类的程序在大型机上运行。但Spacewar!是第一个让人无法移开目光的计算机游戏。

它有一种原始的、不可抗拒的吸引力:两个人在同一块屏幕前,实时对抗,每一个动作都在瞬间产生可见的后果。它不是回合制的,不是批处理的,不是用打印纸输出的。它是活的。

这个程序在PDP-1的用户群体中像病毒一样传播。数字设备公司后来甚至把Spacewar!预装在新出厂的PDP-1上,作为演示程序。每一个接触过Spacewar!的人都记住了那种感觉——屏幕上的东西在实时回应你。

其中一个人是诺兰·布什内尔。布什内尔在1960年代末是犹他大学工程系的学生。他在计算机实验室里第一次玩到了Spacewar!。他后来回忆说,那个游戏让他意识到一件事:如果你能让一个人在屏幕上控制一个东西,他就会往里面投币。这个想法在他脑子里扎下了根。

但当时的计算机太贵了——一台PDP-1要十二万美元,没有哪个购物中心会买一台来开游戏厅。布什内尔毕业后去了加州,在一家叫Ampex的录音设备公司工作,白天设计电路,晚上在车库里琢磨怎么把Spacewar!变成投币游戏机。他最初的尝试是用一台真正的计算机——数据将军Nova——来运行游戏。但即使是最便宜的小型机也要四千美元,而一台街机的售价不能超过一千美元才能回本。布什内尔被迫放弃了这个方案。

他转而采用了一个激进的思路:不用计算机。用专用电路。1972年,布什内尔创立了雅达利公司,推出了Pong。Pong的电路板上没有微处理器,没有操作系统,没有一行软件代码。它由七十五个分立逻辑芯片组成,每个芯片执行一个固定的功能:生成球拍的垂直位置、检测球的碰撞、计算得分、输出视频信号。屏幕上的一切——两个球拍、一个球、中间的虚线、角落里的分数——都是由硬件定时信号直接生成的。

球拍的垂直位置由一个电位器控制,玩家转动旋钮,电位器的电阻改变,电路中的电压改变,屏幕上球拍的垂直位置随之移动。球的速度和方向由电容的充放电时间决定。得分的数字由七段数码管的驱动信号叠加在视频输出上。这里面没有任何东西可以被称为“引擎”。没有任何通用计算能力。没有任何可编程性。Pong的每一块芯片都知道自己该做什么,而且只会做那一件事。但Pong完成了一件至关重要的事情:它把实时交互图形的反馈回路从实验室拖进了购物中心。

投币口里的硬币落下,触发开关,游戏开始。玩家转动旋钮,球拍移动。球碰到球拍,反弹。球越过球拍,对手得分。整个过程在不到六十分之一秒内完成——比人类的反应速度快得多,快到让人感觉是即时的。

这个“即时”的感觉就是一切。它不是图形学的成就——Pong的图形简陋到了极点,白色方块代表球拍,白色小方块代表球,黑色背景代表什么都没有。它也不是技术的成就——Pong的电路设计在电子工程师看来几乎称不上创新。

它是另一种东西:一种契约。玩家投币,机器响应。响应必须发生在玩家动作的瞬间,而不是一秒之后,不是“请稍候”之后。这个契约后来成为电子游戏的定义性特征,但它在1972年没有任何理论表述。它只是被做出来了,被焊在一块玻璃纤维电路板上,封装在一个木纹贴面的机箱里,摆在安迪·卡普酒馆的角落里。

同一时期,日本太东公司的西角友宏正在设计一款叫《太空侵略者》的游戏。1978年,这款游戏登陆街机厅,引发了一场社会现象——日本的百元硬币一度出现短缺,政府不得不增加铸币量。《太空侵略者》的硬件架构比Pong复杂得多,但原理相似:专用集成电路生成图形,没有通用处理器,没有软件层。游戏中的外星人编队是一组精灵图——存储在只读存储器中的位图图像,由硬件电路按照行扫描顺序逐行输出到屏幕。当玩家移动激光炮时,电路改变精灵图在屏幕上的水平坐标。当外星人编队移动时,电路以固定的帧率逐帧更新所有外星人的坐标。精灵图滚动的核心技术挑战在于同步。

CRT显示器从左上角开始,一行一行地扫描,扫描到右下角后跳回左上角开始下一帧。在扫描过程中,如果精灵图的坐标在屏幕中间被改变了,已经扫描过的部分和尚未扫描的部分就会出现撕裂。解决这个问题的方法是双缓冲——在内存中准备好下一帧的所有精灵图位置,然后在扫描线跳回左上角的瞬间一次性切换。这个技术后来成为所有实时图形的标准做法,但在1978年,它是由硬件工程师用触发器和锁存器实现的,没有任何软件抽象。

“引擎”这个概念仍然不存在。每一款游戏都是从头设计的硬件和从头编写的程序(如果有程序的话)的紧密结合体。为《太空侵略者》设计的电路板无法运行《吃豆人》,为《吃豆人》设计的电路板也无法运行《大金刚》。每做一个新游戏,工程师都要重新设计电路,重新布线,重新调试。软件——如果存在的话——是直接写在汇编语言里的,直接操作硬件寄存器,没有任何中间层。这种开发方式的效率低得惊人。但它也带来了一个意想不到的副产品:极致的优化。

因为每一款游戏的硬件都是为这款游戏专门设计的,所以它可以把当时可用的晶体管预算精确地分配到游戏需要的每一个功能上。背景滚动需要硬件支持?加一块卷轴芯片。精灵图需要透明色?加一个颜色键控电路。碰撞检测需要在精灵图之间进行?加一个像素级的硬件比较器。每一颗芯片、每一个晶体管都有明确的、不可替代的职责。

这种“全定制”的哲学在1980年代初达到了顶峰。街机游戏的画面复杂度、滚动速度和精灵图数量以惊人的速度增长。1981年的《防御者》实现了全方向平滑滚动和多层视差背景。1983年的《龙穴》使用了镭射影碟来播放预渲染的动画——这不是实时图形,但它展示了游戏产业对视觉冲击力的无止境追求。1985年的《太空哈利》引入了雅马哈的FM音源芯片和世嘉的“超级标量”精灵图引擎,可以在屏幕上同时显示超过一百个高速移动的精灵图。

但在这些令人眼花缭乱的画面背后,一个结构性的矛盾正在加深。在学术界,计算机图形学已经进入了理论成熟的阶段。

1975年,犹他大学的吉姆·布林完成了博士论文,系统化了纹理映射、环境映射和凹凸映射的理论框架。1979年,特纳·惠特德发表了递归光线追踪算法,可以模拟反射、折射和阴影。1984年,康奈尔大学的戈拉尔、托兰斯和格林伯格提出了辐射度方法,可以模拟漫反射面之间的相互光照——这是光线追踪无法处理的间接光照。1986年,吉姆·卡吉亚发表了渲染方程,用一个简洁的积分方程统一描述了所有光照现象:从直接光照到间接光照,从镜面反射到次表面散射,从焦散到色溢。渲染方程是计算机图形学的“万物理论”——它精确地描述了光在场景中的传播方式,至少在几何光学的范围内,它是完备的。

但在街机厅里,没有人在计算光线追踪。没有人在求解渲染方程。没有人在做纹理滤波。街机游戏的图形是用精灵图拼出来的——一层一层的位图图像,按照固定的优先级叠加在一起,由硬件电路逐行扫描输出。精灵图没有光照,没有阴影,没有透视变形。

它们的颜色是设计时就定好的,不会因为“光源”的位置而改变。它们的尺寸是固定的,不会因为“摄像机”的距离而缩放。这不是因为街机工程师们不懂图形学。他们中的很多人读过学术论文,知道犹他小组在做的事情。问题在于,光线追踪一帧图像需要几分钟甚至几小时的运算时间——用1980年代的计算机算力。而街机游戏需要在六十分之一秒内完成一帧。这个差距不是几倍、几十倍,而是几十万倍。没有任何已知的硬件架构可以弥合这个鸿沟。

于是出现了这样一种局面:计算机图形学最前沿的理论已经能够描述光的物理行为,而游戏产业最先进的硬件仍然在用逐行扫描的精灵图拼凑世界。这两个世界在1980年代早期几乎没有交集。图形学论文发表在SIGGRAPH会议论文集上,读者是大学里的研究者和电影特效公司的工程师。街机游戏的设计文档和电路图锁在游戏公司的保险柜里,读者是硬件工程师和游戏设计师。两群人参加不同的会议,读不同的期刊,使用不同的词汇,解决不同的问题。

但这种隔绝不可能永远持续下去。原因很简单:游戏产业对图形质量的需求在增长,而全定制硬件的开发成本也在增长。每一代新游戏都需要更复杂的电路,更多的芯片,更长的开发周期。通用微处理器的性能正在以摩尔定律的速度提升。英特尔在1978年推出了8086处理器,摩托罗拉在1979年推出了68000处理器。这些芯片的性能还不足以运行光线追踪,但它们已经足够强大,可以用软件来实现精灵图引擎的大部分功能——滚动、碰撞检测、精灵图排序、调色板管理。

这意味着“引擎”概念诞生的条件正在成熟。如果游戏的图形功能可以从硬件中抽象出来,写成一层软件,那么同一层软件就可以运行不同的游戏,同一款游戏也可以运行在不同的硬件上。这个抽象层就是引擎的雏形。但在1980年代初,没有人确切地知道这个抽象层应该长什么样。图形学理论提供了渲染的数学基础,但那些理论是为离线渲染设计的,不是为六十分之一秒的实时循环设计的。

街机硬件提供了实时交互的工程实践,但那些实践是焊接在专用电路上的,不是软件可以复用的。两条河流已经各自奔涌了三十年。一条发源于冷战防空指挥所的雷达屏,流经大学的图形学实验室,携带着帧缓冲、隐藏面消除、纹理映射和渲染方程。另一条发源于购物中心的投币机箱,流经街机厅的电路板,携带着精灵图、双缓冲、碰撞检测和实时响应的契约。

它们流到了1980年代中期的同一个历史时刻,但还没有汇合。在犹他大学的实验室里,卡特穆尔的数字手在缓慢旋转,每一帧都需要几分钟来渲染。在街机厅里,《太空侵略者》的外星人编队以每秒六十帧的速度向下推进,但它们只是黑白位图的简单平移。前者拥有光照的真理但没有速度。后者拥有速度但没有光照的真理。

断裂处,正是引擎即将破土而出的土壤。但要让这两条河流真正交汇,还需要一次碰撞——一次足够猛烈的碰撞,能够把学术界的渲染理论、游戏产业的实时契约和消费级硬件的算力增长强行焊接在一起。那场碰撞还没有发生。它的条件正在1980年代中期的某个看不见的断层带上悄悄累积。