UE4UI性能优化指北(三)-动态UI优化:海量UI零耗时优化方案
前言
前面讲完了静态UI的优化方式。我们现在来讲讲动态UI。动态UI每帧都在发生变化,每帧都要更新,UI缓存的方式几乎无效,再加上拉胯的slate系统的深度递归(主要canvas节点计算了很多锚点、可见性等逻辑),大量的UI在每帧更新的时候,耗时都很高。
解决方案
对于单局HUD,大部分都是简易的,完全可以自己构造顶点索引数据去绘制,不走slate那一套,更高阶的做法可以把耗时转移至GPU,例如使用GPUInstance技术。
测试数据
下来用一台低端Android机器(500块的垃圾手机= =)来展示GameThread相关性能数据。
测试用例A:传统UMG渲染1000个icon(55ms)
测试用例B:使用makeboxApi自己绘制1000个icon(4ms)
测试用例C:使用gpuinstance绘制1000个api(0ms)
ps 具体实验过程在内网wiki 不太方便拿出来,这里贴一个结果。简单来说就是一个ABTest的思路,3种情景都与空场景做一个diff。
UE4提供的UI Gpuinstance方案
UE4提供了一个组件叫SmeshWidget,这个组件提供了最基本的gpuinstance能力。
详情可以看看这个链接: YivanLee:虚幻5渲染编程(UI篇)[第一卷: Slate渲染框架并通过为UMG拓展MeshUI了解Slate的图元阶段]
在FSlateRHIRenderingPolicy.cpp中,也提供了gpuinstance的流程
如果是gpuinstance,则使用streamsource index 为0的buffer进行渲染。
但UE4原版提供的buffer数据结构只有一个float4,UI要一个DC画出来,需要配合图集做UV缩放,UV偏移,旋转,自身缩放的的需求,于是我扩展了UE4引擎原生的功能:
这样子,我们就能单独修改其颜色,大小,图集中的图片位置,并且在Shader中实现。
基于GPUInstance的图片文字混合渲染
背景:
由于手机UI不单单只有图片这么简单,比如玩家头像上既有显示头像icon,又有文字,但我们游戏同屏人数又很多,在人数多的情况下,消耗也挺可观的,也想转移至GPU来优化gamethread的消耗,因此我开发了gpuinstance的图文混合渲染。
实现流程:
文字渲染基础知识可以看看这篇文章: OpenGL进阶(二十一) - 文字渲染_拳四郎的博客-CSDN博客
基于现代文字渲染技术FreeType,我自己提取了文字并且按照FreeType的规则重新设置了缩放和偏移:
由于FreeType会告诉你对应的文字间隔,文字缩放和偏移。原理如下图:
因此我们用下面的代码把一个标准正方形进行缩放偏移,并且间距也算好,就大功告成了。
一个DC绘制出图片和文字
因为我们已经有对应的文字图集了,因此,我魔改了slate的pixelshader,把文字图集传入shader,通过一个变量来判断采样图片图集还是文字图集。
效果展示
这个icon+文字基本就是一个DC处理完了。且Gamethread基本没有任何消耗吧。
海量UI的优化思路可以参考这个方案来进行。