忘记了以前是不是写过类似的文章了,不管了,结合近几年经验总结一下。
先从最核心的部分开始。如果熟悉图形API的朋友都应该可以理解,要想渲染一个模型,我们至少需要做两个操作,设置各种状态,调用绘图函数。这两个操作都会引起性能损失。我们分头来说
先说设置各种状态。都什么状态呢,比如使用什么纹理,是用什么着色器,是否开启Alpha测试,是否双面显示,是否使用混合以及怎么混合,等等。我们可以管这些状态统称为材质。这些信息通过调用图形API,再通过驱动进而设置给显卡。这需要时间,而且有些状态改变很耗时。
那么如何优化呢,问题出在哪就在那里解决,简单来说就是尽可能减少状态的改变!
对游戏而言引起状态改变比较多的首先是纹理的不同,这也是为什么要讲求纹理打包。举个例子,有三个模型,分别对应三张贴图,那么渲染这三个模型时势必会分别为他们设置三次纹理,这就造成了纹理状态的改变。如果把这三个模型的纹理放到一张纹理上之后,只需要设置一次纹理,然后分别渲染他们即可,这样就省掉了两次切换纹理。同样的道理也适用于Shader。
如果是自研引擎的话,可做的事情可以更多
1.抽象出一层图形API层,在其中做好状态缓存,当同样API被调用多次且内容一致时,只有第一次会真正去调用图形API.
2.做好材质排序,并给予材质进行渲染。简单来说场景里面有很多模型,他们有相当一部分材质相同,那么把使用相同材质的模型收集起来,设置一次材质,然后逐个进行渲染。
3.要搞清楚不是所有状态改变代价都相同,而且完全相同的材质也会比较有限,所谓材质排序只是排序那些切换代价比较大的状态即可,比如纹理,比如Shader等。
接下来再说调用绘图函数本身,一次调用就是一次DrawCall.
这个函数不用多说,它内部进行各种设置后就开始渲染了。要想优化他就需要搞清楚现代GPU的一些特性。
现代GPU一般都可以一次渲染大量多边形,但是对drawcall数量较为敏感。PC上3000个以上就会显著影响性能了,手机上不要超过200个为好。与此同时虽说一次可以渲染大量多边形,但其也是有限度的,不是越大越好。如何平和drawcall数量以及单次渲染多边形的数量成为了关键。基本的方法就是根据具体场景情况,适当合并模型。
如果是自研引擎的话,可以做的事情可以更多
1.更有效的场景管理以及筛选方法,使送入渲染引擎的多边形数量最少
2.使用实例(移动平台上只有GLES3以上才支持)
总结以上两点就是,尽可能少的状态改变,尽可能少的DrawCall!
其他
目前手机上送入图形API进行渲染的多边形尽可能控制在10w三角面以下,如果考虑适配几年前的机型,那么这个数量还要再低!
能用LightMap表现的就不要用实时光,而且目前也很难大面积高性能的使用!
Shader要尽可能算法简单,能在VS阶段算的就不要放在FS上算。也不要是用什么pow这样的函数。
终极优化
有时候技术人员想破脑袋也搞不定的优化,也许美术人员三两下就在max里面搞定了。
有时候技术人员和美术人员想破脑袋也搞不定的优化,也许在策划那边稍微改变一下要求就搞定了。
说到底是还是游戏开发各个环节上的人员要多沟通!