GameRes游资网

 找回密码
 立即注册
返回列表
查看: 1229|回复: 1

《守墓人》主程:如何用像素风做出真实的游戏世界

[复制链接]
发表于 2018-11-6 10:22:09 | 显示全部楼层 |阅读模式
游戏程序
平台类型: PC/兼容机 
程序设计: 设计思想/框架 算法逻辑/智能AI 2D图形 3D图形 
编程语言:  
引擎/SDK:  
8月份的时候,有一款叫做《守墓人(Grave Keeper)》的游戏在Steam迅速成功,一天之内就进入了全球畅销榜前三。作为一款像素风模拟游戏,虽然《守墓人》开发商Lazy Bear Games只有两人组成,但却做出了非常真实的游戏效果。最近,该游戏主程序Svyatoslav Cherkasov在博客中讲述了《守墓人》像素风艺术创作背后的技术解决方案,以下是详细内容:


我希望与同行们分享的是我们在图片制作方面的技术,比如下图这张GIF:

1.gif

我们对于游戏的图形非常热衷,这也是我们投入很多时间把像素世界做到如此具有吸引力的原因,通过我们的方法,或许对你们未来的创作有帮助。

首先,我想要说的是组成我们游戏视觉效果的几个重要部分:

  • 动态环境光线实际上只是根据每天的不同时段改变光源;
  • LUT颜色校正主要用于不同时间段的光影改变;
  • 动态光源包括火炬、壁炉和灯光;
  • 正常地图:确保物体看起来有一个真实量,尤其是当光源移动的时候;
  • 光线的3D分布:以屏幕为中心的光源要合理地照亮高处物体,而且不能照亮低处的物体;
  • 阴影使用sprite做的,它们会随着光源位置转化和作出反馈;
  • 物体高空模拟主要是为了让雾气分布看起来自然;
  • 其他的东西,还包括雨、风、动画(包括树叶和草地的着色动画)等等。


接下来是细节方面的内容:

动态环境光线



这一点实际上没有什么特殊之处,夜里变暗、白天明亮,光线颜色使用Gradient编辑器做的,当夜幕降临的时候,光源不仅会变暗,还会变成蓝色调,如下图:

2.png
LUT颜色校正

LUT(即Look-up table)是颜色变化表,简单来说它就是一个三维RGB数组,每个元素都对应各自代表的RGB数值、包含与相应元素变化的颜色值。所以,如果坐标(1,1,1)有一个红点,那就意味着图片里的所有白色都会被红色代替;但如果同样的坐标(R=1,G=1,B=1)上还有一个白点,就意味着颜色不会发生改变。所以,LUT默认与特定颜色的坐标有关。我的意思是,坐标(0.4,0.5,0.8)与颜色(R=0.4,G=0.5,B=0.6)相对应。

这里需要指出的是,为了方便期间,3D问题里都通过二维方式呈现,下图就是默认LUT的视觉效果:

3.png

这样做起来简单、用起来也简单,工作效率非常高。

这样设置起来也很简单,你把一张游戏图给美术师,告诉他,“把它做成夜晚的效果”,然后把所有颜色层加上默认LUT,就可以得到夜晚LUT了。

我们的美术师对此非常热衷,他为一天当中的不同时间创作了10种不同的LUT,我们最终的LUT看起来是这样的:

4.png

所以,即便是同一个位置,在每天的不同时段也会出现不同的视觉效果:

5.png

这张图还展示了每天不同时段的光线密度变化。

动态光源和常规地图

我们使用的是常规光源,也就是Unity默认光源,而且每个sprite都有自己的常规地图:

6.gif

这些常规地图画起来很容易,一个美术师通常只需要用色刷在四面画出亮色就可以了:

7.png

随后我们用脚本把它们放到常规地图:

8.png

如果你想用一个着色器或者软件实现,可以留意Sprite Lamp。

3D光线模拟

从这里开始,制作起来就变得稍微复杂了,你不能只点亮sprite,一个sprite在光源前方还是后方位置非常重要,我们不妨看看下面这张图:

9.png

这两棵树都和光源的距离相等,但后面这棵树被照亮了,而前面的树确没有亮,因为摄像头在前面这棵树的暗面。

