Cocos Creator 2.1.1 性能优化 (一)

cocos creator 2.1.1 性能优化之 draw call优化

一.原理

1.优化draw call的原因

CPU与GPU在进行通讯时,CPU会将准备好的渲染数据存储在命令缓冲区中(Command Buffer)然后由GPU从中读取数据并进行渲染。通常GPU的渲染速度非常快,渲染几百个和几千个网格没有什么太大的差别,但是过多的draw call意味着CPU需要做的准备工作就越多,从而导致CPU的效率降低。其次在PC端CPU与GPU在进行交互时需要跨越硬件交互,而为了保证跨越硬件带来的数据同步问题,又会导致效率低下。所以CPU是draw call性能问题的元凶。

2.如何优化

根据优化原因可知,我们需要降低CPU提交draw call的数量。cocos creator中有动态合批处理,会自动将碎图动态的打成一张大图。但是限制是单张图片的最大尺寸不能超过512x512,最小尺寸要大于 8x8。如果图片的尺寸超过了合集的要求,我们就应该在节点的摆放上做一些处理了。

let _maxAtlasCount = 5;
let _textureSize = 2048;
// Smaller frame is more likely to be affected by linear filter
let _minFrameSize = 8;
let _maxFrameSize = 512;
...
...
 /**
     * !#en The maximum size of the picture that can be added to the atlas.
     * !#zh 可以添加进图集的图片的最大尺寸。
     * @property maxFrameSize
     * @type {Number}
     */
    get maxFrameSize () {
        return _maxFrameSize;
    },
    set maxFrameSize (value) {
        _maxFrameSize = value;
    },

    /**
     * !#en The minimum size of the picture that can be added to the atlas.
     * !#zh 可以添加进图集的图片的最小尺寸。
     * @property minFrameSize
     * @type {Number}
     */
    get minFrameSize () {
        return _minFrameSize;
    },
    set minFrameSize (value) {
        _minFrameSize = value;
    },

二.项目分析

1.cocos creator 中的自动合批

将两张碎图放置在场景中,并且最大值不超过512x512,如果自动合批起作用,在运行时应该会有2个drawcall(显示drawcall的面板也会占用一个drawcall)
在这里插入图片描述
在这里插入图片描述
运行结果满足预测。
当加入一个大于512x512的图片资源,并且节点摆放位置在最上层时应该会有3个draw call,图片如下
在这里插入图片描述
在这里插入图片描述
运行结果满足预测。

2.节点摆放对draw call的影响

实验:

  1. 如果我们将无法打入合集的节点放置在能打入合集节点的中间,是否会打断节点从而增加draw call呢?
    在这里插入图片描述
    在这里插入图片描述
    结论:由图可知drawcall变为了4,所以同样的节点经过不同的摆放是会增加drawcall消耗的。

3.项目优化

1.drawcall的优化并不意味着一定要纠结于节点的摆放,而是应在不影响层级显示及后续维护的情况下合理的摆放节点。以多个不同的fnt字体举例,在摆放节点时,为了方便程序维护节点,我们可以不纠结于字体是否会打断合批,而是在运行时动态管理节点。将采用相同fnt字体的组件放置在同一父节点下,然后控制不同fnt父节点的层级位置来达到减少drawcall的目的。
2.示例代码:

		//获取content节点下的所有label组件
        let labelArray = content.getComponentsInChildren(cc.Label);
        let labelType = [];
        let labelFont = [];
        if (labelArray) {
            labelArray.forEach(element => {
            	//如果该字体资源是fnt资源则对其进行分类
                if (element.font) {
                //如果labelType中未存储此字体资源则创建一个node节点用来放置所有同类型的字体节点
                    if (!labelType.includes(element.font.name)) {
                        labelType.push(element.font.name);
                        let tempNode = new cc.Node();
                        tempNode.parent = content;
                        labelFont.push(tempNode);
                        let pos = tempNode.convertToNodeSpaceAR(element.node.parent.convertToWorldSpaceAR(element.node));
                        element.node.parent = tempNode;
                        element.node.position = pos;
                    }
                    else {
                        //如果已创建了node节点则将其丢进与之对应的节点下
                        let index = labelType.indexOf(element.font.name);
                        let pos = labelFont[index].convertToNodeSpaceAR(element.node.parent.convertToWorldSpaceAR(element.node));
                        element.node.parent = labelFont[index];
                        element.node.position = pos;
                    }
                }
            })
        }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值