65.9K
CodeProject 正在变化。 阅读更多。
Home

移动虚拟现实渲染

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2014年10月26日

CPOL

11分钟阅读

viewsIcon

21092

downloadIcon

244

浏览器驱动、视差 3D 环境渲染的高级介绍

引言

用一个代码文件在现代设备的整个频谱上为虚拟现实 (VR) 游戏渲染图形很简单!听起来太牵强了吗?我提供了一些解释和理由,以及带有完整注释源代码的激动人心的方块游戏 Tetro 2D/3D 作为概念验证。

Title Screen

目的

我很高兴您高超的编码技能和求知欲使您超越了介绍。我们现在在这里,因为我一直着迷于我从小就知道的“虚拟现实”或 VR 的复兴。VR 在 80 年代与 Alf、Max Headroom 和其他深奥的片段一起长期腐朽,成为计算机时代曙光中未兑现的承诺。嗯,时光流逝,现在我们生活在未来,强大而廉价的计算促使 VR 重新站稳脚跟。Oculus Rift1 带来了对该技术的认知和吸引力,而 Google 的 Cardboard2 则贡献了创新和可访问性。本文旨在通过揭开 VR 图形周围的一些谜团来激发他人,并推动对 VR 持续复兴的兴趣。

Using the Code

如果您不耐烦或根本不在乎解释或理由,源代码是一个独立的 HTML 文件,“Tetro.htm”,其中嵌入了 CSS 和 JavaScript。要在 2D 模式下玩,请使用任何当前版本的浏览器(推荐 Chrome)打开文件。要在 3D 模式下玩,您还可以使用 Cardboard 或支持并排模式的 3D 显示器。如果您想阅读或编辑代码,请在任何文本编辑器中打开文件。非常简单。

2D Game Screen

为什么选择 Tetro?

俄罗斯方块的创造者 Alexey Pajitnov 无疑是编程名人堂的成员。他游戏的简单性使其成为一种理想的说明工具,但直接复制它会构成侵权。本文改用一个语义上不同的游戏,名为 Tetro。本文无意作为游戏本身的编程教程,因为 Code Project 上已有其他文章探讨游戏逻辑。我假设您已经了解四格骨牌游戏3,或者可以通过现有教程解开这个谜团。相反,我选择 Tetro 是因为它简洁的游戏逻辑,可以提高实际渲染的可见性。

原生 vs. Web

好的,您已经知道 Windows、Android、Apple 等设备以不同的方式执行,具有不同的原生处理路径。这意味着您需要多次编写应用程序才能将您的软件分发到各种设备。Web 应用程序旨在通过为程序员提供一个通用且独立于设备的运行时(很像 Java 和 JRE)来解决这个问题。虽然历史表明浏览器在 W3C 标准的实现上存在兼容性混乱和/或故意不兼容,但任何单个 Web 文件在不同浏览器之间平等渲染的整体能力都非常出色。因为我在这里演示 HTML 作为 VR 游戏的可行平台的强大功能,所以我选择只使用纯 HTML、CSS 和 JavaScript。不使用 JQuery 或其他包装器,只有散养、有机的 Web。

矢量 vs. 栅格(绘图 vs. 绘画)

正如您的经验所告诉您的,图形渲染大致有两种样式:矢量和栅格。栅格(位图)图形利用 2D 颜色对象网格连续堆叠以创建游戏显示。如果游戏的分辨率不变,那么栅格图形可能看起来令人惊叹地逼真。不幸的是,存储、传输和转换彩色网格的计算成本很高,并且需要预先存在的资产(例如背景、物品、角色和其他精灵)。这种成本乘以可玩分辨率的数量,考虑到市场上的设备分辨率范围,这个数量可能很大。

考虑到简单性和可移植源代码,我选择仅使用矢量图形来实现 Tetro。矢量图像不是颜色网格,而是小的渲染配方(想想涂色书中的连点游戏)。本质上,一系列导数或点与绘图指令一起存储。表达这些几何图形和指令只需很少的字节,矢量处理速度极快,甚至可以支持最有限的硬件(前提是设备具有足够的软件)。矢量处理的几何特性与 Tetro 的方块渲染非常吻合。

