跳转到内容

视频游戏设计/编程/真实模拟

来自 Wikibooks,开放世界中的开放书籍

真实感(现实模拟)

[编辑 | 编辑源代码]

光线和阴影

[编辑 | 编辑源代码]

灯光和纹理

[编辑 | 编辑源代码]

光照贴图

[编辑 | 编辑源代码]

凹凸贴图

[编辑 | 编辑源代码]

法线贴图

[编辑 | 编辑源代码]

视差映射

[编辑 | 编辑源代码]
添加细节

让游戏包含一些微小的,即使重复的细节,也能提供更丰富的体验,无论是阵阵风声,一粒尘埃,垃圾桶上方的苍蝇,一片随风飘落的树叶,都可能像动态灯光一样,拥有强大的效果。

水可能是游戏中最难再现的效果,它包含反射、透明度和扭曲,像波浪、泡沫一样的高细节,并且是流体,表现得像固体和液体一样,因此,取决于你想要达到的细节水平,这不仅是一项艰巨的任务,而且如果实时完成,还会消耗大量的计算能力。

对于引擎的这一部分,我们将使用 OpenAL API。为什么?因为在选择 API 时提到了以下简单的理由:它开源、跨平台、功能强大,同时使用起来也相对容易。所以让我们开始吧...

游戏世界中所有可以发出声音的物体都有一个位置(背景音乐除外)。此外,声音还与某种触发事件相关联,因此当玩家做某些事情激活触发器时,声音就会开始播放。很简单吧!那么我们实际上如何实现这一点呢?

OpenAL 的工作原理是,有一个 source(播放的声音)和一个 listener(正在聆听的人),这两个对象可以放置在 3D 环境中的任何位置,并赋予某些属性,例如使用什么衰减模型,声音源的移动速度等,但这些我们稍后再讲。你还可以拥有许多声音源(这很合理),但只能拥有一个聆听者(这也十分合理)。当你添加 OpenAL 要播放的声音时,你需要先执行三件事:创建一个缓冲区,用于将音频数据加载到其中,然后创建一个声音源,然后将声音源与缓冲区关联起来,以便 OpenAL 知道从哪个声音源播放什么音频。因此,考虑到所有这些因素,我们将把每个声音源封装到一个 C++ 结构体中。该结构体(我们称之为 newSource)将包含声音源的位置信息,作为 sourcePos[3],一个 sourceID 和一个 bufferID,以便我们可以唯一地寻址每个声音源。

我们还需要考虑的是,由于 OpenAL 很友好地根据距离为我们衰减声音,因此我们需要让声音在玩家到达声音源的“外边界”(你再也听不到声音播放的点)时开始播放。因此,我们将在结构体中添加一个 activateDistance 值。

此外,我们还需要考虑,由于声音数据无法从硬盘上立即加载,因为与内存相比,硬盘的速度非常慢。因此,我们将在结构体中添加一个 preloadDistance 值,这样当我们在该值范围内移动时,声音就会加载到缓冲区中,当我们在 activateDistance 值范围内移动时,声音就会开始播放。很酷吧!

最后,由于我们很可能会有不止一个声音源(如果只有一个声音源,游戏就会很无聊),我们将把我们的结构体放入 C++ 向量中(如果你不知道向量是什么,它只是一个数组,但功能更多),我们称之为 pipeline。我们还需要添加一些功能,从管道中删除“静默”的声音源,并释放内存,但这我们稍后再说。

为了说明所有这些是如何结合在一起的。

这个图说明了 preloadDistanceactivateDistancesourcePos 在“游戏内”视图中的位置。

因此,概括一下这个过程

  • 当玩家进入外部红色球体时,就会创建一个新的 newSource 结构体,声音被加载到缓冲区中,并被推送到 pipeline 中。
  • 当玩家进入黄色球体时,声音就开始播放,并且当玩家朝内侧的白色球体移动时,声音会变得越来越响,直到在白色球体处达到最大音量。
  • 反过来,当玩家远离白色球体时,声音的音量会逐渐降低,直到玩家离开黄色球体,此时声音会关闭,但仍然保留在 pipeline 中。
  • 当玩家离开红色球体时,声音源就会从 pipeline 中移除并销毁(剔除),这样就不会占用不必要的内存。
华夏公益教科书