在移动平台上打造60fps的3A游戏

https://zhuanlan.zhihu.com/p/28109173

就在近期的Unite Europe 2017 中,有两个talk比较有意思,分别是The AAA graphics of Spellsouls: achieving 60FPS on mobile 和 The
Real-time VFX of Spellsouls,恰好最近在做一些优化方面的工作,就一起学习了一下。


游戏官方介绍说是一个Moba类的卡牌,但个人感觉就是3D版的炉石?下面是几个截图。






作为一个图形程序,目标有两个:


AAA级别的画质

支持尽可能多的移动设备


所面临的挑战




首先是如何基于PBR Shading打造一种真实暗黑风格,然后是Shader的变种,接着是对性能的优化,最低设备支持到iphone4s,最后是动态画质调整。



PBR Shading之多对性能消耗很大,是因为其光照模型非常的复杂,这个代价对于大部分的低端设备还是不太现实的,我们对PBR做了一些深入研究之后,决定还是走Blinn-Phong这一套,采用的是近似的方法来处理。

通过和美术同学的通力合作,我们得到了一些不错的效果,而且在移动平台,由于屏幕尺寸很小,所以和真实的PBR差别并不是很大。




当一提到PBR的时候,你可能第一时间会反应出一个模型拥有不同的质感,比如皮革,金属,木头等等。我们最初就用了Roughness和Metalness来处理,但是我们发现这还不够,原因有两点,对于Roughness和Metalness的计算非常消耗性能,另一个原因是我们的游戏是一个魔幻类的游戏,有时候又不想那么真。最终我们添加了一张新的Reflectivity贴图,这样计算cubemap的反射就非常简单了。


对于环境光对角色的影响,采用的是分级的Cubemap



同时我们对CubeMap进行了HDR的处理,让暗的地方更暗,亮的地方更亮,这样最终效果会更好一些。


接下来要说的是



对于动态阴影,我们首先考虑的是Unity自带的阴影系统,他可以适用于很多场合,FPS,TPS等等,但是我们只有俯视角的操作,所以我们实现了自己的基于PCF的阴影系统,比Unity自带的影子系统更快一些,而且可以精准的控制,你们如果要自己来处理阴影的话,最好先考虑下基于自己的游戏能不能做的比Unity更好,同时有没有时间去处理,我们对这两个问题的回答都是yes,所以我们这样做了。


可以注意到场景中的动态阴影和地面烘培的静态阴影可以完美地Blend,这更加符合真实世界的表现。技术上,对于Lightmap,rgb三个通道用来表示光照的,阴影Bake在alpha 通道里面,最终和动态阴影Blend。


我们采用的VRay来进行光照的烘培,这是设计师和技术共同的抉择,从技术方面我们可以实现很酷的阴影,美术方面他们可以在Max里面控制烘培的效果,品质也会更高。


接下来是动态的光照



我们没有去做Defered rendering,因为这在移动平台上不太现实,而用forward的方式渲染的时候,对于多个光源的情况,需要通过多个Pass来渲染,这也很 expensive,所以我们做了几个不同的shader来处理0个灯光,1个灯光,2个灯光,3个灯光,4个灯光的情况,按照设备的性能来使用对应的shader。


对于每一个材质我们都可以在编辑器上定义一些渲染状态,



为了给设计师充分的空间,我们的Shader通常写得非常复杂



遇到了三个问题



分析了一大堆之后,决定自己动手撸一个Variant system



听起来很炫酷,但其实很简单,一共分为两个部分



还优化了构建的速度



重点,CPU和GPU的优化!我们实际上需要优化的东西有三点,帧率,电量,发热



做优化的时候,一定要同时考虑三者。首先讲GPU的优化



可以用Adreno Profiler截帧,然后实时改shader生效,这样就解决了重新编译之痛。


不过Adreno Profiler看到的shader很难看懂,一个trick就是你可以用Unity Editor编译出来的shader直接贴在这里,也可以立即生效。


在Adreno Profiler还可以看到shader里面指令数量,指令数量越多,消耗肯定就越高



下图中的抖动是因为移动设备的过热保护造成的。下面是很容易踩到的坑,希望你们别踩到了。



1. 不要在develop mode来衡量fps,虽然在develop mod可以用来做profiling和找性能瓶颈,但是你所面对的游戏和你的最终用户所面对的游戏是不一样的,很多地方代码消耗都不一样,最不济也是在release版本下在屏幕上放个fps统计。

2. 因为移动设备对于过热会有降频保护,所以在测试的时候,很可能会因为性能波动而造成fps波动,多疑参考第三点

3. 把目标帧率拔高一些作为优化目标,这样在发布的时候帧率恢复到正常帧率就不会出问题了,比如我们在优化60fps的时候是将目标帧率锁定在80的。



对于Shader的优化主要是两个点,减少指令数,小心No-ops.



当年我们在做自己的GPU Skinning,下面是一条最简单的蒙皮计算



性能和预期差别太大了,我们在Profiler里面显示有250条No-ops,。结果我们换成下面的形式




快了20%!


最后一个是用half来替代float,这个在shader里面可以提速很多。不要用fix类型,很多移动GPU是不支持fix的,这些GPU会把fix转成half。



下一个优化是最简单的优化,缩放分辨率。

对于现在的一些移动设备,分辨率已经大到变态了。比如一些1440p,相对于1080p,gpu要多渲染75%的像素,移动GPU对于填充率是非常敏感的,所以比较好的方案是渲染1080p的图像,然后放大到1440p,在移动平台上通常是发现不了的。