最后一个考虑是矢量图形可以缩放到任何分辨率,而不会像调整位图大小时那样发生丢失或变异。矢量图形的动态和响应式大小调整允许最大的兼容性,而不会增加成本。顺便说一句,学习有效地协同使用矢量和栅格有助于在报告系统、现代游戏和其他动态渲染解决方案中实现有意义的 GIS/地图、图形和图表绘制。

3D vs. 3D

随着近年来引入的新的 3D 技术,有时很难区分上下文,这在图形渲染方面尤其如此。在最初的 VR 大约十年后,3D 图形随着任天堂 64 和 PlayStation 等游戏机进入消费者视野。除了 2D 游戏领域中灯光和阴影等重要的深度效果外,我们还看到物体以额外的轴建模。传统侧向和俯视滚动游戏中的 X 和 Y 轴上的受限移动被添加的第三个轴 Z 所取代。Z 轴通过添加“近和远”组件创造了新的维度。在 3D 空间中存储和处理游戏对象创造了无与伦比的真实感,但仍然缺少另一种 3D。

Graphics Axes

另一种 3D 可以称为立体或视差 3D。视差是你的两只眼睛在看东西时所看到的角度差异。你的大脑不是单独分析每只眼睛的图像,而是将它们流式传输在一起,并将差异合理化为深度感知。如果你有更多的眼睛,那么你的深度感知会变得更清晰,而如果你有更少的眼睛,那么这个概念就会对你失去意义。记住,至少需要两个参考点才能减去一个并得到一个差异,这就是为什么至少需要两只眼睛才能三角测量深度。

Try Parallax, Squish Something

尽管使用了 Z 轴,但 3D 游戏机游戏类似于单眼人感知 3D 世界的方式,因为屏幕本身实际上是 2D 的。要渲染真实的 3D 模拟,当实际深度不存在时,我们需要为每只眼睛提供一个图像流,并且至少需要两只眼睛,重新进入 VR 技术。通过 VR 为每只眼睛创建不同的图像流,该技术可以同时利用游戏 3D 和视差 3D 来创造最真实的视觉体验。

VR 输出

如果您有 3D 电视,那么您可能已经用它来观看 3D 蓝光光盘。3D 蓝光(和 3D 影院)通过以全分辨率快速交替左右帧来创建视差效果。这就是为什么 3D 显示器或投影仪必须以双倍刷新率运行的原因。它依次绘制左眼看到的内容,然后绘制右眼看到的内容,但表示单个运动帧。

VR 采用了一种略微不同的策略,称为并排或 SBS 3D。SBS 将左右图像绘制在同一帧中。VR 设备在您的眼睛之间放置一个薄的物理屏障,该屏障汇聚在分隔线上。如果您玩过 View-Master 玩具,那么您已经了解这种方法的工作原理。优点是可以在正常刷新率下实现流畅的 3D,从而扩大了兼容设备的范围。

3D Game Screen

请注意,3D 显示器和电视通常支持 SBS 渲染。然而,与当前的 VR 设备不同,电视硬件将图像切成两半,并在交替帧中渲染每个拉伸的半部分。与蓝光一样,这种方法也需要双倍刷新率,因为它依次渲染左右图像。这种 SBS 渲染方法的一个问题是最终图形在水平分辨率上拉伸了整整两倍。除非您预先压缩图形以进行补偿,否则游戏将显得扭曲。

计算视差

首先要指出的是,在计算深度时,我们不关心 Y 轴值。我们需要在下巴或额头上长眼睛才能考虑高度视差,因此左右视图中的 Y 值是相同的。另一点要注意的是,所有 Z 轴值都需要转换为 X 轴偏移。这是必要的,因为 VR 设备和显示器实际上只有长度和宽度(记住深度是一种错觉)。这意味着,虽然我们可以在对象模型中拥有 Z 轴,但最终绘图必须将 Z 值转换为 X 轴。

