赞
踩
本文所用引擎为cocos creator 2.4.11,且是一篇自我总结的文章,如果有错误和瑕疵,或者所写内容其实是烂大街的东西,是很正常的,读者可以随意观看。
https://blog.csdn.net/u013962723/article/details/135275250
对于一款游戏,渲染合批是一条非常重要的优化路线。
对于常规的2D游戏,或者说一款能够在逻辑上铺成一张纸,然后动一动里面的物件就是全部变化逻辑的2D游戏,合批最直观的方式就是通过算法,将同批次纹理在节点树中处于前后关系,使得可以可以进行合批。当然,这种做法会让代码显得非常奇怪,因此我们通常会配合设置zIndex,来固定渲染顺序的同时,让逻辑代码更整齐。
不过,一款伪3D游戏则需要一种完全不同的做法。
这种游戏在渲染上有若干个额外需要考虑的技术点:
1. 因为游戏中的物件会频繁的移动,前后遮挡关系会频繁进行切换。
处理这种需求最简单的方法,当然可以通过修改zIndex的方式来实现效果。这么做最大的问题在于,调整了渲染次序,导致中间会出现合批打断的现象。要解决这个问题也简单,我们把这些所有的精灵所需要的纹理全部放到一个图集里。实际上许多小规模的类似游戏这么做就足够实现了。(想起了以前做过的一款大富翁游戏)
但第二个技术点,导致问题无法这么简单就解决掉。
2.一款RTS或者模拟经营游戏,在场景中的物件相当多,而且因为存在换皮一类的需求。所以地图里的纹理可能会非常之多并且很难去合并到同一个图集上。
在一定程度上,我们是可以解决的,不过这需要去自定义着色器了。因为openGL是可以支持多texture的模式,数量至少有8个还是16个,而一张纹理可以用到2048x2048大小,这种规模的纹理已经足够多数情况下去使用了。
不过,这种做法毕竟要去定制着色器,可能大部分2d开发,都并不会接触到这些(说实话,我自己也不就会写点简单的形变。。。诶,人太菜)。另外,一款游戏中除了静态的图片,我们可能还会存在大量的动画,而且我们可能还无法只用简单的形变动画来实现,这时就需要用spine或者龙骨来辅助了,这里也会让本来简单移动的辅助控件变得非常不可控。而且,虽然说能用的纹理空间足够大,但也是有上限的,因此这种方式我不认为算一种很好的处理方式(这明显就是自己不会shader的借口罢了)
那有没有一种,不用写复杂的shader,不用复杂的额外代码就能做到这件事呢?
答案我认为是有的。
提出解决思路前,不得不先提一下真正的3D游戏。3D游戏的前后关系可比伪3D的要复杂不知道多少倍了,而且3D游戏存在大量的多边形模型,不可能像2D游戏一般,靠渲染顺序去实现哪些看得到,哪些被挡住,而且模型和模型之间还会相交,这复杂的不是一点两点。
想到这里,我仔细回忆了一下之前自学openGL,做3D场景demo的那段日子。然后突然想到了一个能处理前后关系的东西,深度测试。一个待渲染片元的深度会和当前已经渲染的内容的深度进行比较,根据结果执行一些逻辑(当然,通常来说都是如果更深就会丢弃),这不就正好用在我们的case中吗。
https://blog.csdn.net/u013962723/article/details/135275250
前言说了一大堆,现在可以开始正片了。
既然已经考虑使用深度测试来做我们的优化,那就先试一试。
首先要解决的是,深度该怎么表示。因为我用的是2.x的creator,这个版本还几乎是个纯2D的引擎,当然既然是几乎,那其实还是有部分3D的功能的,虽然不强(甚至有点坑)。既然有3D功能,那节点其实除了可以当2D节点用2D坐标表示位置,也可以是3D的。另外,摄像机是也是默认打开了深度缓存的清除,所以也不需要特意去改这里的逻辑和参数。
这里需要自己手动切换。
上图是我希望的顺序,其中3个怪物是放在同一个图集中的,可以看到,这里有4次dc
而我调整了顺序,让文本最后渲染,这里就成了3次。
当我兴高采烈的把z坐标改成前后顺序后,我发现渲染顺序还是上图所示。
难道这种做法不对?
其实并不是做法不对,而是因为cocos的默认的精灵渲染材质是不启用深度测试的(其实也能理解,一般的2D游戏都是贴纸式的,没必要去做判断)
因此我们需要使用一个自定义的材质,这个材质,我们可以直接复制cocos自带的sprite材质,然后把里面的深度测试打开即可。
我加上了深度测试的开关后,dc确实是合批了(多的一次是画了个纯色的底板),但是边框上居然出现了透明底。我开始想到了可能是混合模式的关系,但改了半天发现并没有任何变化。所以又回忆起了之前的教程,教程的第一步也出现了这种情况,那段教程给的策略是根据透明度来进行片元的舍弃。当然,后续也提供了使用混合方式来解决问题的策略,但哪个策略需要将透明的物件需要从远到近依次渲染,才能保证不出问题。如果修改了渲染顺序,显然会影响我们的合批策略。
因此,我再将着色器改成了,舍弃透明像素的方式,
这下就基本完美了。
解决掉了跨层合批的问题后,剩下的问题就到算法这一块儿了,通常来说2d游戏里,物件“脚底板”的y越大,其实应该越靠后的,因此,我们完全可以把物件的z坐标设置为负y,这样越往上的节点就更深,越下面的节点就会显示在上层。
当然,这只是一个粗略的算法, 毕竟这类游戏地形可能都很复杂,所以具体怎么去设置z坐标,要根据应用场景去设计。另外,也需要考虑不参与深度测试的图层的渲染顺序(不过RTS或者经营类游戏的场景渲染中,大地图中的所有物件肯定会在同一个节点下进行渲染的,不会也不应该穿插其他组件,所以通常来说类似血条这类UI组件要么是在最上层,要么就是actor的一部分)
另外,由于着色器的采用了丢弃的方法来处理透明像素。所以这里有一个非常严重的问题,那就是我们场景中的物件不应该再带上半透明的东西了(像是玻璃啥的),不过说实话,这个应该也不太常见吧,至少我没遇到过蛋疼的要加半透明玻璃的类似游戏。
以上就是全部内容了,大家就看着玩玩吧,毕竟A场游戏部门的P6还是P7钦定的我一点都不懂cocos。
https://blog.csdn.net/u013962723/article/details/135275250
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。