Unity_UGUI|通向UGUI源码的入口VertexHelper

为什么要介绍VertexHelper(顶点帮助器)这个类。他在UGUI中起到了至关重要的地位。当然不了解这个类,对于使用UGUI没有任何影响。他只是看懂UGUI源码的一个基础。不看点源码,怎敢说自己精通。

前言

UGUI是图形学渲染和射线检测这两个技术结合的典型例子。图形学渲染来处理UI的显示,射线用来交互。

今天我们主要看看UI的渲染。
首先介绍一点图形学的基础知识:
1、所有的渲染对象都是由网格(Mesh)构成,Mesh的绘制单位是图元(点、线、三角形)。意思也就是说所有的游戏对象都是在绘制一些点、线、三角形的集合。

具体是如何一步一步显示到屏幕上的,可以看之前的一篇博文(实时渲染(第四版)_第2章|图形渲染管线总结)://www.greatytc.com/p/2d8eeec9d0ef

2、顶点数据中最主要的是位置,颜色,纹理坐标,法线等。也就是说顶点中保存着其位置、颜色、纹理坐标、法线信息等。

3、贴纹理是指,将一张纹理(可以称为图片),根据纹理坐标,贴在模型上面。就好比同一个模型人,穿上了不同的衣服。纹理坐标指的是根据坐标将图片信息覆盖在Mesh表面,就相当于,柚子就贴在手腕处,裤子就贴在腿上。

正文

UGUI提供了我们自己构建顶点、三角形的类,那就是VertexHelper类。通过这个类,我们可以创建顶点,构成三角形,填充到一张mesh上,然后用MeshRenderer渲染到屏幕上,实际上我们可以直接操作Mesh类添加顶点、三角形等操作,这里的vertexHelper只是UGUI与Mesh之间的一座桥梁。

实践

接下来 我们尝试用这种办法在空物体上画出一张image图片。

首先在Unity中添加一个空对象,命名Image,Image对象需要添加MeshFilter组件,用来添加Mesh,还需要添加MeshRenderer组件,用来渲染Mesh,使其能够在屏幕中显示。

创建CreateImage.cs脚本,并挂载在Image上。
在脚本中添加Create函数,并有vertexHelper构造4个顶点(矩形):

        VertexHelper vp = new VertexHelper();
        vp.Clear();
        //这里采用的添加顶点函数,函数参数分别对应了顶点位置,顶点颜色,纹理坐标
        vp.AddVert(new Vector3(0, 0, 0), Color.red, new Vector2(0, 0));
        vp.AddVert(new Vector3(0, 1, 0), Color.green, new Vector2(0, 1));
        vp.AddVert(new Vector3(1, 1, 0), Color.blue, new Vector2(1, 1));
        vp.AddVert(new Vector3(1, 0, 0), Color.cyan, new Vector2(1, 0));

接下来,我们用4个顶点构造出矩形的两个三角形:

        vp.AddTriangle(0, 1, 2);
        vp.AddTriangle(2, 3, 0);

我们知道矩形最少是由两个三角形构成的,当然我们可以构造更多的三角形去显示一个矩形,但是这样不仅显得多余,而且对于计算机来说计算量就会上升。同时我们要注意:

Unity默认是只渲染物体的正面,背面是不渲染的。这里就涉及到构造三角形的顺序。在Unity中以顺时针方向构造三角形,这个三角形就是正面,就被会参与渲染的计算,逆时针就是背面,最终不会显示到屏幕上。

如何看三角形是顺时针还是逆时针呢。从构造三角形的三个顶点顺序(A、B、C),第一个顶点A为基准,然后指向第二个顶点B划线AB,这根线沿着第二个顶点B到第三个顶点C的连线BC扫描,扫描的方向是顺时针即为正面,逆时针即为背面(当然这个规定只是Unity的规定,其他地方要看所用的图形接口是如何规定的)。

接下来,我们填充到一张Mesh上,并将这个Mesh赋值为空物体Image的MeshFilter上。

        meshFilter = this.GetComponent<MeshFilter>();
        Mesh mesh = new Mesh();
        vp.FillMesh(mesh);
        meshFilter.mesh = mesh;

然后我们运行游戏:


vp1.gif

