PART 4
This commit is contained in:
Xingyu Wang 2022-08-19 11:04:49 +08:00
parent 2fb12abd63
commit c6322093cd

View File

@ -7,7 +7,7 @@
[#]: publisher: " " [#]: publisher: " "
[#]: url: " " [#]: url: " "
在《毁灭战士》中应用二叉空间分割技术是何等天才之举? 在《毁灭战士》中应用二叉空间分割BSP是何等天才之举?
====== ======
1993 年,游戏开发公司 id Software 发行了一款第一人称射击游戏 《<ruby>毁灭战士<rt>DOOM</rt></ruby>》,游戏一经发行迅速爆火。在今天看来,《毁灭战士》可谓有史以来最具影响力的游戏之一。 1993 年,游戏开发公司 id Software 发行了一款第一人称射击游戏 《<ruby>毁灭战士<rt>DOOM</rt></ruby>》,游戏一经发行迅速爆火。在今天看来,《毁灭战士》可谓有史以来最具影响力的游戏之一。
@ -100,30 +100,24 @@ BSP 树是计算机图形领域最具挑战性难题的解决方案之一。举
别忘了,卡马克首次为 《毁灭战士》 设计渲染器时通过让渲染器渲染玩家所在房间之外的临近房间试图为关卡几何图形建立一套渲染顺序。对此BSP 树是个不错的选择因为在玩家进入之前的房间区域BSP 树能够避免让渲染器重复劳动,从而节省 CPU 资源。 别忘了,卡马克首次为 《毁灭战士》 设计渲染器时通过让渲染器渲染玩家所在房间之外的临近房间试图为关卡几何图形建立一套渲染顺序。对此BSP 树是个不错的选择因为在玩家进入之前的房间区域BSP 树能够避免让渲染器重复劳动,从而节省 CPU 资源。
实际上,“将 BSP 树引入 《毁灭战士》”意味着将 BSP 树生成器引入 《毁灭战士》 的关卡编辑器中。《毁灭战士》 的关卡制作完成之BSP 树就会在关卡几何图形的基础上生成。根据程序员法比安·桑格勒德的说法,在原版 《毁灭战士》 中,一个关卡的 BSP 树生成时间需要 8 秒,全部关卡合计共需 11 分钟 [5][10]。之所以生成时间较长,部分原因在于卡马克所用的 BSP 生成算法,该算法尝试使用各种启发式方法找出“高质量” BSP 树。在运行时8 秒的延时可能让人无法接受;但是在线下等 8 秒,时间并不算长,尤其是考虑到 BSP 树提升了渲染器的性能。每个关卡生成的 BSP 树将在游戏启动时作为关卡数据载入。 实际上,“将 BSP 树引入 《毁灭战士》”意味着将 BSP 树生成器引入 《毁灭战士》 的关卡编辑器中。当完成一个《毁灭战士》 的关卡制作时BSP 树就会在关卡几何图形的基础上生成。根据程序员<ruby>法比安·桑格勒德<rt>Fabien Sanglard</rt></ruby>的说法,在原版 《毁灭战士》 中,一个关卡的 BSP 树生成时间需要 8 秒,全部关卡合计共需 11 分钟 [^5]。之所以生成时间较长,部分原因在于卡马克所用的 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] 根据罗梅洛所言,卡马克认为这种算法对 《毁灭战士》 依然有效,所以他放手一试,将 BSP 技术应用到了该游戏中。不过这话说得有些奉承的意味 —— 意在暗示卡马克在别人仍然使用 BSP 树渲染静止的场景时,发现该技术可以用于实时游戏领域。在 《Doom 启示录》 也有给卡马克戴高帽的故事。该书作者库什纳认为,卡马克在阅读内勒的论文之后,问了自己,“如果使用 BSP 技术创造一整个虚拟世界,而不仅仅是一张 3D 图像,会怎么样呢?” [^7]。
这些“片面之词”忽视了 BSP 树的发展历史。当美国空军研究人员开始意识到场景分割可能会加快渲染任务的时候,他们就对提升 _实时_ 渲染的速度产生了兴趣,毕竟他们当时想要开发出飞行模拟器。1980 年,同样的案例再次出现在了福克斯等人的论文中,他们探讨了 BSP 树如何应用于飞行模拟器中,帮助飞行员进行训练:重复将飞机降至同一空港。由于空港的地形不会发生改变BSP 树只需生成一次,即可一劳永逸。很明显,他们考虑的是实时模拟。在论文的引言部分,福克斯等人还谈到实时图形系统必须在至少 1/30 秒内生成一张图像,由此介绍了他们的研究动机 这些“片面之词”忽视了 BSP 树的发展历史。当美国空军研究人员开始意识到场景分割可能会加快渲染任务的时候,他们就对提升 _实时_ 渲染的速度产生了兴趣,毕竟他们当时在试图创建一个飞行模拟器。1980 年,同样的案例再次出现在了福克斯等人的论文中,他们探讨了 BSP 树如何应用于飞行模拟器中,帮助飞行员进行训练:飞行员用它来反复练习将飞机降至同一空港。由于空港的地形不会发生改变BSP 树只需生成一次,即可一劳永逸。很明显,他们考虑的是实时模拟。在论文的引言部分,福克斯等人还谈到实时图形系统必须在至少 1/30 秒内生成一张图像,由此激励了他们的研究
因此,卡马克不是第一个想到在实时图形模拟中应用 BSP 树的人。诚然设想与付诸实践是两码事。但是即使在实施的过程中卡马克受到的帮助与指导可比人们想象中的要多得多。至少是到这篇文章写成之时BSP 树的 [维基百科词条][13] 页面显示,卡马克参考了 1991 年陈和戈登的一篇论文以及 1990 年的一本教材 _《计算机图形学原理及实践》_。尽管该页面并未提供引用信息,但是基本上不会出错。陈和戈登的论文介绍了运用 BSP 树由前向后的渲染方法,这种方法与 《毁灭战士》 用到的方法基本一致,还包括我称之为“内置缓冲器”的数据结构,可用于防止远处的图形在绘制时遮挡近处的图形。_《计算机图形学:原理及实践》_ 详细介绍了 BSP 树以及一些构建并展示 BSP 树的伪代码(非常感谢我大学的图书馆,让我能够一睹这本教材的 1990 年的版本)。因为这本书是计算机图形学的经典之作,所以卡马克很可能也有一本。 因此,卡马克不是第一个想到在实时图形模拟中应用 BSP 树的人。诚然设想与付诸实践是两码事。但是即使在实施的过程中卡马克受到的帮助与指导可比人们想象中的要多得多。至少是到这篇文章写成之时BSP 树的 [维基百科词条][13] 页面显示,卡马克参考了 1991 年<ruby><rt>Chen</rt></ruby><ruby>戈登<rt>Gordon</rt></ruby>的一篇论文以及 1990 年的一本教材 《计算机图形学:原理及实践》。尽管该页面并未提供引用信息,但它可能是真的。陈和戈登的论文介绍了运用 BSP 树由前向后的渲染方法,这种方法与 《毁灭战士》 用到的方法基本一致,还包括我称之为“隐式 Z 缓冲区”的数据结构,可用于防止远处的图形在绘制时遮挡近处的图形。《计算机图形学:原理及实践》 详细介绍了 BSP 树以及一些构建并展示 BSP 树的伪代码(非常感谢我大学的图书馆,让我能够一睹这本教材的 1990 年的版本)。因为这本书是计算机图形学的经典之作,所以卡马克很可能也有一本。
然而,卡马克发现自己遇到一个新问题:如何让第一人称射击游戏在一台 CPU 甚至都无法进行浮点操作的电脑上运行呢?通过调查研究,他证明了 BSP 树的数据结构非常适用于实时游戏渲染。尽管 BSP 树早已提出,而且到了卡马克的时代,相关理论已经非常成熟了,但我始终认为,卡马克的做法可谓惊人之壮举。也许,得到人们称誉的应该是整个 《毁灭战士》 的游戏引擎,毕竟它的确非常精致。我在前文也提及过,但是桑格勒德的 _《游戏引擎黑皮书:毁灭战士》_ 很好地讲解了这款游戏引擎的非凡之处以及这些优势相互契合之法。要明白VSD 问题只是卡马克在编写 《毁灭战士》 游戏引擎时需要解决的诸多问题之一。不得不说,面对不为大多数程序员所知的复杂的数据结构,卡马克能够查阅相关文献,将其付诸实践,仅此一点就足以说明其技术之精湛、匠心之独到。 然而,卡马克发现自己遇到一个新问题:如何让第一人称射击游戏在一台 CPU 甚至都无法进行浮点操作的电脑上运行呢?通过调查研究,他证明了 BSP 树的数据结构非常适用于实时电子游戏渲染。尽管 BSP 树早已提出,而且到了卡马克的时代,相关理论已经非常成熟了,但我始终认为,卡马克的做法可谓惊人之壮举。也许,得到人们称誉的应该是整个 《毁灭战士》 的游戏引擎,它的确非常精致。我在前文也提及过,但是桑格勒德的 《游戏引擎黑皮书:毁灭战士》 很好地讲解了这款游戏引擎的非凡之处以及这些优势相互契合之法。要明白VSD 问题只是卡马克在编写 《毁灭战士》 游戏引擎时需要解决的诸多问题之一。不得不说,面对不为大多数程序员所知的复杂的数据结构,卡马克能够查阅相关文献,将其付诸实践,仅此一点就足以说明其技术之精湛、匠心之独到。
_如果你喜欢这篇文章欢迎关注推特 [@TwoBitHistory][14],也可通过 [RSS feed][15] 订阅获取最新文章每四周更新一篇。_ _如果你喜欢这篇文章欢迎关注推特 [@TwoBitHistory][14],也可通过 [RSS feed][15] 订阅获取最新文章每四周更新一篇。_
_TwoBitHistory 文章回顾……_
> 我曾想花上一段时间深入了解 GNU Readline所以我以此为主题写了一篇新博客包括在与 Readline 库(以及 Bash的维护者切特·雷米通过邮件交流时了解到的一些趣事<https://t.co/wnXeuyjgMx>
>
> — TwoBitHistory (@TwoBitHistory) [2019 年 8 月 22 日][16]
[^1]: Michael Abrash, “Michael Abrashs Graphics Programming Black Book,” James Gregory, accessed November 6, 2019, <http://www.jagregory.com/abrash-black-book/#chapter-64-quakes-visible-surface-determination>.  [^1]: Michael Abrash, “Michael Abrashs Graphics Programming Black Book,” James Gregory, accessed November 6, 2019, <http://www.jagregory.com/abrash-black-book/#chapter-64-quakes-visible-surface-determination>. 
[^2]: R. Schumacher, B. Brand, M. Gilliland, W. Sharp, “Study for Applying Computer-Generated Images to Visual Simulation,” Air Force Human Resources Laboratory, December 1969, accessed on November 6, 2019, <https://apps.dtic.mil/dtic/tr/fulltext/u2/700375.pdf>.  [^2]: R. Schumacher, B. Brand, M. Gilliland, W. Sharp, “Study for Applying Computer-Generated Images to Visual Simulation,” Air Force Human Resources Laboratory, December 1969, accessed on November 6, 2019, <https://apps.dtic.mil/dtic/tr/fulltext/u2/700375.pdf>. 
[^3]: Henry Fuchs, Zvi Kedem, Bruce Naylor, “On Visible Surface Generation By A Priori Tree Structures,” ACM SIGGRAPH Computer Graphics, July 1980.  [^3]: Henry Fuchs, Zvi Kedem, Bruce Naylor, “On Visible Surface Generation By A Priori Tree Structures,” ACM SIGGRAPH Computer Graphics, July 1980. 
@ -132,9 +126,6 @@ _TwoBitHistory 文章回顾……_
[^6]: Sanglard, 200.  [^6]: Sanglard, 200. 
[^7]: David Kushner, Masters of Doom (Random House Trade Paperbacks, 2004), 142.  [^7]: David Kushner, Masters of Doom (Random House Trade Paperbacks, 2004), 142. 
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
via: https://twobithistory.org/2019/11/06/doom-bsp.html via: https://twobithistory.org/2019/11/06/doom-bsp.html
@ -142,7 +133,7 @@ via: https://twobithistory.org/2019/11/06/doom-bsp.html
作者:[Two-Bit History][a] 作者:[Two-Bit History][a]
选题:[lujun9972][b] 选题:[lujun9972][b]
译者:[aREversez](https://github.com/aREversez) 译者:[aREversez](https://github.com/aREversez)
校对:[校对者ID](https://github.com/校对者ID) 校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出