《明日之后》程序篇:末世的昼夜与天气

兔白

2022-11-161411次浏览

0评论

23收藏

9点赞

分享

《明日之后》是网易金牌研发团队历时三年打造的末世下的人类生存手游。在采集、砍树、采矿、打猎获得基本资源后,玩家可用来烹饪食物、制作武器和防具等等生存所需要的物品。游戏内有昼夜变化,在寒冷的夜里,你必须待在篝火旁或手持火把才可以避免冻伤。

本游戏主打废土合作生存玩法,以在废土中引导玩家互相帮助,克服恶劣的生存环境为主要理念。以虚拟摇杆为主要操作方式,以营地建设、地图探索、资源采集、战斗对抗等为主要手段,帮助玩家逐步提升自己的能力和庄园等级。同时,游戏还强化了玩家自主收集资源、制作工具、建设家园、营地的概念,更多的强调玩家之间的互相协作,最终经营出的专属营地。为了追求代入感,营造生存气氛,场景中的昼夜、天气都可以动态变化。接下来,网易游学特邀《明日之后》程序小姐姐从手游低成本的角度出发,聊一聊明日之后中用到的一些昼夜与天气技术。

目前PC和主机平台的很多AAA大作都已经支持昼夜变化(Time of Day)了,但在明日之后立项之初,我们还没有在手机平台上见过多少这样的游戏。主机游戏实现昼夜效果,通常是基于全场景PBR(Physically Based Rendering)、全局光照(Global Illumination)、延迟渲染(Deferred Shading)等技术的基础上去做的。

比如育碧在自家游戏里使用的基于PRT的全局光照方案,使得Far Cry、全境封锁、刺客信条等游戏能够在开放大世界体验日出日落的优秀效果[1]。EA的镜之边缘催化剂,使用Enlighten烘焙预处理的光照,运行时实时生成对应时刻的Lightmap和Light Probe。为了掩盖Light Probe的低精度,他们增加了大量的镜面反射[2]。EA还在一个实验性的项目PICA PICA中,使用了最新的 DirectX Raytracing (DXR)技术来进行全局光照、AO、阴影的计算,取得了很好的效果[3]。

但是在手机平台,由于耗电、发热、内存、硬件性能等一系列因素的限制,使得我们并不用以上的前沿方式去实现这些效果,而是要在效果和效率中做出取舍,尽量通过“0消耗”的方式来达到目的。

 天空 

由于我们是一个自由视角的3D游戏,天空成为游戏画面中的一个重要占比。传统的低消耗的天空渲染方式如下图所示,使用一张天空的图片渲染到半球上,这个半球始终挂接在相机上,包裹住玩家的视野。

这样渲染出来的天空很真实,但仅限于固定时刻。对于这种纯贴图渲染的天空,只能通过插值来实现昼夜的过渡。如果插值的贴图样本少,那么过渡期间会有明显的走样;如果插值的样本多,又会导致游戏包体增大。

图 1 贴图渲染到天空球上

或者像看火人在GDC里介绍的那样[4],让美术去编辑天空球的颜色时间轴,来实现24小时的变化。但是这样又很难达到真实的效果,而且美术工作量有些大。

最后我们所选择的方式,是基于物理的大气散射模拟[5]。这一方法被广泛应用于很多游戏中,包括前面提到的镜之边缘,而我们用一些小小的让步,使得它可以用于低端手机。我们肉眼所观察到的光照结果,由3个部分组成:L0表示直视太阳时的光照,R[L]表示来自地面的反射光,S[L]表示来自空气中的散射光。

在模拟大气散射的过程中,想要获得真实的效果,需要考虑光在传播过程中发生多次散射,以及地面中的反射光在传输过程中又散射到空气中等情况,计算非常复杂。因此,该方法对公式做了各种项进行预计算。具体的推导细节这里不赘述,感兴趣的同学可以去查阅相关的论文和源码。

