UI 血条批次优化

来源:互联网 发布:官方软件 编辑:程序博客网 时间:2024/06/02 12:03

前提介绍

之前的角色血条实现较为简单。画一个血条需要4个批次,有图有真相:


(GPA截取,粉红色为当前drawcall对应的绘制区域)

乍看好像没什么问题,但是游戏是10 vs 10的游戏,极端情况下(两方英雄加小兵进行团P)仅是血条这部分就有上百个批次。虽说图片小、顶点少,但是批次多引起的状态切换开销,大家都懂得。

于是乎,就要想办法合并批次。

之前血条各部分的贴图资源全是分开出的,如果让美术重新出图,程序结构和配置文件都要改。最终美术、程序,策划三方都不爽。
还是发扬优良传统已最小的代价,程序自己把这件事给悄悄做了吧。

因此就有了这篇文章的重点,动态贴图合并算法。

核心算法

把小贴图合并成大贴图也不是什么新鲜事,为了packing lightmaps,图形学前辈就想出了很多绝妙点子。

google “texture atlas”文章一大堆。这里讲一种二叉树算法实现。

思想很简单:递归得把空白大图片切割成小区域,在合适的区域填上小图片。

比如,把图片1填到大图片A的过程:

  • 把A根据图片1的高度上下切割成两部分,上部分B的高度等于图片1的高度。

    高度差大于宽度差的前提下。否则,A切割成左右两部分,左边的宽度等于图片1的宽度。

  • 把B切割成左右两部分。左边的宽度等于图片1 的宽度。

    同上依据宽度差大于高度差(此时高度差为0)

  • 图片1填充到左边部分。
    此时对应的区域结构和数据结构:

继续把图片2填到大图片A:

  • A已被切割,转到B;B已被切割,转到1.

  • 1已被填充,转到1的兄弟节点;空间不够,转到B的兄弟节点

  • 切割B的下部分C,根据宽度差大于高度差,左右切割成两部分。左边部分D的宽度等于图片2的宽度。

  • 继续根据高度差大于宽度差上下切割D节点。上部分的高度等于图片2的高度。

  • 图片2填充到上部分。

此时对应的区域结构和数据结构:


优化成果:

由于层次表现需要,血条被分成了5种: 己方英雄,敌方英雄,己方小兵,敌方小兵,自己。分5个批次画出。
下图为画敌方英雄的批次:

GPA截图一局游戏中同一时刻的某一常规帧进行对比:
批次由1075降为1013

GPU时间比较:

补充说明

为提高插入命中率并高效利用空间,可以事先对所有的小图片进行排序。
但也不一定,比如这次就没做,原因两点:变动和影响尽可能小,小图片数量少压根没必要。
下图是程序运行中,生成的texture cache。


参考文献

http://www.blackpawn.com/texts/lightmaps/

0 0
原创粉丝点击