mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-25 23:11:02 +08:00
R
PART 1
This commit is contained in:
parent
c111632755
commit
7c23d31285
@ -3,30 +3,30 @@
|
||||
[#]: author: "Two-Bit History https://twobithistory.org"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "aREversez"
|
||||
[#]: reviewer: " "
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
在《毁灭战士》中应用二叉空间分割技术是何等天才之举?
|
||||
======
|
||||
|
||||
1993 年,游戏开发公司 id Software 发行了一款第一人称射击游戏 _《毁灭战士》_,游戏一经发行迅速爆火。在今天看来,《毁灭战士》可谓有史以来最具影响力的游戏之一。
|
||||
1993 年,游戏开发公司 id Software 发行了一款第一人称射击游戏 《<ruby>毁灭战士<rt>DOOM</rt></ruby>》,游戏一经发行迅速爆火。在今天看来,《毁灭战士》可谓有史以来最具影响力的游戏之一。
|
||||
|
||||
_《毁灭战士》_ 发行之后的第十年(2003 年),记者大卫·库什纳出版了一本关于 id Software 的书,书名为 _《Doom 启示录》_,后被奉为记录 _Doom_ 创作史的典范读物。几年前我曾读过这本书,如今内容已记得不太真切了,但是书中有一个关于 id Software 首席程序员约翰·卡马克的故事,我印象特别深刻。这里只对故事做粗略描述(具体情节请往下阅读)。实际上,早在 _《毁灭战士》_ 开发前期,卡马克就发现自己为这款游戏编写的 3D 渲染器在渲染某些关卡时,出现速度缓慢的问题。对于 _《毁灭战士》_ 这一对动感和速度有着相当高要求的射击游戏来说,这是一个非常严重的问题。意识到了这一问题的严重性,卡马克需要一个更加有效的渲染算法,于是他开始阅读相关文献。最后,他采用“二叉空间分割”技术,极大地提升了《毁灭战士》游戏引擎的运行速度,而这项技术此前从未用于电子游戏当中。
|
||||
《毁灭战士》发行之后的第十年(2003 年),记者<ruby>大卫·库什纳<rt>David Kushner</rt></ruby>出版了一本关于 id Software 的书,书名为 《<ruby>Doom 启示录<rt>Masters of Doom</rt></ruby>》,后被奉为记录毁灭战士创作史的典范读物。几年前我曾读过这本书,如今内容已记得不太真切了,但是书中有一个关于 id Software 首席程序员<ruby>约翰·卡马克<rt>John Carmack</rt></ruby>的故事,我印象特别深刻。这里只对故事做粗略描述(具体情节请往下阅读)。实际上,早在 《毁灭战士》 开发前期,卡马克就发现自己为这款游戏编写的 3D 渲染器在渲染某些关卡时慢得像爬一样。对于 《毁灭战士》 这一对动感和速度有着相当高要求的射击游戏来说,这是一个非常严重的问题。意识到了这一问题的严重性,卡马克需要一个更加有效的渲染算法,于是他开始阅读相关论文。最后,他实现了一种叫做“<ruby>二叉空间分割<rt>binary space partitioning</rt></ruby>”的技术,极大地提升了《毁灭战士》游戏引擎的运行速度,而这项技术此前从未用于电子游戏当中。
|
||||
|
||||
一直以来,我对这个故事的印象十分深刻。卡马克将学术前沿研究运用于电子游戏之中,我觉得这正是他之所以成为传奇人物的原因。无论从哪个角度来看,卡马克都应该是电子游戏行业中人尽皆知的典型天才程序员,只不过上面这个故事是我最先能够想到的理由。
|
||||
一直以来,我对这个故事的印象十分深刻。卡马克将学术前沿研究运用于电子游戏之中,我觉得这正是他之所以成为传奇人物的原因。无论从哪个角度来看,卡马克都应该是电子游戏行业中人尽皆知的典型的天才程序员,只不过上面这个故事是我最先能够想到的理由。
|
||||
|
||||
显而易见,“二叉空间分割”这个术语听起来就是难度相当高的课题,能够自行阅读文献并将其付诸实施实属不易,所以这个故事给我留下了深刻的印象。我一直认为卡马克的做法十分具有创见性,不过由于我既不懂二叉空间分割到底是怎样的一项技术,也不晓得这项技术在当时究竟有多么革新,所以我也并不确定自己的观点是否正确。如果按照从荷马·辛普森到爱因斯坦的顺序为天才列出一套级别体系,那么卡马克将二叉空间分割技术运用于 _《毁灭战士》_ 的做法究竟属于什么级别的天才之举呢?
|
||||
显而易见,“二叉空间分割”这个术语听起来就是难度相当高的课题,能够自行阅读论文并将其付诸实施实属不易,所以这个故事给我留下了深刻的印象。我一直认为卡马克的做法十分具有创见性,不过由于我既不懂二叉空间分割到底是怎样的一项技术,也不晓得这项技术在当时究竟有多么革新,所以我也并不确定自己的观点是否正确。如果按照从<ruby>霍默·辛普森<rt>Homer Simpson</rt></ruby>(LCTT 译注:《辛普森一家人》中的那个老爹)到<ruby>阿尔伯特·爱因斯坦<rt>Albert Einstein</rt></ruby>的顺序为天才列出一套级别体系,那么卡马克将二叉空间分割技术运用于 《毁灭战士》 的做法究竟属于什么级别的天才之举呢?
|
||||
|
||||
同时,我也在想,二叉空间分割这个概念最初是从哪儿来的,又是怎样吸引到卡马克的?因此,本篇文章不仅仅会讲述约翰·卡马克和 _《毁灭战士》_ 的故事,也会探讨二叉空间分割树(BSP 树)数据结构的发展历史。有意思的是,BSP 树和计算机科学领域其他许多技术一样,最初都起源于军事研究领域。
|
||||
同时,我也在想,二叉空间分割这个概念最初是从哪儿来的,又是怎样吸引到卡马克的?因此,本篇文章不仅仅会讲述约翰·卡马克和 《毁灭战士》 的故事,也会探讨二叉空间分割树(BSP 树)数据结构的发展历史。有意思的是,BSP 树和计算机科学领域其他许多技术一样,最初都起源于军事研究领域。
|
||||
|
||||
没错,_《毁灭战士》_ 的第一关卡 E1M1 就受到了美国空军的启发。
|
||||
没错,《毁灭战士》 的第一关卡 E1M1 就受到了美国空军的启发。
|
||||
|
||||
### VSD 难题
|
||||
|
||||
BSP 树是计算机图形领域最具挑战性难题的解决方案之一。举个例子,为了渲染出三维场景,渲染器必须能够区分可见物体和不可见物体。如果渲染时间比较充足,这一要求也算不上大问题;但是理想来说,实时游戏引擎在 1 秒内至少需要完成 30 次区分任务。
|
||||
|
||||
这一问题有时被称为可见表面检测问题。当时,卡马克与迈克尔·亚伯拉什携手合作,一起开发 _《雷神之锤》_(id Software 继 _《毁灭战士》_ 之后开发的游戏)。关于可见表面检测问题,亚伯拉什在自己的著作 _《图形程序开发人员指南》_ 中写道:
|
||||
这一问题有时被称为可见表面检测问题。当时,卡马克与迈克尔·亚伯拉什携手合作,一起开发 _《雷神之锤》_(id Software 继 《毁灭战士》 之后开发的游戏)。关于可见表面检测问题,亚伯拉什在自己的著作 _《图形程序开发人员指南》_ 中写道:
|
||||
|
||||
> 我想探讨一下在我看来 3D 中最棘手的一个问题:可见表面检测问题(在每个像素点上绘制合适的表面)以及与之密切相关的隐面消除问题(迅速去除不可见的多边形,用于加快可见表面检测速度)。简略起见,我将在下文采用缩写 VSD 来表示可见表面检测和隐面消除。
|
||||
|
||||
@ -34,13 +34,13 @@ BSP 树是计算机图形领域最具挑战性难题的解决方案之一。举
|
||||
|
||||
> 相反,VSD 却像是一个无底洞,目前应对方案也有很多。但实际上,在采用简单的方法处理 VSD 时,其性能会直接受到场景复杂程度的影响,而场景的复杂程度通常会以平方级或立方级的形式增大。所以在渲染过程中,VSD 很快就会成为制约因素。[1][1]
|
||||
|
||||
_《毁灭战士》_ 这款游戏告诉我们,普通人盼望着能用自家电脑玩很吃图形配置的游戏。之后数年,即上个世纪九十年代,亚伯拉什讨论了复杂的 VSD 问题。同时代早期,id Software 成立后发行了一些游戏。尽管当时的计算机还只是用来处理文字与表格或者执行其他任务,未尝想过要在上面运行游戏,id Software 必须对发行的游戏进行编程,使其能在计算机上流畅运行。为了实现这一飞跃,尤其是为了能让在 _《毁灭战士》_ 之前发行的少数 3D 游戏在电脑上运行,id Software 必须做出革新。在这些游戏中,所有的关卡在设计时都施加了一定的限制,以便更容易解决 VSD 问题。
|
||||
《毁灭战士》 这款游戏告诉我们,普通人盼望着能用自家电脑玩很吃图形配置的游戏。之后数年,即上个世纪九十年代,亚伯拉什讨论了复杂的 VSD 问题。同时代早期,id Software 成立后发行了一些游戏。尽管当时的计算机还只是用来处理文字与表格或者执行其他任务,未尝想过要在上面运行游戏,id Software 必须对发行的游戏进行编程,使其能在计算机上流畅运行。为了实现这一飞跃,尤其是为了能让在 《毁灭战士》 之前发行的少数 3D 游戏在电脑上运行,id Software 必须做出革新。在这些游戏中,所有的关卡在设计时都施加了一定的限制,以便更容易解决 VSD 问题。
|
||||
|
||||
例如,在 _《毁灭战士》_ 之前,id Software 发行了 _《德军总部 3D》_,该游戏的每一个关卡都是由与坐标轴平齐的墙壁组成。换言之,在《德军总部 3D》的游戏画面里,你看到的只有南北方向或者东西方向的墙壁。在游戏中,墙壁与墙壁之间有着固定的间隔,所有过道的宽度或是一个方格,或是两个方格等等,但绝不会出现 2.5 个方格。如此一来,尽管 id Software 团队只能设计出外观十分相似的关卡,但这也让卡马克为 _《德军总部 3D》_ 编写渲染器的工作简单了不少。
|
||||
例如,在 《毁灭战士》 之前,id Software 发行了 _《德军总部 3D》_,该游戏的每一个关卡都是由与坐标轴平齐的墙壁组成。换言之,在《德军总部 3D》的游戏画面里,你看到的只有南北方向或者东西方向的墙壁。在游戏中,墙壁与墙壁之间有着固定的间隔,所有过道的宽度或是一个方格,或是两个方格等等,但绝不会出现 2.5 个方格。如此一来,尽管 id Software 团队只能设计出外观十分相似的关卡,但这也让卡马克为 _《德军总部 3D》_ 编写渲染器的工作简单了不少。
|
||||
|
||||
通过将屏幕上的光线“齐射”入虚拟游戏世界,_《德军总部》_ 的渲染器解决了 VSD 问题。通常来说,使用光线的渲染器叫做“光线投射”渲染器。这种渲染器的速度一般较慢,因为解决内部的 VSD 问题涉及到在光线和游戏中的物体之间找到第一个交点,这通常需要进行大量的计算。但在 _《德军总部》_,由于所有的墙壁都与网格平齐,所以光线与墙壁相交的位置只能在网格线上。如此一来,渲染器只需逐个检查这些交点即可。如果渲染器先从离玩家视角最近的交点开始检查,接着检查下一个最近的交点,以此类推,最后遇到第一面墙壁时停止检查。这样,VSD 问题便轻而易举地得到了解决。光线从每一个像素点向前投射,与画面物体接触时停止运动,这一方法是可行的。因为结合 CPU 周期来看,投射的成本很低。事实上,由于每面墙壁高度相同,因此针对同列的像素点,投射的光线只需一条。
|
||||
|
||||
尽管当时还没有专业的图形显卡,_《德军总部》_ 凭借这一取巧之法得以在配置较低的个人电脑上正常运行起来。然而,这个办法并不适用于 _《毁灭战士》_。id Software 为这款新游戏增添了许多新元素——倾斜的墙面、楼梯以及高低不一的天花板。光线投射的办法自然也就不好用了,于是卡马克编写出了一个新的渲染器。_《德军总部》_ 的渲染器关注的是图像,将光线投射到屏幕像素表示的列上,而 _《毁灭战士》_ 关注的则是物体。换句话说,_《毁灭战士》_ 的渲染器会记录游戏场景中的所有物体,继而将其投射到屏幕当中;而非记录屏幕上的像素点,判断每个像素点的颜色。
|
||||
尽管当时还没有专业的图形显卡,_《德军总部》_ 凭借这一取巧之法得以在配置较低的个人电脑上正常运行起来。然而,这个办法并不适用于 《毁灭战士》。id Software 为这款新游戏增添了许多新元素——倾斜的墙面、楼梯以及高低不一的天花板。光线投射的办法自然也就不好用了,于是卡马克编写出了一个新的渲染器。_《德军总部》_ 的渲染器关注的是图像,将光线投射到屏幕像素表示的列上,而 《毁灭战士》 关注的则是物体。换句话说,《毁灭战士》 的渲染器会记录游戏场景中的所有物体,继而将其投射到屏幕当中;而非记录屏幕上的像素点,判断每个像素点的颜色。
|
||||
|
||||
对于强调物体的渲染器来说,可以使用 Z 缓冲器来解决 VSD 问题,比较简单。每次将物体投射到屏幕上时,需要对每个用于绘制的像素点进行检查。如果你想绘制出的物体的部分和已经绘制在目标像素点上的物体相比更加接近玩家,可以将其覆盖。否则,必须保持像素不变。尽管办法很简单,但是 Z 缓冲器对内存的要求较高,投射关卡几何图形时渲染器仍会消耗大量的 CPU 资源,虽然玩家无法看到这些几何图形。
|
||||
|
||||
@ -48,9 +48,9 @@ _《毁灭战士》_ 这款游戏告诉我们,普通人盼望着能用自家
|
||||
|
||||
考虑到将图像写入帧缓冲器的成本非常之高,理想的渲染器需要首先绘制离玩家最近的物体,接着是比较近的物体,以此类推,直到屏幕上每个像素点都写入了信息。这时,渲染器会停止运行,大幅缩短远处不可见物体的渲染时间。这种由近及远对物体进行排序的方法也可以解决 VSD 问题。那么问题又来了:什么才是玩家可以看到的?
|
||||
|
||||
最初,卡马克打算依靠 _《毁灭战士》_ 的关卡布局来解决 VSD 问题。首先用渲染器绘制出玩家目前所在房间的墙壁,之后玩家冲进隔壁房间,再绘制出隔壁房间的墙壁。由于每个房间互不遮挡,这一办法也能解决 VSD 问题。而互相遮挡的房间可以分割成若干互不遮挡的“区域”。在 YouTube 上的一个 [视频][2] 中,Bisqwit 展示了自己制作出来的使用了相同算法的渲染器。可以看到,如果玩家移动速度非常慢,便能一睹渲染的具体过程。这一算法同样运用到了《毁灭公爵 3D》当中,这款游戏在 _《毁灭战士》_ 推出三年之后发行,当时 CPU 的性能也更加强大了。1993 年,尽管在硬件上已经可以运行游戏了,但是使用这一算法的 _《毁灭战士》_ 渲染器在复杂的层级结构上依旧表现吃力,尤其是在房间分割出来的各部分相互嵌套的情况下。不巧的是,这类层级结构正是构造环形楼梯等物体的唯一办法。沿着环形楼梯走下去,直到走入已经绘制好的区域,由于这其中涉及多次循环下降运动,导致游戏引擎的运行速度大幅降低。
|
||||
最初,卡马克打算依靠 《毁灭战士》 的关卡布局来解决 VSD 问题。首先用渲染器绘制出玩家目前所在房间的墙壁,之后玩家冲进隔壁房间,再绘制出隔壁房间的墙壁。由于每个房间互不遮挡,这一办法也能解决 VSD 问题。而互相遮挡的房间可以分割成若干互不遮挡的“区域”。在 YouTube 上的一个 [视频][2] 中,Bisqwit 展示了自己制作出来的使用了相同算法的渲染器。可以看到,如果玩家移动速度非常慢,便能一睹渲染的具体过程。这一算法同样运用到了《毁灭公爵 3D》当中,这款游戏在 《毁灭战士》 推出三年之后发行,当时 CPU 的性能也更加强大了。1993 年,尽管在硬件上已经可以运行游戏了,但是使用这一算法的 《毁灭战士》 渲染器在复杂的层级结构上依旧表现吃力,尤其是在房间分割出来的各部分相互嵌套的情况下。不巧的是,这类层级结构正是构造环形楼梯等物体的唯一办法。沿着环形楼梯走下去,直到走入已经绘制好的区域,由于这其中涉及多次循环下降运动,导致游戏引擎的运行速度大幅降低。
|
||||
|
||||
在 id Software 团队意识到 _《毁灭战士》_ 游戏引擎的速度可能过慢时,公司还面临着其他任务:将 _《德军总部 3D》_ 移植到超级任天堂游戏机(简称“超任”)上。那时,超任的性能比兼容 IBM 公司机器的个人电脑还要差。结果表明,尽管光线投射渲染器非常简单,但是想要在超任上快速运行是不可能的。于是,卡马克着手研究更为高效的算法。事实上,也正是为了顺利将 _《德军总部》_ 移植到超任,卡马克首次研究了二叉空间分割技术,并将其付诸应用。由于 _《德军总部》_ 的墙壁与坐标轴平齐,所以二叉空间分割技术应用起来也比较简单直接;但是 _《毁灭战士》_ 的情况则比较复杂。不过,卡马克发现,二叉空间分割树同样可以用来解决 _《毁灭战士》_ 速度过慢的问题。
|
||||
在 id Software 团队意识到 《毁灭战士》 游戏引擎的速度可能过慢时,公司还面临着其他任务:将 _《德军总部 3D》_ 移植到超级任天堂游戏机(简称“超任”)上。那时,超任的性能比兼容 IBM 公司机器的个人电脑还要差。结果表明,尽管光线投射渲染器非常简单,但是想要在超任上快速运行是不可能的。于是,卡马克着手研究更为高效的算法。事实上,也正是为了顺利将 _《德军总部》_ 移植到超任,卡马克首次研究了二叉空间分割技术,并将其付诸应用。由于 _《德军总部》_ 的墙壁与坐标轴平齐,所以二叉空间分割技术应用起来也比较简单直接;但是 《毁灭战士》 的情况则比较复杂。不过,卡马克发现,二叉空间分割树同样可以用来解决 《毁灭战士》 速度过慢的问题。
|
||||
|
||||
### 二叉空间分割
|
||||
|
||||
@ -88,27 +88,27 @@ _《毁灭战士》_ 这款游戏告诉我们,普通人盼望着能用自家
|
||||
|
||||
同时,三人也提到了一项需要进一步深入研究的问题:究竟怎样才能构建出一棵“高质量的” BSP 树?BSP 树的质量取决于用作分割平面的多边形的选择。我在前文跳过了这一问题,不过如果用作分割平面的多边形与其他多边形相交,那么为了避免 BSP 算法失效,必须将相交的多边形一分为二,这样两部分就可以分在不同的空间。但是如果这种现象反复出现,BSP 树的构建势必会大幅增加场景中多边形的数量。
|
||||
|
||||
内勒后来在其 1993 年的论文《<ruby>构建高质量的分割树<rt>Constructing Good Partitioning Trees</rt></ruby>》中提及这一问题。与卡马克一同建立 id Software 的约翰·罗梅洛指出,这篇论文是卡马克在 _《毁灭战士》_ 中引入 BSP 树时读到的论文之一。[4][9]
|
||||
内勒后来在其 1993 年的论文《<ruby>构建高质量的分割树<rt>Constructing Good Partitioning Trees</rt></ruby>》中提及这一问题。与卡马克一同建立 id Software 的约翰·罗梅洛指出,这篇论文是卡马克在 《毁灭战士》 中引入 BSP 树时读到的论文之一。[4][9]
|
||||
|
||||
### 《毁灭战士》中的 BSP 树
|
||||
|
||||
别忘了,卡马克首次为 _《毁灭战士》_ 设计渲染器时,通过让渲染器渲染玩家所在房间之外的临近房间,试图为关卡几何图形建立一套渲染顺序。对此,BSP 树是个不错的选择,因为在玩家进入之前的房间(区域)时,BSP 树能够避免让渲染器重复劳动,从而节省 CPU 资源。
|
||||
别忘了,卡马克首次为 《毁灭战士》 设计渲染器时,通过让渲染器渲染玩家所在房间之外的临近房间,试图为关卡几何图形建立一套渲染顺序。对此,BSP 树是个不错的选择,因为在玩家进入之前的房间(区域)时,BSP 树能够避免让渲染器重复劳动,从而节省 CPU 资源。
|
||||
|
||||
实际上,“将 BSP 树引入 _《毁灭战士》_”意味着将 BSP 树生成器引入 _《毁灭战士》_ 的关卡编辑器中。_《毁灭战士》_ 的关卡制作完成之时,BSP 树就会在关卡几何图形的基础上生成。根据程序员法比安·桑格勒德的说法,在原版 _《毁灭战士》_ 中,一个关卡的 BSP 树生成时间需要 8 秒,全部关卡合计共需 11 分钟 [5][10]。之所以生成时间较长,部分原因在于卡马克所用的 BSP 生成算法,该算法尝试使用各种启发式方法找出“高质量” BSP 树。在运行时,8 秒的延时可能让人无法接受;但是在线下等 8 秒,时间并不算长,尤其是考虑到 BSP 树提升了渲染器的性能。每个关卡生成的 BSP 树将在游戏启动时作为关卡数据载入。
|
||||
实际上,“将 BSP 树引入 《毁灭战士》”意味着将 BSP 树生成器引入 《毁灭战士》 的关卡编辑器中。《毁灭战士》 的关卡制作完成之时,BSP 树就会在关卡几何图形的基础上生成。根据程序员法比安·桑格勒德的说法,在原版 《毁灭战士》 中,一个关卡的 BSP 树生成时间需要 8 秒,全部关卡合计共需 11 分钟 [5][10]。之所以生成时间较长,部分原因在于卡马克所用的 BSP 生成算法,该算法尝试使用各种启发式方法找出“高质量” BSP 树。在运行时,8 秒的延时可能让人无法接受;但是在线下等 8 秒,时间并不算长,尤其是考虑到 BSP 树提升了渲染器的性能。每个关卡生成的 BSP 树将在游戏启动时作为关卡数据载入。
|
||||
|
||||
卡马克非常赞赏 1980 年论文中提出的 BSP 树算法,因为在 _《毁灭战士》_ 开始运行时,当前关卡的 BSP 树就会读取到内存中,渲染器通过 BSP 树由前向后绘制物体,而非由后向前进行绘制。福克斯、凯德姆以及内勒在那篇论文中演示了 BSP 树可用于执行由后向前的画家算法,但是画家算法会造成许多重复的绘制任务,对于与 IBM 机器兼容的个人电脑来说负担较大。因此,_毁灭战士_ 的渲染器换了个方向,首先绘制距离玩家较近的图形,之后再绘制离玩家较远的。采用这种相反的顺序,更有利于 BSP 树的应用,因为在树的每个节点都可以进行反向遍历。为了避免绘制出来的远处图形遮挡到近处的图形,_《毁灭战士》_ 的渲染器使用了一种内置的 Z 缓冲器,这种缓冲器不仅具备普通 Z 缓冲器的优势,而且对内存的要求也较低。Z 缓冲器有两组数组,一组记录水平方向的遮挡关系,另一组自屏幕由上及下记录垂直方向的遮挡关系。_《毁灭战士》_ 的渲染器就算不使用真正的 Z 缓冲器也无伤大雅,因为从技术上来看它并不是真正的 3D 游戏。BSP 树数据结构的成本虽然不高,但却能够起作用,其原因在于 _《毁灭战士》_ 不会发生以下问题:水平方向的遮挡数组能够运行,是因为该游戏中没有倾斜的墙体;垂直方向的遮挡数组能够运行,是因为该游戏不存在有着一上一下两扇窗户的墙体。
|
||||
卡马克非常赞赏 1980 年论文中提出的 BSP 树算法,因为在 《毁灭战士》 开始运行时,当前关卡的 BSP 树就会读取到内存中,渲染器通过 BSP 树由前向后绘制物体,而非由后向前进行绘制。福克斯、凯德姆以及内勒在那篇论文中演示了 BSP 树可用于执行由后向前的画家算法,但是画家算法会造成许多重复的绘制任务,对于与 IBM 机器兼容的个人电脑来说负担较大。因此,_毁灭战士_ 的渲染器换了个方向,首先绘制距离玩家较近的图形,之后再绘制离玩家较远的。采用这种相反的顺序,更有利于 BSP 树的应用,因为在树的每个节点都可以进行反向遍历。为了避免绘制出来的远处图形遮挡到近处的图形,《毁灭战士》 的渲染器使用了一种内置的 Z 缓冲器,这种缓冲器不仅具备普通 Z 缓冲器的优势,而且对内存的要求也较低。Z 缓冲器有两组数组,一组记录水平方向的遮挡关系,另一组自屏幕由上及下记录垂直方向的遮挡关系。《毁灭战士》 的渲染器就算不使用真正的 Z 缓冲器也无伤大雅,因为从技术上来看它并不是真正的 3D 游戏。BSP 树数据结构的成本虽然不高,但却能够起作用,其原因在于 《毁灭战士》 不会发生以下问题:水平方向的遮挡数组能够运行,是因为该游戏中没有倾斜的墙体;垂直方向的遮挡数组能够运行,是因为该游戏不存在有着一上一下两扇窗户的墙体。
|
||||
|
||||
剩下比较棘手的问题是如何将 _《毁灭战士》_ 中处于运动中的角色融入到借助 BSP 树绘制的静止的关卡几何图形中。该游戏中的敌人不可能纳入 BSP 树之中,因为他们会移动,而 BSP 树只对静止的几何形状起作用。所以渲染器首先绘制静止的关卡几何图形,同时与另一个内存使用效率较高的数据结构协作,记录屏幕上分割出来用于绘制的区域。之后,渲染器按照由后往前的顺序绘制敌人,并消除被屏幕上的区域遮挡住的敌人。这一过程与使用 BSP 树进行渲染相比,效果稍差一些。但是由于关卡中能看到的敌人的数量少于几何图形的数量,所以速度问题并没有那么重要。
|
||||
剩下比较棘手的问题是如何将 《毁灭战士》 中处于运动中的角色融入到借助 BSP 树绘制的静止的关卡几何图形中。该游戏中的敌人不可能纳入 BSP 树之中,因为他们会移动,而 BSP 树只对静止的几何形状起作用。所以渲染器首先绘制静止的关卡几何图形,同时与另一个内存使用效率较高的数据结构协作,记录屏幕上分割出来用于绘制的区域。之后,渲染器按照由后往前的顺序绘制敌人,并消除被屏幕上的区域遮挡住的敌人。这一过程与使用 BSP 树进行渲染相比,效果稍差一些。但是由于关卡中能看到的敌人的数量少于几何图形的数量,所以速度问题并没有那么重要。
|
||||
|
||||
将 BSP 树应用到 _《毁灭战士》_ 中可谓一大成功。卡马克能够想到 BSP 树是解决 VSD 问题的最佳方案,无疑非常高明。但是这可以称得上是天才之举吗?
|
||||
将 BSP 树应用到 《毁灭战士》 中可谓一大成功。卡马克能够想到 BSP 树是解决 VSD 问题的最佳方案,无疑非常高明。但是这可以称得上是天才之举吗?
|
||||
|
||||
桑格勒德在其关于 _《毁灭战士》_ 游戏引擎的书中引用了罗梅洛的话:内勒的论文《构建高质量的分割树》主要讲述使用 BSP 树消除 3D 模型的背面。[6][11] 根据罗梅洛所言,卡马克认为这种算法对 _《毁灭战士》_ 依然有效,所以他放手一试,将 BSP 技术应用到了该游戏中。不过这话说得有些奉承的意味——意在暗示卡马克在别人仍然使用 BSP 树渲染静止的场景时,发现该技术可以用于实时游戏领域。在 _《Doom 启示录》_ 也有给卡马克戴高帽的故事。该书作者库什纳认为,卡马克在阅读内勒的论文之后,问了自己,“如果使用 BSP 技术创造一整个虚拟世界,而不仅仅是一张 3D 图像,会怎么样呢?” [7][12]。
|
||||
桑格勒德在其关于 《毁灭战士》 游戏引擎的书中引用了罗梅洛的话:内勒的论文《构建高质量的分割树》主要讲述使用 BSP 树消除 3D 模型的背面。[6][11] 根据罗梅洛所言,卡马克认为这种算法对 《毁灭战士》 依然有效,所以他放手一试,将 BSP 技术应用到了该游戏中。不过这话说得有些奉承的意味——意在暗示卡马克在别人仍然使用 BSP 树渲染静止的场景时,发现该技术可以用于实时游戏领域。在 _《Doom 启示录》_ 也有给卡马克戴高帽的故事。该书作者库什纳认为,卡马克在阅读内勒的论文之后,问了自己,“如果使用 BSP 技术创造一整个虚拟世界,而不仅仅是一张 3D 图像,会怎么样呢?” [7][12]。
|
||||
|
||||
这些“片面之词”忽视了 BSP 树的发展历史。当美国空军研究人员开始意识到场景分割可能会加快渲染任务的时候,他们就对提升 _实时_ 渲染的速度产生了兴趣,毕竟他们当时想要开发出飞行模拟器。1980 年,同样的案例再次出现在了福克斯等人的论文中,他们探讨了 BSP 树如何应用于飞行模拟器中,帮助飞行员进行训练:重复将飞机降至同一空港。由于空港的地形不会发生改变,BSP 树只需生成一次,即可一劳永逸。很明显,他们考虑的是实时模拟。在论文的引言部分,福克斯等人还谈到实时图形系统必须在至少 1/30 秒内生成一张图像,由此介绍了他们的研究动机。
|
||||
|
||||
因此,卡马克不是第一个想到在实时图形模拟中应用 BSP 树的人。诚然,设想与付诸实践是两码事。但是即使在实施的过程中,卡马克受到的帮助与指导可比人们想象中的要多得多。至少是到这篇文章写成之时,BSP 树的 [维基百科词条][13] 页面显示,卡马克参考了 1991 年陈和戈登的一篇论文以及 1990 年的一本教材 _《计算机图形学:原理及实践》_。尽管该页面并未提供引用信息,但是基本上不会出错。陈和戈登的论文介绍了运用 BSP 树由前向后的渲染方法,这种方法与 _《毁灭战士》_ 用到的方法基本一致,还包括我称之为“内置缓冲器”的数据结构,可用于防止远处的图形在绘制时遮挡近处的图形。_《计算机图形学:原理及实践》_ 详细介绍了 BSP 树以及一些构建并展示 BSP 树的伪代码(非常感谢我大学的图书馆,让我能够一睹这本教材的 1990 年的版本)。因为这本书是计算机图形学的经典之作,所以卡马克很可能也有一本。
|
||||
因此,卡马克不是第一个想到在实时图形模拟中应用 BSP 树的人。诚然,设想与付诸实践是两码事。但是即使在实施的过程中,卡马克受到的帮助与指导可比人们想象中的要多得多。至少是到这篇文章写成之时,BSP 树的 [维基百科词条][13] 页面显示,卡马克参考了 1991 年陈和戈登的一篇论文以及 1990 年的一本教材 _《计算机图形学:原理及实践》_。尽管该页面并未提供引用信息,但是基本上不会出错。陈和戈登的论文介绍了运用 BSP 树由前向后的渲染方法,这种方法与 《毁灭战士》 用到的方法基本一致,还包括我称之为“内置缓冲器”的数据结构,可用于防止远处的图形在绘制时遮挡近处的图形。_《计算机图形学:原理及实践》_ 详细介绍了 BSP 树以及一些构建并展示 BSP 树的伪代码(非常感谢我大学的图书馆,让我能够一睹这本教材的 1990 年的版本)。因为这本书是计算机图形学的经典之作,所以卡马克很可能也有一本。
|
||||
|
||||
然而,卡马克发现自己遇到一个新问题:如何让第一人称射击游戏在一台 CPU 甚至都无法进行浮点操作的电脑上运行呢?通过调查研究,他证明了 BSP 树的数据结构非常适用于实时游戏渲染。尽管 BSP 树早已提出,而且到了卡马克的时代,相关理论已经非常成熟了,但我始终认为,卡马克的做法可谓惊人之壮举。也许,得到人们称誉的应该是整个 _《毁灭战士》_ 的游戏引擎,毕竟它的确非常精致。我在前文也提及过,但是桑格勒德的 _《游戏引擎黑皮书:毁灭战士》_ 很好地讲解了这款游戏引擎的非凡之处以及这些优势相互契合之法。要明白,VSD 问题只是卡马克在编写 _《毁灭战士》_ 游戏引擎时需要解决的诸多问题之一。不得不说,面对不为大多数程序员所知的复杂的数据结构,卡马克能够查阅相关文献,将其付诸实践,仅此一点就足以说明其技术之精湛、匠心之独到。
|
||||
然而,卡马克发现自己遇到一个新问题:如何让第一人称射击游戏在一台 CPU 甚至都无法进行浮点操作的电脑上运行呢?通过调查研究,他证明了 BSP 树的数据结构非常适用于实时游戏渲染。尽管 BSP 树早已提出,而且到了卡马克的时代,相关理论已经非常成熟了,但我始终认为,卡马克的做法可谓惊人之壮举。也许,得到人们称誉的应该是整个 《毁灭战士》 的游戏引擎,毕竟它的确非常精致。我在前文也提及过,但是桑格勒德的 _《游戏引擎黑皮书:毁灭战士》_ 很好地讲解了这款游戏引擎的非凡之处以及这些优势相互契合之法。要明白,VSD 问题只是卡马克在编写 《毁灭战士》 游戏引擎时需要解决的诸多问题之一。不得不说,面对不为大多数程序员所知的复杂的数据结构,卡马克能够查阅相关文献,将其付诸实践,仅此一点就足以说明其技术之精湛、匠心之独到。
|
||||
|
||||
_如果你喜欢这篇文章,欢迎关注推特 [@TwoBitHistory][14],也可通过 [RSS feed][15] 订阅,获取最新文章(每四周更新一篇)。_
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user