《塞尔达传说:荒野之息》超长干货技术分析 神作是这样炼成的

这篇文章的目的是为了让更多的人接触到其他人不打算费心去调查的,游戏中的技术成就。

《塞尔达传说:荒野之息》超长干货技术分析 神作是这样炼成的

游民星空

下载游民App,掌握一手游戏情报

《塞尔达传说:荒野之息》超长干货技术分析 神作是这样炼成的

未来游戏研究所 未来游戏研究所 2019-08-08 20:29
0

作者:未来游戏研究所

  我其实很久以前就想做一篇正式的《塞尔达传说:荒野之息》引擎分析文章了,但一直没时间去弄。然而,现在Switch有了新的视频录制功能后,我想这是一个完美的时机来重游这款游戏并通过我上传到Twitter上的视频来分享我的想法(本文中以动态图与静态图代替)。

游民星空
《塞尔达传说:荒野之息》

  我将先从我的研究结果摘要开始,但我也会在文章的后面对每一个技术特性进行细分以便通俗易懂。同时我也会尽可能避免出现重复内容。比如说像是Digital Foundry这样的已经分析了引擎的一部分特性,那我就不会再在这里提及到了。这篇帖子的目的是为了让更多的人接触到其他人不打算费心去调查的,游戏中的技术成就。

总之,这里就是这款引擎特性的总结:

  • Global Illumination | 全局光照 (更具体来讲,是光能传递)
  • Local Reflections | 局部反射 (由菲涅尔反射计算)
  • Physically-based Rendering | 基于物理的渲染
  • Emissive materials/area lights | 自发光材质/区域光源
  • Screen Space Ambient Occlusion | 屏幕空间环境光遮蔽
  • Dynamic Wind Simulation system | 动态风力模拟系统
  • Real-time cloud formation | 实时云体变形 (受风力影响)
  • Rayleigh scattering/Mie Scattering | 瑞利散射/米氏散射
  • Full Volumetric Lighting | 完整体积光照
  • Bokeh DOF and approx. of Circle of Confusion | Bokeh景深与模糊圈的近似值
  • Sky Occlusion and Dynamic Shadow Volumes | 天空遮蔽与动态阴影体
  • Aperture Based Lens Flares | 基于光圈的镜头光晕
  • Sub-surface Scattering | 次表面散射
  • Dynamically Localized Lightning Illumination | 动态局部闪电照明
  • Per-Pixel Sky Irradiance | 逐像素天空辐照度
  • Fog inscatter | 雾光散射
  • Particle Lights | 粒子光源
  • Puddle formation and evaporation | 水坑的形成与蒸发

光影:

Global Illumination/Radiosity | 全局光照/光能传递

  首先我想要声明一点,所有所谓的实时全局光照方案都是以某种方式伪造出来的,都具有着不同程度的准确性。任何仅仅因为没有使用路径追踪之类的而忽略了《塞尔达:荒野之息》中的全局光照方案的人们应该仔细想想自己究竟在说些什么。最重要的一点是,这一切都是实时渲染的;这不仅仅是烘培入纹理中的光照,这对于一款开放世界游戏来说(尤其是在Wii U上)非常令人钦佩。

游民星空

  那么,光能传递到底是个什么东西?在3D图形渲染中,它是从不同表面反射的光,并在这个过程中讲颜色信息从一个表面传输到另一个表面的全局光照近似法。光能传递越是准确,为了传输适当的颜色就需要计算更多的反射光。

  在《荒野之息》中的引擎用的是光照探针在整个环境中收集在光照探针附近不同表面的颜色信息。并没有什么模拟反射光,只是一个给定区域中基本颜色的一些近似值。《荒野之息》用于计算此信息的算法尚不清楚,但我的最佳猜测是球谐函数或之类的东西,基于颜色平均值与光能传递局部化。与《超级马里奥:奥德赛》不同,《荒野之息》中的光能传递并非二进制而是粒子。从光照探针计算的照明信息似乎与LOD系统在同一个渲染管线层次捆绑串流,使得其效率极高。

  观察建议:注意当相机靠近该区域时,岩石悬崖是如何从草地上接收到绿色色调的。

  起初我假设可能整个环境中都有放置球谐函数来收集色彩采样,因为当林克在整个环境中移动时,它似乎会更新为基本颜色。然而,经过进一步调查后,我现在知道了那些基本颜色反射是由于环境中缺乏颜色变化。当我在一个彼此相邻的许多不同颜色表面的区域测试全局光照时,其全局光照系统是如何运作的就变得豁然开朗了。注意林克在接触红墙时,其颜色是如何传递到面向相反方向上所有表面上的。

  在红墙相反方向的绿墙也是如此(尽管效果并不是很强烈,因为探针更靠近红墙,因此红墙的颜色本身反射更强烈)。事实上,在任何给定的点上,这在各个方向上都会发生。地面向上传递颜色,而林克头部正上方的任何天花板或是彩色表面都会传递其颜色。探针不断地动态的采样并传递颜色(我们可以认为这就是反射光了),因为探针会因为新的传递而拾取更多的颜色,并且还必须对他们进行采样。最后,最终结果将会停止改变,因为最靠近探针的样本将具有最主要的颜色,无论颜色转移量如何。这一过程井然有序,但非常局部化且速度相当的快。探针具有有限的采样范围,并将这些结果应用于世界空间中的材质上。由于如此般的效率,探针能够近似出许多反射光的效果,但只有在距离探针最近的区域中看起来准确。

  这是一个非常重要的发现。