预计算的结果存储在LUT(Lookup Table)中,运行时可以在Fragment Shader中访问然后渲染,能够呈现出诸如物理天空盒、空气透视、God Ray等多种效果。

图 2 Precomputed Atmospheric Scattering

但是,我们仍然无法在手游中实时渲染出来。对于物理天空盒来说,进一步的简化方法是在游戏的时刻发生变化时,将天空渲染到一张Cube Texture中,运行时只需要采样这张Cube Texture就可以了。

那么还有没有更加高效的方法呢?为了兼容低端的机型,甚至是OpenGL ES 2.0的设备,我们将天空的颜色存储在天空盒模型的顶点色中,在渲染时利用硬件的插值来生成天空盒。由于计算天空颜色这一步是在CPU进行,避免了将预处理数据存储于3D Texture中由GPU采样的方法,也就获得了更高的兼容性。

至于天空中的云,也是用了一种比较简单低成本的方案。我们以贴图的形式,贴上一圈云,让其受到场景昼夜光照的影响。这个方案的缺点是,云的光影不够真实,而且形态不会动态的变化。

图 3 明日之后的物理天空和贴图云

 场景 

场景的昼夜光照接下来会分为两个部分来讲,直接光照和间接光照。

直接光照的部分是比较简单的,由于明日之后的模型大部分是基于PBR管线制作的,具有能量守恒的特征,因此能够适应多变的光照环境。我们的美术编辑了24小时的方向光、环境光的颜色与强度,就能够实现昼夜的效果了。

图 4 天气编辑器编辑的昼夜方向光

间接光的部分会复杂一些,由于手机平台的各种限制,我们没办法做到实时GI,因此最后用的是传统的烘焙技术,用Lightmap和Light Probe来实现静态、动态模型的间接光照。但是烘焙的前提是光照环境已经确定,确定了太阳光的方向,才能知道它在场景中如何反射。

那么,要如何让烘焙结果支持昼夜呢?这里我们采用了两种方式,对于大部分野外场景,我们发现白天间接光是不明显的,而Sky Occlusion效果则重要很多。因此,我们将烘焙的Sky Occlusion单独提取出来,存储在Lightmap的Alpha通道中。渲染场景时,我们会始终将环境光乘以Sky Occlusion,Lightmap则只在晚上出现,通过静态点光、间接光来增加氛围。白天有SkyOcclusion和Ambient的存在,使得场景的暗部有了一些细节,不至于太死板。

图 5 快乐101的昼夜烘焙对比

对于城市场景,我们会为白天也烘焙一份Lightmap,然后在昼夜交替时,通过修改权重来在两份Lightmap之间来回切换。这样的话,白天的光照细节会更加丰富。

图 6 莱文市的昼夜烘焙对比

除了光照,雾也是场景渲染不可或缺的部分。前面在介绍天空时,提到了基于物理的空气透视效果。但是对于游戏而言,用这样的方式去渲染雾效消耗太大了。传统游戏一般还是使用线性雾、高度雾来实现的。那么,要如何让我们的雾看起来更加物理呢?

在Unity3D的一篇文章中,给出了不错的答案[6]。在远近方向上,根据距离采样不同的色调;在太阳附近添加光晕,模拟米氏散射效果;将低海拔处雾浓度提升,因为那里的空气微粒较多。

图 7 Atmospheric Scattering in The Blacksmith

在这篇文章的启发下,我们也为场景加入了远近区分的雾颜色。一般来说,雾的颜色推荐使用LUT进行设置,但是我们想要节省掉一次贴图的采样,并且我们需要支持设置昼夜的雾颜色,因此仅仅设置了近处雾颜色,和远处雾颜色两个值。

图 8 远近的雾有不同的颜色

而太阳附近的米氏散射,我们使用了一种比较简单粗暴的方式,在shader中判断太阳的位置,在太阳附近会使用方向光颜色作为雾的颜色。

