egret_渲染优化-降低dc


title: egret_渲染优化-降低dc
categories: Egret
tags: [egret, 渲染, webgl, drawcall]
date: 2018-07-21 01:47:18
comments: false

按照 egret_渲染源码阅读.md , 对项目进行实际操作优化, 降低 drawcall. 主要是使用图集
这里的ui是使用 fairygui. 一个包就一个图集


验证合批机制

确认过无误之后, 就往这个方向优化.
工具使用 通过egret的Chrome插件 inspector 控制显示隐藏.

  1. 打开绘制数据显示 (index.html中 data-show-fps="true" )

  2. 禁止 失去焦点时的中端ticker, 注释掉代码(看你自己写在那)

            // egret.lifecycle.onPause = () => {
            //     egret.ticker.pause();
            // }
            // egret.lifecycle.onResume = () => {
            //     egret.ticker.resume();
            // }
    
  1. 添加框框内的九个节点, 控制显示隐藏, 查看dc

    dc差值是 9, 可以判断除 每一个icon, 文字节点 都是一个批次. 9 = 6 + 3

  2. 调整一下节点顺序, 让icon相连, 看是否能合批

    ​ dc差值是 7, 每一个 文字 节点都是一个批次, 但icon节点合到了一个批次. 7 = 6 + 1

  3. 把系统字换成美术字, 并打到一个图集中

    在同一个图集里直接就一个批次绘制完成

  4. 结论: 合批机制正如源码一样. 所以项目使用中, 一些简单的, 变化比较小的 (如单位 人, 辆, 个 …) 可以考虑打成美术字, 并 整理到一个图集中. 可能不同图集会冗余一些相同的icon或美术字, 这就看怎么权衡 dc 跟 内存 了. 如果图集有很多空余空间 (毕竟 2的n次幂图集 应该会有很多空余的地方), 就 直接把 icon 或 美术字 冗余进去.


spine 动画

如果某些需求是 连续飘多个spine, 但是颜色不一样(只是举例), 空余考虑打到一个图集中, 通过不同动作触发 不同的uv映射下的贴图.

例如我这的项目有个飘小鸟的需求, 是spine做的, 但是有多个不同的颜色, 且在场景中的节点 排序是乱序的. 这样最坏情况下 n 个小鸟就n个批次. 优化: 打到一个图集. 一个批次绘制完成

优化前

优化后


cocos 和 egret 降低dc

这两种绘制机制都差不多, 降低 dc 重要指标就是 使用图集, 然渲染是 get 到的是同一个 Texture 对象, 才能让引擎做 合批 操作.

所以 有一套自己的资源加载方案, 让同一贴图路径返回同一个texture对象 (其实就是存在一个 key-value 集合中, new Map<string, Texture>()), 然后做引用计数. cocos 中经做了 TextureCache 和 引用计数, 但egret 两个都木有做.


cacheAsBitmap

官方还有一个操作就是 将某个节点 生成一个位图, 就一个小图集, dc 可以瞬间降到1, 但是这个是以 内存 为代价的, 看自己怎么权衡了


详细的优化过程由于商业原因, 不能详细把截图都贴出来 (都是放在 excel 中)

src.zip中包含:DelegateUtil.ts ,Dictionary.ts ,BC.ts,Main.ts DelegateUtil.ts 函数代理,方便传递参数和函数执行空间地址,包含原始参数和附加参数。 Dictionary.ts 支持存取少量的“对象”来当作存储数据的key. 重点见介绍下面的类,养成习惯模块销毁时用一句 BC.removeEvent(this);可以有效防止出现遗漏移除的监听. 还有BC.addOnceEvent(...);方法是也是懒人必不可少的方法。 BC类在actionscript中已经用了将近8年了,版本陆陆续续改过5次,这几天根据ts的特性修改了一个版本,值得推荐给大家。 BC.ts : 支持模糊移除事件,“BC.removeEvent(this, ”后面3个参数为模糊参数,可有可无,明确的参数必须相等才会移除. * 000 删除所有关于监听者的所有事件,通常在类销毁时使用一次 BC.removeEvent(this); * 001 指定相同回调函数的所有监听 BC.removeEvent(this,null,null,func); * 010 指定事件名的所有监听 BC.removeEvent(this,null,Event.COMPLETE,null); * 011 指定事件名,指定回调函数的所有监听 BC.removeEvent(this,null,Event.COMPLETE,func); * 100 删除指定通知者 和 监听者之间的所有监听 BC.removeEvent(this,dispatch,null,null); * 101 删除通知者 和 监听者之间使用同一回调函数的所有监听 BC.removeEvent(this,dispatch,null,func); * 110 删除通知者 和 监听者之间指定事件的所有监听 BC.removeEvent(this,dispatch,Event.COMPLETE,null); * 111 明确删除指定的事件监听 BC.removeEvent(this,dispatch,Event.COMPLETE,func); 代码: class Main extends egret.DisplayObjectContainer{ //申明一个广播对象“dispatchSprite” private dispatchSprite: egret.Sprite; public constructor() { super(); //字典使用对象作为key引用存储数据.对象作为key实际上需要进行遍历索引,所以在同一个字典中尽量不要添加过多的key会影响性能. var dic: Dictionary = new Dictionary(); var arr1: string[] = ["我是数组"]; var obj2: any = { name: "我是对象" }; var str3: string = "我是字符"; //添加到字典 dic.add(arr1, arr1); dic.add(obj2, obj2); dic.add(str3, str3); //打印字典内部的数据 dic.dump(); //申明一个广播对象“dispatchSprite” this.dispatchSprite = new egret.Sprite(); //添加一个自动会移除监听事件 BC.addOnceEvent(this, this.dispatchSprite, egret.Event.ENTER_FRAME, this.onEnterFrameOnce); //创建和监听一个Timer事件 var timer: egret.Timer = new egret.Timer(50); BC.addEvent(this, timer, egret.TimerEvent.TIMER, this.onEnterTimer); timer.start(); } /** * dispatchSprite的帧事件 */ public onE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蝶泳奈何桥.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值