游民星空
(靠近红墙时其他材质也"染"成红色)

游民星空
(靠近绿墙时其他材质也"染"成绿色)

  全局光照实际上会近似多次反射。在林克的头部上有一个光照探针可以对环境中的大多数材质的色彩进行采样。然后,每一个采样的颜色被传递并以相反的方向反射。有趣的是,强度有被考虑为因素,其受到探针最接近的表面以及反射光的强度影响。

  在户外可能看起来效果不太明显,但当有多个相邻的表面时,全局光照的效果看起来很不错。

Local Reflections | 局部反射

  那么,自从我开始分析这款游戏以来,总是让我头疼的一个区域似乎就是局部反射了。有着如此多看似不一致的情况,因为我的理论最初满天飞。现在我可以自信的说,我已经解开了局部反射是如何运作背后的谜团了。显然,这是一种根据具体情况而三管齐下的方案。

• Specular Lighting | 镜面光照

  阳光,天光,闪电,点光源都属于此类别。起初我以为神庙,塔也是如此(因为它们是自发光的,因此我就假设它们是区域光源),但看到神庙与塔所展现出的非常能够揭露真相的加工痕迹(artifact)时,就可以排除这一点了。不是所有发光的材质都能够照明环境,而神庙与塔可以归属于那些不能的发光材质。

• Aperture mapped reflections | 光圈映射反射

  如果这个术语对你来说感到很新颖,那可能对了。基于这款游戏的文本转储,《荒野之息》开发人员标记了他们对虚幻引擎4的场景捕获2D反射的看法。环境是这样反射出来的。林克头部(明确来讲,是光圈)上方的虚拟相机有着相对较小的视野,因此当林克移动时就会使得反射(实时显示)在它们适当的空间内移动,直到光圈再次捕获环境。你可以在以下的视频中看到这类的加工痕迹与视野。

• Screen Space Reflections | 屏幕空间反射

  只有那种看起来像层压材质的才会使用这种模型,而这些仅限于神庙之中。在光泽贴图中的一个数值告诉引擎仅对这些材质使用屏幕空间反射。它们会反射屏幕上的任何内容,能够在任何材质的入射余角看到。然而,这些材质上同样也有使用光圈映射来进行环境反射,这也是让我感到迷惑的源头之一。这些材质反射的不协调表现使得我对神庙外的其他材质也做出了假想。值得庆幸的是,我们把这一点理清了。

  观察建议:看看林克的反射与蓝灯的反射的对比。林克必须得在屏幕上才能显示出其反射,而蓝灯不需要在屏幕上也能显示出反射。


(屏幕空间反射+镜面高光)

  局部反射之谜解开了!


(正面的墙不能反射,而侧面的墙则可以)

  局部反射之谜解开了!那么,神庙材质具有一层额外的光泽反射层,但他们在外部反射上也使用了同样的反射模型。怪不得这么让人迷惑!

  使用光泽材质,可以在屏幕空间(屏幕空间反射)内捕获所有内容的反射。而使用非光泽材质(几乎所有的外部材质),使用与虚幻引擎4中所用到的场景捕获2D反射技术几乎完全相同的技术来捕获环境反射。基本上,虚拟相机(具有自己的视体与视野)位于林克的头部正上方,始终面对主相机的地平线,无论林克的定向如何(这使得有限的屏幕外反射得以实现)。然后将捕获的图像馈送到产生反射的材质中,就好像向电视发出现场直播信号。这意味着图像的馈送是以游戏所运行的任何帧率(30帧)实时投射的。这样使得材质的不同元素得以无需等待新的捕获就能更新。但是,实际捕获画面本身会以低得多的帧率(4到5帧)而更新。只要场景捕获相机从其绝对位置移动,你就能看到这一点。在更新捕获反射之前,当前捕获画面于材质内(例如,水)在相机移动的任何方向实时移动(30帧)。然而,一旦材质接收到更新的捕获,就会更正反射。这种更正的延迟是我们得以真实地了解捕获更新即沿着材质的痕迹(4到5帧)。


(桥柱的反射稍微有些延迟)

  你可以在这里看到,过时的反射仍然可以平滑地跟踪林克的行动。没有任何卡顿。然后当新的捕获更新时,反射就得以更正了。这与反射贴图的运作原理不同,反射贴图仅在贴图本身更新时才会更新反射。在这,捕获的反射显然已经过时了,但它仍然以30帧的速度改变自身的位置。

  你可以在以下动图中体会到捕获相机的FOV:


