NGUI Drall原理分析

要想 理解NGUI Drall的原理,首先要理解UIPanel、UIWidget、UIDrawCall、UIGeometry之间的关系。

1、所有的UIWidget都需要一个UIPanel来管理和绘制;

2、每个UIWidget都有一个UIGeometry,UIGeometry就是对UIWidget的顶点vertices,uvs和color进行存储和更新,UIGeometry完全由UIWidget维护;

3、不是每个UIWidget都有UIDrawCall,因为NGUI会通过Batch合并来减少UIDrawCall;

4、UIDrawCall根据UIGeometry提供的数据由UIPanel统一指定渲染绘制;

在次借鉴DSQiu的一张图更说明他们之间的关系,他有一篇博客就是讲这个的,有兴趣的可以去看看:http://dsqiu.iteye.com/blog/1973651

     

好了他们之间的关系有了大概的了解那我们就开始进入正题吧。

先说说NGUI DrawCall的大概的一个原理,然后我们再去看看源码吧。

原理:1、首先将UIPanel上的所有UIWidget按照Depth排序,若Depth相同就按照Material的ID进行排序;

            2、然后遍历UIWidget将相同Material的合并到一个DrawCall里面;

OK,基本原理就是这样,那么再让我们来看看源码吧

        /// <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();

		for (int i = 0; i < widgets.Count; ++i)
		{
			UIWidget w = widgets[i];

			if (w.isVisible && w.hasVertices)
			{
				Material mt = w.material;
				Texture tx = w.mainTexture;
				Shader sd = w.shader;

				if (mat != mt || tex != tx || sdr != sd)
				{
					if (dc != null && dc.verts.size != 0)
					{
						drawCalls.Add(dc);
						dc.UpdateGeometry(count);
						dc.onRender = mOnRender;
						mOnRender = null;
						count = 0;
						dc = null;
					}

					mat = mt;
					tex = tx;
					sdr = sd;
				}

				if (mat != null || sdr != null || tex != null)
				{
					if (dc == null)
					{
						dc = UIDrawCall.Create(this, mat, tex, sdr);
						dc.depthStart = w.depth;
						dc.depthEnd = dc.depthStart;
						dc.panel = this;
					}
					else
					{
						int rd = w.depth;
						if (rd < dc.depthStart) dc.depthStart = rd;
						if (rd > dc.depthEnd) dc.depthEnd = rd;
					}

					w.drawCall = dc;

					++count;
					if (generateNormals) w.WriteToBuffers(dc.verts, dc.uvs, dc.cols, dc.norms, dc.tans);
					else w.WriteToBuffers(dc.verts, dc.uvs, dc.cols, null, null);

					if (w.mOnRender != null)
					{
						if (mOnRender == null) mOnRender = w.mOnRender;
						else mOnRender += w.mOnRender;
					}
				}
			}
			else w.drawCall = null;
		}

		if (dc != null && dc.verts.size != 0)
		{
			drawCalls.Add(dc);
			dc.UpdateGeometry(count);
			dc.onRender = mOnRender;
			mOnRender = null;
		}
	}

这就是合并DrawCall的代码,其思路如下

        1、清空DrawCall List表,声明Material mat、Texture tex、Shader sdr、UIDrawCall dc记录上一次循环的Material、Texture、Shader、UIDrawCall;

         2、遍历UIWidget列表对Material、Texture、Shader与上一个是否相同进行判断:

                     1)如果不同先将上个UIDrawCall加入到DrawCall列表中,然后根据当前UIPanel、Material、Texture、Shader创建一个UIDrawCall;

                      2)相同则就改变UIDrawCall的depthStart和depthEnd两个变量值;

OK,就简单粗暴的写到这,有写的不到位请指正谢谢!!!


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值