【NGUI源码剖析】NGUI的drawcall
来源:互联网 发布:知乎每日精选 rss 编辑:程序博客网 时间:2024/05/18 20:06
前言
在使用unity3d开发实际的项目中,性能优化一直是一项不得不考虑的重点,而其中UI的优化又是绕不过去的坎,很多看似简单的UI为何会占用大量的cpu开销?本文以NGUI这套UI的解决方案为例,从源码出发,分析影响性能的原因,看清问题的本质,对症下药。
NGUI的drawcall
在Unity中,每次引擎准备数据并通知GPU的过程称为一次Draw Call。这一过程是逐个物体进行的,对于每个物体,不只GPU的渲染,引擎重新设置Material/Shader也是一项非常耗时的操作。
说起NGUI的drawcall,UIPanel是一座绕不过的大山,看源码:
/// <summary> /// List of draw calls created by this panel. Do not attempt to modify this list yourself. /// </summary> [System.NonSerialized] public List<UIDrawCall> drawCalls = new List<UIDrawCall>();
可以将UIDrawCall近似的理解为NGUI层对于drawcall需要用到的数据进行的一层封装,后续会写文章来分析UIDrawCall。
这里看到UIPanel会维护一个UIDrawCall的列表,注释说明了这个列表保存的是当前panel创建的draw calls。跟踪这个列表,查询向列表添加元素的地方会发现FillAllDrawCalls 这样的一个接口:
/// <summary> /// Fill the geometry fully, processing all widgets and re-creating all draw calls. /// </summary> void FillAllDrawCalls () { for (int i = 0; i < drawCalls.Count; ++i) UIDrawCall.Destroy(drawCalls[i]); drawCalls.Clear(); Material mat = null; Texture tex = null; Shader sdr = null; UIDrawCall dc = null; // 引用类型 int count = 0; if (mSortWidgets) SortWidgets(); // 对widgets进行排序 for (int i = 0; i < widgets.Count; ++i) { UIWidget w = widgets[i]; if (w.isVisible && w.hasVertices) { Material mt = w.material; if (onCreateMaterial != null) mt = onCreateMaterial(w, mt); Texture tx = w.mainTexture; Shader sd = w.shader; // 判断材质,贴图,shader是否与当前的widget相同,若不同则增加一个drawcall if (mat != mt || tex != tx || sdr != sd) { if (dc != null && dc.verts.Count != 0) { drawCalls.Add(dc); dc.UpdateGeometry(count); dc.onRender = mOnRender; mOnRender = null; count = 0; dc = null; // 调用UpdateGeometry对Mesh,MeshRenderer,MeshFilter进行设置 // 之后重置dc } ... }
上述代码出现了另一个列表widgets:
/// <summary> /// List of widgets managed by this panel. Do not attempt to modify this list yourself. /// </summary> [System.NonSerialized] public List<UIWidget> widgets = new List<UIWidget>();
可以看到一个UIPanel可能对应多个UIWidget,而一个UIWidget不一定会对应一个UIDrawCall(可能对应一个UIDrawCall,也可能与其他UIWidget共用一个UIDrawCall)三者间的关系可以用下图表示:
顺藤摸瓜,可以得出函数调用栈:
下一次,我将会着重分析SortWidgets()对于UIWidget与UIDrawCall之间关系的影响。
阅读全文
0 0
- 【NGUI源码剖析】NGUI的drawcall
- 【NGUI源码剖析】深入理解NGUI的drawcall
- 【NGUI源码剖析】NGUI如何优化drawcall数量
- 源码分析NGUI的DrawCall合并原理
- 源码分析NGUI的DrawCall合并原理
- NGUI诡异的drawCall
- NGUI DrawCall
- NGUI减少drawcall 的总结
- Unity3d NGUI的drawcall,UISprite与UITexture
- NGUI 减少drawcall
- NGUI 减少drawcall
- NGUI Drawcall 优化
- NGUI 减少drawcall
- NGUI界面Drawcall优化
- NGUI DrawCall优化
- NGUI减少Drawcall
- NGUI减少Drawcall
- NGUI源码分析(七) Panel,Widget,DrawCall 三者之间的关系
- Android中网络通信基于HTTP、Socket
- trustzone的硬件框架和安全扩展
- socket实现文件传输功能
- 6.1~6.3关于sublime的一下额总结
- 宿命的PSS
- 【NGUI源码剖析】NGUI的drawcall
- 怎样在Git码云上上传项目
- 绘制caffe中的prototxt网络结构图
- hihocoder1121 二分图一•二分图判定
- maven持续集成本地搭建私有仓储
- 二分图最佳完美匹配——KM算法总结
- Eclipse报错: Failed to get the required ADT version number from the SDK
- 2017 计蒜之道 初赛 第五场 A. UCloud 机房的网络搭建
- Ubuntu下安装R,升级R版本,安装Rstudio,安装Rstudio Server以及安装Shiny Server