UI渲染合批

cocos渲染ui组件时,在节点树中从上往下渲染,由此导致图文穿插时,产生大量的drawcall,如示例:

image
可能有开发者尝试将文字转化为图片,然后和ui图片一起打图集来合批,但这很蛋疼;
还有的开发者通过手动移动节点来避免图片和文本穿插渲染,但这也很蛋疼,尤其是对于滚动列表,从上往下渲染时无法避免图文穿插;

鉴于此,为了达到合批的效果,我们需要自定义渲染顺序,避免从上往下渲染产生大量的drawcall;

不知道大家先前是否用过Unity的Ngui,ngui优先按组件的depth来渲染,我们可以将能合批的组件设置为相同的depth值,这样无论多么复杂的界面,drawcall都可以控制在个位数;

由此,笔者就把ngui那套搬到cocos上来,设置ui组件的depth,渲染时按depth值从小往大渲染:
image
image
将图片组件的depth设置为0,将文本组件的depth设置为100,然后再设置合批根节点为IsBatchRoot:
image
默认不使用自定义合批,对于需要使用自定义合批的界面,需要设置界面根节点为IsBatchRoot,这样根节点里面的ui元素才按depth排序渲染,实现默认mask节点为IsBatchRoot,因为mask会打断合批,可看源码;

可以看到,draw马上减少到4个,实际当前ui只有2个drawcall,一个渲染图片,一个渲染文本;

如此美妙的效果,想必大家都想在自己项目中应用,这需要自定义引擎,包括网页端(ts)和原生端(cpp),不过并不复杂,笔者会将相关代码无私贡献。

笔者使用的引擎版本是3.8.1,该版本UIOpacity组件在原生端有问题,因此给出的代码也包含了对透明度的修复;

测试工程及源码链接:链接:https://pan.baidu.com/s/1YcHhiOT3LJjFz7lLdtd22g?pwd=e30c
提取码:e30c

下载好后解压,可看到文件夹:
image
源码:
image
可用BeyondCompare将笔者修改的代码与官方下载的比较,查看笔者修改的代码:
image
(ts)
image
(原生端cpp)
如果想跑测试工程,得先从官网下载3.8.1引擎代码,然后同步笔者修改,关于怎么自定义引擎,去官方手册看吧。

27赞

非常好用的方法:call_me_hand::+1::+1:

强烈建议官方做一个这个功能,论坛见过太多这样的定制了 :sob:,浪费开发者的时间

8赞

非常好用的方法:call_me_hand::+1::+1:

顶顶顶!!!

确实可以,这个,可以做个插件,卖钱

你这东西早点出来参加V7,肯定拿奖了

太好了,感谢楼主的无私奉献

不错,收藏,点赞

感谢你的捧场

不好做成插件,得在现有流程上修改

我用unity倒腾的时候,发现ugui的一个黑科技特性,它同时具有先子女后兄弟的渲染次序 和 先兄弟后子女的渲染次序。
使用哪种次序,要看ui之间有没有重叠,这个重叠是用boundingbox做重叠检测的。
举个例子,如果你渲染一个列表,里面的item之间互相没有重叠,然后每个item只有一张图,图上有一个文本。
这时候,会先渲染所有图,在渲染所有文本。
然后我总结了一些使用的技巧:
1z轴必须为0,否则会影响boundingbox检测,导致这个黑科技失效。
2可以通过修改文本的固定尺寸的方式,在不改变视觉表现的情况下,让文本的boundingbox和其他对象产生交叠,从而调整渲染次序。
3可以通过叠上一个透明度为0的图的方式,来调整渲染次序。

大佬可以试试这个能不能复刻到ccc里

3赞

ugui确实挺智能,他不是严格按照节点树来渲染,而是考虑组件间是否重叠,来做最大限度的合批,这种方式确实方便开发者,但是要写好这个渲染逻辑,需要花费不少时间,考虑的情况也比较多

希望楼主 或 某个大佬 出个 2.4.x 版本的

大佬威武!

希望作者大大出一个 2.x 版本

2.x没用过,没时间去弄了

fgui的思路类似吧,要么合并mesh,要么合并批次。ugui是合并mesh,fgui和ngui都是合并批次

此处@官方,为什么这些实用的功能不优化

3赞

突然想起,这里思路跟 【分享】简单方便的UI渲染优化 - SortingGroup (支持原生,支持2.4.x,无需自定义引擎) - Creator 3.x - Cocos中文社区 这个一样。