缩放的方案也有硬件实现方案和软件实现方案。


对于现在的移动设备,MSAA是基本免费的(貌似5.6才支持?)。


由于fillrate对于移动GPU来说很容易变成性能瓶颈,所以下面要说的帧率杀手就是,overdraw。


Overdraw主要是由于半透明物体的渲染引起的,因为每渲染一个半透明物体,就要很framebuff里面已存在的pixel做blend。不过很难凭人眼去判断overdraw的程度,所以我们做了一个检查overdraw的工具,这些设计师就可以一键检查自己制作的特效是否合格。这个工具免费share给大家。



上面的都是GPU方面的优化,下面要说一下CPU方面的优化,主要的优化方法我们都尝试了,这里要说的主要是两个方面。

第一,预加载和对象池。首先要说明的一点,io是非常耗时的,所以对于资源最好是采用一些预加载,

包括实例化对象和warm up shader.

关于shader的Warm up,我们的做法是在loading阶段在看不到的地方用所有材质去渲染一个quad。



第二个点是逻辑Update和渲染Update分离。

我们将逻辑Update用更慢的速度Update,每秒20次,帧与帧之间的结果想办法用插值来处理,相比于每秒60次的update 快了200%。



最后聊一下画质分级。

主要是跟据GPU来进行画质分级的,不同画质对应着不同的特性。



测试方面,我们开发了一个真机上的工具,用来开关这些特性



这样就可以很快地对设备进行分级了。


关于游戏的特效也专门有一个talk,这里也简单整理一下。


从制作的流程上看,分别有下面三个阶段



Art通常是创意阶段,给游戏的风格指明方向后面的两个阶段都是以Art为基础和目标。为了给游戏制作独一无二的特效,肯定是需要TECH作为支撑,最后我们需要就是一条打磨得非常完美的流水线,能够让每个人都能够在流水线上发挥自己的才华。


首先是Art,在设计方向,我们首先需要表达出gameplay想要表达的意思,让玩家能够理解





我们想在保持尽量真实的情况下又有一些风格化


下面是制作贴图的一些建议



下面是动画制作的一些建议。



没怎么听懂…


接下来讲Tech。

通常特效其实是一种折衷,因为设计师总有各种天马行空的想法,但是技术上不一定能实现。实际上技术就是让美术发挥无限的可能性,特别是在移动平台。作为特效设计师,我一直认为在工具和打磨流水线上的投资是值得的。


我们自定义了作为特效的Shader



上面有很多特性开关。


自定义颜色的几种方法




可以在shader里面定义很多Color变量,中间做插值渐变,也可以用LUT,,通常推荐用LUT,这样会更灵活,而且对设计师也更加友好,设计师可以用别的图片编辑软件来编辑这张LUT,或者在Unity做一个托渐变的工具也不错。

一张贴图的通道分布



减法运算



用第二张贴图来控制alpha值,获得更复杂的效果。右边的火焰只用了一个dc就实现,他是由一个sprite sheet和一张alpha mask组成。



还有裁剪方式与混合模式上效果的变化



在优化方面,主要要优化的有亮点,DC和overdraw,后者更加要注意




对于不同的设备做了LOD,像Glow和Bloom这种后期效果我们基本都是用一些fake的方法去模拟。


最后是Pipeline

首先是概念设计




我们的特效基本都是基于Mesh制作,可以说我们的特效,90%都是在Mesh上做一些贴图的动画,由于我们的摄像机是固定的,所以我们很多时候都可以采用一些treat的做法。


重点讲下Morph target,Wiki里面的解释


Morph target
animation
per-vertex animationshape interpolation, or blend shapes[1] is a method of 3D computer animation used together with techniques such as skeletal animation. In a morph target animation, a "deformed" version
of a mesh is stored as a series of vertex positions. In
each key frame of an
animation, the vertices are then interpolated between these stored positions.

对于变形的mesh,我们通常都使用Marph target这种方法,它很节省性能,这个冰块生长的动画就只使用了5个Morph target就搞定了。



当实在需要用骨骼的时候,我们通常会限制在10根骨骼以下,每个顶点最多只受两个骨骼影响。

对于贴图,我们是像下面这样分类的。



只有在用其它方法完成不了的时候,才使用sprite sheet,比如说闪电或者一些很特别烟。


在绘制贴图的时候,我们出了手绘,用PS去绘制,还尝试了用Substance基于procedual的方式去制作一些贴图,我觉得它简直是上天赐予给特效设计师的礼物!可能在初期需要付出一些学习成本,但当你逐渐掌握的时候,迭代的效率简直Crazy。


我们还使用了AE,MAX,Phoenix等工具。


然后是粒子系统



我们不会把粒子作为一个特效的主体,而只是把它作为一些调料加载特效里面,不过对于一些很依赖随机性的东西,我们只能用粒子系统去做,不过要遵循一定的约束。


最终在整合的时候,我们使用的是Unity的Animation system.



特效的每一个阶段都是一个Animation clip,通过时间来触发状态的切换,通过Layer来对特效进行分层。我们基本不使用Animationd的transition而是直接跳转,因为很多东西没法Blend。


最后举了一个特效的例子



完全没有用到粒子系统.


Link

Unite Europe 2017 - The Real-time VFX of Spellsouls \

Unite Europe 2017 - The AAA graphics of Spellsouls: achieving 60FPS on mobile

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值