所谓Drawcall,就是CPU加载并整理好美术资源(包括模型、贴图、材质等)及相关指令后,调用GPU进行工作的过程。
UIpanel UIWidget UIDrawcall 三者关系
uipanel管里其底下的UIwidget,并统一创建管理UIDrawcall
在继承自UIWidget的组件中生成顶点、UV、颜色等数据,并缓存到UIGeometry中
数据从UIGeometry被写入UIDrawCall的缓冲区,准备渲染,使用UIDrawCall中的数据建立网格,并通过MeshRenderer渲染。
NGUI的渲染机制以及Drawcall处理
static List<UIPanel>内部包含一个Sort排序方法,会基于Panel的Depth进行一次排序。
而Panel内部也包含一个Sort排序方法,会基于Widget的Depth进行一次排序。
所以,虽然Panel和Widget都有Depth这个参数,但是这两个参数的地位是不一样的。
只要一个Panel的depth比另一个Panel小一丢丢,这个Panel内部的所有Widget都会被先处理。
当一个Panel的List<Widget>排序完成后,Panel就会根据List<Widget>来生成List<Drawcall>,List<Widget>中的第一个Widget必定会创建一个新的Drawcall,之后的每一个Widget都会拿出来和前一个进行对比,如果两者的material、texture、shader(下简称M/T/S)一致,则把后面这个Widget也丢给同一个Drawcall处理,如果两者的M/T/S有一丢丢不一样的地方,就创建一个新的Drawcall,也就是说,相同M/T/S且下标连续的Widget会共用一个Drawcall,而如果相同M/T/S的Widget中间隔着一个或多个不同M/T/S的Widget,就会拆分出许多额外的Drawcall。
减少Drawcall规则:
1.同一个UIPanel下的texture和font尽量放在同一个altals下。
2.如果一个UIPanel下面使用了多个altals,那么尽量让使用相同altals的元素连续,尽量避免altals交叉。
减少Drawcall的目的还在于提高渲染效率
对于CPU来说,调用Drawcall需要耗费时间,而构建Drawcall同样需要耗费时间。
NGUI在运行的过程中,如果某一个Panel下面有任意一个Widget进行了一点非常微小的变动:比如移动了一点点距离。那么这个Panel就会清空自己的List<Drawcall>,从头再遍历所有Widget,重新构建所有Drawcall。而这个过程显然是非常耗费性能的。
所以,有时候可以根据Widget的用途,将动态Widget和静态Widget拆分到不同Panel,如此一来虽然增加了Drawcall的数量,但最终结果却反而能提升渲染效率。