Parallax Considerations

SBS 要求您在同一视图中渲染图像两次,每只眼睛一次。如果您对左右两半使用两个相同的图像,那么所有对象将具有相同的相对位置,并且看起来与设备屏幕在视觉上齐平。为了说明一个水平对象,下图显示了一个棕榈树的 SBS 渲染,其 X 坐标(距左边界的距离)在左右帧中都设置为 146 像素。由于棕榈树具有相等的 X 坐标,当您的大脑组合图像时,它将与设备齐平。

Render Even

然而,如果你将右侧帧的棕榈树向正 X 方向渲染,那么你的大脑会将这种差异解释为一棵更远的树。

Render Far

相反,如果您在负 X 方向渲染右侧帧的棕榈树,那么您的大脑会将这种差异解析为一棵更近的棕榈树。

Render Near

仅此而已。视差的计算只是 X 轴偏移与所需深度感知之间的一种合理关联。在现实生活中,额外的因素(例如温度、大气、重力等)会影响计算。然而,在编写游戏时,在形成深度方面更实际的问题是视觉舒适度。最终,可能需要以艺术而非数学的视角进行测试,才能渲染一个无眩晕的环境。

渲染视差

要实际将 SBS 渲染到屏幕上,我们只需循环绘制两次,每只眼睛的帧一次。在第一次迭代中,左帧的绘制不考虑 3D。当 Tetro 在 2D 模式下运行时,它实际上只是左帧的渲染,居中于屏幕。在 3D 模式下,右帧也会渲染并携带所有视差偏移,从而生成深度。为了获得这些偏移量,我们通过减去或加上来修改任何 X 坐标,具体取决于我们希望对象更近还是更远。对象模型中的 Z 坐标应该决定实际的偏移值。

Tetro 通过渲染近距离、水平和远距离对象来展示深度范围。为了提供一个远距离渲染的示例,背景星星以不同程度的距离绘制。游戏棋子、棋盘、标题和游戏统计数据都水平绘制,为了展示浅渲染,当棋盘上的线条被清除时会出现星爆。

其他注意事项

为了保持代码简单,我们没有进行一些优化。例如,完全没有理由每次都重新绘制星空背景。当没有发生变化时,每个星星的位置都会不必要地重新计算和重新绘制。使用第二个画布来渲染游戏的静态元素,然后将其分层到具有高度动态元素的画布下方,将有助于提高效率。此外,您会在 `Draw` 过程内部看到大量用于支持动态大小和布局的计算。在您自己的模拟中,您可以考虑将支持响应式 UI 的计算(例如在页面大小调整后)存储在更全局的范围内,并且仅在召唤事件发生后计算一次。

虽然本文的重点是渲染,但我想快速介绍一下音频是如何集成到这个项目中的。虽然浏览器完全能够支持所有听觉上的花哨功能,以使您的游戏流畅运行,但您会发现添加它们可能需要意想不到的修修补补和咒骂。没有一种音频格式可以转换为所有浏览器,并且任何一种格式在同一浏览器中可能会根据编码和编解码器版本而具有混合兼容性。为了帮助解决兼容性问题,JavaScript 中的 Audio 对象指定了一个函数,该函数有助于测试音频格式与客户端浏览器的兼容性。要测试 mp3 功能,您将传入“`audio/mpeg`”作为类型,任何不兼容的浏览器都将返回一个空字符串。但是,如果浏览器并非不具备功能,则会返回“probably”或“maybe”,两者都不是确切的。无论如何,尽管浏览器之间的音频支持有些模糊,但 Tetro 展示了嵌入式 WAV 和 MP3 类型以及 JavaScript 的使用,以提供音效,同时将资源依赖性保持为零。

最后一个考虑是,为 VR 编程游戏需要本文未探讨的策略。例如,通过位置感知和视差下的碰撞检测进行控制就是两个这样的例子。也许未来的文章可以探讨更多的 VR 编程策略。感谢您的阅读,祝您的项目顺利!

附加说明

历史

  • 版本 1.0
© . All rights reserved.