图 9 左侧是普通雾颜色,右侧是太阳附近的雾颜色

剩下最重要的一个部分,也就是高度雾的模拟。我们参考Crytek在GDC 2007中提到的指数高度雾来实现[7]。指数高度雾其实是对前面大气散射模拟中所提及的透射比(Transmittance)公式的简化版本,考虑到了空气中的粒子密度变化,因此包含水平方向和高度方向上的光照衰减。这个公式带来的一个额外好处是,我们可以在根据时间的不同来调节雾的浓度,为昼夜效果带来更多变化,或者从玩法角度上去调整雾的效果。

图 10 高度雾效果

 天气 

天气部分,明日之后的实现相对简单一些。虽然我们有下雨、下雪、沙尘暴等天气,但都发生在特定的场景中,因此效果实现上会简单很多,我们只需要为角色模型增加动态的天气效果支持。

首先我们看看现实世界在不同天气下的表现:从下图可以看出,下雨之后,镜面反射变强了,物体的颜色变深了。那么对于PBR模型来说,我们需要做的就是调整PBR参数,修改roughness\metallic和albedo。

图 11 下过雨的街道

下雪之后的表现也可以总结为:屋檐等水平向上的表面有积雪,墙壁、树干等竖直向上的表面,基本不受影响。同样的,我们可以根据模型法线的角度,修改roughness\metallic和albedo。

图 12 下过雪的建筑群

除了上述的修改PBR参数以外,我们还为角色模型添加了专门的通道,用来控制其受天气影响的参数。美术更喜欢这样自定义的方式,而不是简单地使用向上的法线来判断。

图 13 角色的天气效果

至于雨雪效果,我们在GPU粒子和特效盒子之间选择了后者,效果上虽然不如粒子特效那样好,但是开销很低。这一方法来自一篇博客[8]中提到的” Flight simulator 2004”中的方法,让雨水贴图在一个锥形的盒子上不断流动,形成下雨的效果。使用这样的锥形盒子带来的好处是,当抬头或者低头时,雨滴能够有较好的透视效果。另外,通过增加渲染雨水的层数,可以增强下雨效果的层次感。

图 14 特效盒子

有了特效盒子之后,再叠加一些屏幕特效,比如镜头水滴、雨雾等等,就能够实现低成本的天气模拟效果了。

图 15 下雨、下雪效果

上面讲述了明日之后所使用的一些低消耗的昼夜、天气技术,我们的实现远不能说是优秀的,比如在端游逆水寒中,有非常棒的天气效果,感兴趣的同学可以移步知乎去阅读他们的分享[9]。在GDC、SIGGRAPH、github、知乎等平台上,都不断有前辈提出新颖、高效的方法供我们去学习,许多优秀的游戏也为我们带来了灵感,督促我们去改进。我们一直在迭代和优化各种画面效果,大家可以继续关注,我们会努力交出一份满意的答卷。

引用:

[1]. https://www.gdcvault.com/play/1015326/Deferred-Radiance-Transfer-Volumes-Global

[2]. https://www.ea.com/frostbite/news/lighting-the-city-of-glass

[3]. https://colinbarrebrisebois.com/category/rendering/global-illumination/

[4]. https://www.gdcvault.com/play/1022295/The-Art-of

[5]. https://github.com/ebruneton/precomputed_atmospheric_scattering

[6]. https://blogs.unity3d.com/cn/2015/05/28/atmospheric-scattering-in-the-blacksmith/

[7]. https://www.gamedevs.org/uploads/real-time-atmospheric-effects-in-games-revisited.pdf

[8]. https://seblagarde.wordpress.com/2012/12/27/water-drop-2a-dynamic-rain-and-its-effects/

[9]. https://zhuanlan.zhihu.com/p/111904859

评论 0

0/1000
网易游学APP
为热爱赋能
扫描二维码下载APP