(由于没有地平线相机末尾视线的颜色反射在材质上)

  现在为什么所有非自发光材质都只有菲涅尔反射就讲得通了。使用这样的反射技术,这些是它唯一可以正常运作的角度了!

  我碰巧找到了这个拱门,并意识到了这是测量捕获相机视野的完美设置:


结合上一些基本的三角学来看

游民星空

  我估算其水平视野为大约115º。在林克还没有穿过拱门前,拱门的反射就已经离屏了,因此我们得知它肯定不是180°的视野了,因为如果是的话,拱门的反射就不会像这样出现视觉错误了。

  你还能够看到,当相机距离拱门数英尺并且垂直于拱门时,反射是倾斜的并且与视野成比例,这使得我们可以观察到它的宽度。它会测量场景捕获相机的相对水平视野。

  不过我想重申一下,这仅仅是粗略的估算,所以我可能会偏上个10°左右,但在有的角度下使用这个视野是不可能的,因此通过排除法,我们至少能有一个估算值。

Physically-based Rendering | 基于物理的渲染

  在有人问起来前,不,这并不意味着"物理上看起来正确的材质"。这只不过是应用于3D图形渲染管道的一种方法,所有的材质(纹理表面)在与光交互时独特的改变它们的行为方式。现实世界中就是这样的,这也就是为什么它被称作基于物理的渲染(基于现实世界光物理的概念)。不同的材质导致光的行为不同,也就是为什么我们能够在视觉上区分不同的表面。

  传统上,渲染管道依赖于美术师对光与不同的真实世界材质的交互方式的理解,并基于那份理解定义纹理贴图的效果。作为结果,不同的纹理表面之间存在着很多不一致性,以及它们与现实世界中的对应物相比之下(这一点是可以理解的,因为我们不能指望美术师对现实世界中的所有物质都有着百科全书般的知识)。对于PBR,光物理的基本原理是管道本身的一部分,并且所有的纹理表面都被归类为具有独特性质的材质,这些性质将导致光根据这些独特性质运转。这样使得不同表面得以放置于不同的光照条件以及动态相机角度之下,并动态的调整光与这些表面的交互方式。美术师不必像传统工作流程那样预定义这种交互方式。一切都是自动的。由于PBR的效率,开发人员更想要制作其中所有材质都有着影响光的独特性质的游戏。

游民星空
加了“光追特效”的荒野之息

游民星空
游戏原图

  在《荒野之息》中,其PBR有一点艺术天赋,因此你可能甚至不会注意到其引擎有依赖于这样的管道,因为纹理并不一定需要看起来很逼真。然而,材质上所用到的BDRFs(双向反射分布函数)使得引擎有用PBR这一点比较明确。对于每一个动态光源,它的镜面高光(光源本身显示为反射表面的部分)和这些高光的反射率/折射率是根据入射角(入射光相对于表面法线的角度)和光与之相互作用的任何材质的折射率(当光线接触其表面时,材质"弯曲"了多少的光)动态生成的。如果游戏使用的是传统管道,分配在木头与金属上的镜面高光之间就不会有太大的差异。但在这个游戏中,镜面高光的产生完全取决于光与之相互作用的材质。

  另一个表明《荒野之息》使用PBR的关键因素是所有材质上的Fresnel(s不发音) | 菲涅尔反射。首先,大部分使用传统管道的游戏甚至都不会用上菲涅尔反射,因为这样还不如直接用PBR了。正如我之前在讨论局部反射时所解释的那样,菲涅尔反射在入射余角处变得可见(入射光几乎与观察者/相机的视角相互作用的表面平行的角度)。根据菲涅尔反射系数,所有材质在入射余角下都达到了100%的反射率,但反射率的有效性将取决于材质的粗糙度。因此,程序员可以区分"反射率"与"折射率"。一些材质反射所有方向的光(漫反射材质)。

游民星空
加了“光追特效”的荒野之息

游民星空
游戏原图

  即使在100%的反射率下,100%的光也可能从整个表面区域反射出来,但并非所有光都在同一方向上反射,因此光线均匀分布,而你看不到任何镜面反射(表面周围的镜像)。其他材质只会反射入射光相反方向的入射光(镜面材质),因此你只能在适当的角度看到反射,接近90%的光都被反射了。漫反射和镜面反射材质的反射率即便是在入射余角下,其反射率(材质反射入射光能力的有效性)也不总是100%,这就是为什么在入射余角下所有材质都看不到完美的镜面反射,哪怕是在现实世界中也是如此。菲涅尔反射的清晰度将随着产生反射的材质而变化。

  观察建议:注意桶子木头上的绿色光源是如何在所有角度看起来都是相同的,而这一相同的绿色光源似乎还改变了金属桶箍(桶上的金属圆圈)的反射。

相关资讯请关注:塞尔达传说:荒野之息专区

责任编辑:小熊桑

APP精彩推荐打开游民APP查看更多

相关内容 打开游民APP查看更多

在线玩推荐更多