可以看到有一个紫色的方块从无到有。可能有小伙伴就有疑问了,创建的顶点不是紫色的啊,这是因为MeshRender渲染时候无材质的默认颜色。在来看看官方的解释:


vertexcolor.png

意思就是大部分的shder都不会显示顶点颜色,用一个可以显示顶点颜色的shader比如, partice shader去观察顶点颜色。
这时候随便用partice下的shader创建一张材质,赋给meshrender,再运行一遍就可以看到顶点颜色了。


mat.png

顶点效果就出来了:


vp2.gif

4个顶点的颜色是已知的,中间的颜色是插值得到的。具体原理还是在上文链接中有详细介绍。

当然我们也可以用Material中的颜色或者一张图片,给mesh贴上纹理,就相当于给Mesh穿上纯色或者有图案的衣服。全部代码如下:

    private MeshFilter meshFilter;
    private MeshRenderer render;
    public Texture tex;

    void Start()
    {        
        meshFilter = this.GetComponent<MeshFilter>();
        render= this.GetComponent<MeshRenderer>();
        CreateAImage();
    }

    void CreateAImage()
    {
        VertexHelper vp = new VertexHelper();
        vp.Clear();
        //这里采用的添加顶点函数,函数参数分别对应了顶点位置,顶点颜色,纹理坐标
        vp.AddVert(new Vector3(0, 0, 0), Color.red, new Vector2(0, 0));
        vp.AddVert(new Vector3(0, 1, 0), Color.green, new Vector2(0, 1));
        vp.AddVert(new Vector3(1, 1, 0), Color.blue, new Vector2(1, 1));
        vp.AddVert(new Vector3(1, 0, 0), Color.cyan, new Vector2(1, 0));

        vp.AddTriangle(0, 1, 2);
        vp.AddTriangle(2, 3, 0);

        Mesh mesh = new Mesh();
        vp.FillMesh(mesh);
        meshFilter.mesh = mesh;

        //设置颜色或者纹理(这里的设置会覆盖Mesh的颜色)
        //想象你穿衣服是不是就把你的肤色盖着了
        //render.material.color = Color.red;
        render.material.mainTexture = tex;
    }

最终效果:


vp3.gif

举一反三:

想象一下圆,他同样是有三角形来构成的,我们可以用10个三角形构成一个圆,也可以用1000个三角形构成。下面我们看看三角形数量有什么差别。
直接上主要代码:

void CreateCircle()
    {
        VertexHelper toFill = new VertexHelper();
        toFill.Clear();
        //首先添加圆心
        toFill.AddVert(new Vector3(0, 0, 0), Color.white, new Vector2(0.5f, 0.5f));
        //计算单位三角形的角度
        float theta = 2 * Mathf.PI / triCount;

        for (int i = 0; i < triCount; i++)
        {
            //玩的特殊的,顶点颜色都不一样
            Color color = Color.Lerp(Color.blue, Color.red,  (float)i / (triCount-1));
            //计算每个顶点的位置
            float X = Mathf.Sin(2 * Mathf.PI-i * theta);
            float Y= Mathf.Cos(2 * Mathf.PI-i * theta);
            //radius为半径
            toFill.AddVert(new Vector3(X*radius, Y*radius, 0), color, new Vector2(X, Y));
        }
        //添加三角形
        for (int i = 1; i < triCount; i++)
        {
            toFill.AddTriangle(0, i, i + 1);
        }
        toFill.AddTriangle(0, triCount, 1);
        Mesh mesh = new Mesh();
        toFill.FillMesh(mesh);
        meshFilter.mesh = mesh;
    }

看看效果:


10.png
1000.jpg

上面分别是10面和1000面的效果。
实际上36个三角形已经可以构造出很圆的圆形了。大量的三角形渲染会增加GPU负担。这也是在游戏开发中,美术为什么要限制模型的顶点与三角形数量的原因。
我们还可以搞点不一样的。想想下面是如何实现的。


vp5.gif

小结

知识点:了解VertexHelper的用法。VertexHelper有助于我们理解UGUI源码。而且我们熟悉了VertexHelper的用法后,甚至可以随心所欲的制作出独特的UI。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,423评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,147评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,019评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,443评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,535评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,798评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,941评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,704评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,152评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,494评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,629评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,295评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,901评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,978评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,333评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,499评论 2 348