NGUI源码分析(一) 核心类UIDrawCall

来源:互联网 发布:android程序员工资 编辑:程序博客网 时间:2024/06/06 04:16

    前阵子一直想研究一下NGUI的源码,打开一看代码很多代码很庞大不知道从何入手,然后我看代码的方法搞错了,总想一下子就把类之间的关系理清楚,看到局部的代码没看懂又老是不自觉的沉陷其中,结果是这里看懂一点,那里又没看懂,搞的我一知半解又一头雾水,结果我放弃了。后来无意中有个网友告诉我,研究代码一开始不能思路铺的太开,一开始应该从最核心的部分看起,然后一层一层的向外围展开,一次只看一个类或一个方法,别想看A的时候又想看B,遇到不懂的时候可以先放着,特别时遇到很复杂的调用关系的代码时千万不要深陷其中。之后我完全按照这个网友的建议,从最核心的一小部分开始着手,比如我看DrawCall 类的时候完全不管Widget和Panel,我只关心这个类对外开放什么接口,需要什么数据等等,结果发现这种方法效果奇佳。

     废话不多说切入正题,DrawCall是NGUI最核心的一个类,它负责把顶点,UV,颜色等数据输入到网格和构建材质,最终绘制出我们看到的UI图形.

  下面是UIDrawCall的关键方法的介绍:

  一.UpdateGeometry() 最核心最重要的方法, 通过顶点,UV,颜色,贴图等信息绘制UI图形,下面是部分关键的代码:
 
      1.if (mFilter == null) mFilter = gameObject.AddComponent<MeshFilter>();//获得MeshFilter组件
 
      2. mMesh = new Mesh(); //创建用来渲染的网格对象 
 
      3. mTriangles = (verts.size >> 1); //三角形数量=顶点数/2
 
      4.  mMesh.vertices = verts.buffer; //将顶点 UV 颜色信息赋值跟网格对象,将网格赋值给mFilter 
           mMesh.uv = uvs.buffer;
           mMesh.colors32 = cols.buffer;
           mFilter.mesh = mMesh;
 
       5.if (mRenderer == null) mRenderer = gameObject.GetComponent<MeshRenderer>();//获得MeshRenderer组件
 
        6.UpdateMaterials();//更新Material 完成一次drawcall
 
  三.UpdateMaterials() 更新Material
 
   void UpdateMaterials ()
   {
        //如没有材质或使用了裁剪,就需要重建材质
        if (mRebuildMat || mDynamicMat == null || mClipCount != panel.clipCount)
        {
             RebuildMaterial();
             mRebuildMat = false;
        }
        else if (mRenderer.sharedMaterial != mDynamicMat)
        {
             //将材质赋值给MeshRender组件 ,更新render
             mRenderer.sharedMaterials = new Material[] { mDynamicMat };
        }
   }
  
  
三.RebuildMaterial ()重新生成材质
 
     1. CreateMaterial(); // 创建新的材质对象
 
     2. if (mTexture != null) mDynamicMat.mainTexture = mTexture;//将纹理赋值给材质
 
     3. if (mRenderer != null) mRenderer.sharedMaterials = new Material[] { mDynamicMat };//将材质赋值给MeshRender组件 ,更新render
 
四.CreateMaterial()  创建新的材质
  
 1. string shaderName = (mShader != null) ? mShader.name :
     ((mMaterial != null) ? mMaterial.shader.name : "Unlit/Transparent Colored");//默认使用NGUI自带的shader
 
   2. 
      //如果裁剪数量不为0 获得裁剪相关的shader ,如果不需要裁剪,直接获得shader对象
      if (mClipCount != 0)
      {
           shader = Shader.Find("Hidden/" + shaderName + " " + mClipCount);
           if (shader == null) Shader.Find(shaderName + " " + mClipCount);
 
           // Legacy functionality
           if (shader == null && mClipCount == 1)
           {
                mLegacyShader = true;
                shader = Shader.Find(shaderName + soft);
            }
       }
       else shader = Shader.Find(shaderName);
    
    3. mDynamicMat.shader = shader; //将shader赋值给Material对象
 
  其实DrawCall类功能很单一,下面做一个小测试,测试后会发现:完全可以把DrawCall类分离出NGUI,不用管Panel和Widget类,只用一个DrawCall类就可以独立渲染出想要的图形。
  下面是DrawCall测试的步骤:
 
 1.新建一个CustomDrawCall类,把UIDrawCall的代码原封不动的复制过去,把部分的属性改为Public属性:
  public Texture mTexture;
  [HideInInspector]
  public int[] mIndices;
 
 2.注释掉OnWillRenderObject()方法
 
 3.在unity3d场景中新建一个空GameObject,命名为“DrawCallObject”,这个对象就是我们绘制的目标对象。然后给这个对象添加MeshFilder,MeshRender组件,再挂上一个CustomDrawCall脚本,随便找一张贴图,拖到CustomDrawCall面板赋值给MTexture属性
  


   
  4.创建一个脚本TestDrawCall,在Start方法添加代码如下:


    5.把TestDrawCall脚本挂到场景的Main Camera上去

    6.运行Uinty3d,切换到场景,就可以看到贴图被绘制出来了:

   

   总结:UIDraw类其实并不复杂,它并不关心谁调用了它,我们完全可以把它独立出来,只要外部传入顶点,UV,颜色,贴图等信息给它,就可以绘制图形了。

   测试代码的链接是http://pan.baidu.com/s/1i3GRbtb

原文地址:http://www.cnblogs.com/rocky300/articles/4674046.html

0 0
原创粉丝点击