实际上这个问题很容易解决,有一个着色器可以计算垂直轴上的光源与sprite之间的距离,如果距离值为正(光源在前),我们就会像往常一样照亮它,但如果为负值(即光源在后),那么光照就会基于距离而不断减弱。所以,光源照在不同位置的物体上是需要按比率的,并非简单的照亮就可以。所以,如果物体背后的光源是移动的,那么物体就会逐渐变暗,而不是立即变暗,如下面的动图所示:

10.gif

阴影处理

阴影都是围绕一个点的sprite制作的,我曾经尝试让他倾斜,但后来发现完全没有必要。

每个物体可能最多有4个阴影,太阳光照的阴影和另外三个从动态光源照出来的阴影,所以下面的图形可以展示上述概念:

11.png

实际上,对于“如何找到最近的3个光源并且计算距离和角度”这个问题,只需要在Update()运行一个脚本就能解决。

没错,考虑到加入的数学运算量,这并不是最快的方式,如果让我今天重新做它的编程,我会使用Unity Jobs System,但当时还没有这样的工具,所以我们不得不优化常规的脚本。

这里非常重要的是,我做物体旋转并不是修改旋转,而是在顶点着色器内完成的,所以旋转并不是在此时发生。你只需要对一个物体加入参数(我使用了颜色通道,毕竟所有的阴影都是黑色的),着色器负责物体旋转,我们发现这样做的效率很高,因为你可以不再使用Unity几何体。

当然,这种方式有一些不利影响,阴影是需要调整的(有时候需要你画出来),而且与物体是相对独立的,实际上,我们做了大概10中常用的物体(根据薄厚程度等因素)。

另一个不利之处就是在单轴拉伸的物体阴影比较难做,比如下图的篱笆:

12.gif

这个效果并不理想,如果让它变成半透明,就会出现下面的结果:

13.gif

这是需要注意的,物体是被高度垂直扭曲的(阴影物体原本看起来像个圆环),所以旋转看起来并不像是简单的旋转,同时看着还像是做了扭曲。

迷雾与高度模拟

我们的游戏里是增加了迷雾的,常规的雾气下图当中的上半部分,而大雾效果则如下半部分:

14.png

如你们所见,树木和房屋的顶部是可以在雾气中被看到的。实际上这种效果很容易做。雾气是由所有图片中分布的平面云层组成,因此在上半部分,物体上的云层较少,而下半部分就增加了密度:

15.png

风的效果

在像素游戏里,风的效果制作完全和其他游戏不一样,因为你的选择非常少。你可以手动制作动画(由于美术师数量有限,这个方法不现实),或者做一个变形着色器,但随后你要处理一些比较丑陋的扭曲,你也可以不做任何动画,但画面看起来就会是动态而且没有活力的。

我们选择了变形着色器,效果看起来是这样的:

20181106102058.gif

如果把着色器放到网格纹理中,或许就更容易看出这个效果是怎么做的:

17.gif

还需要补充的是,我们并没有给整棵树做动画,而是只做了一部分特殊的树叶动画:

18.png

麦田里的麦穗摇动的动画制作也很简单,顶点着色器改变X轴的形状,并且把Y轴变化考虑在内,最高点的物体摇动密度最大。我们这么做的目的是让麦穗头部摇动,但根部不动。另外,摇晃的效果会根据物体移动的差异而变化。

19.gif

这个着色器还可以在你穿过麦田或者草丛的时候做出摇动的效果:

20.gif

以上就是我要分享的内容,这里我没有提到场景打造以及几何体的创作,因为内容量比较大,但除此之外,这些内容基本上涵盖了我们研发游戏过程中所使用的大多数主要解决方案,希望对你们有用。

来源:gamelook
原地址:https://mp.weixin.qq.com/s/ajrR3FqUwGYjaZP2ybscDA

发表于 2018-11-6 14:44:46 | 显示全部楼层
很棒,赞一个
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|稿件投递|广告合作|关于本站|GameRes游资网 ( 闽ICP备05005107-1 )

GMT+8, 2018-11-18 17:44

快速回复 返回顶部 返回列表