Unity 頂點基礎 + OnPopulateMesh

轉自:

https://www.cnblogs.com/lyh916/p/9162463.html

https://blog.csdn.net/jk823394954/article/details/53870779

一.圖形繪製

1.繪製三角形

using UnityEngine;
using UnityEngine.UI;

public class TestMesh : BaseMeshEffect {

    public override void ModifyMesh(VertexHelper vh)
    {
        vh.Clear();
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        vh.AddTriangle(0, 1, 2);
    }
}

2.繪製正方形(繪製兩個三角形)

using UnityEngine;
using UnityEngine.UI;

public class TestMesh : BaseMeshEffect {

    public override void ModifyMesh(VertexHelper vh)
    {
        vh.Clear();
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        vh.AddVert(new Vector3(100, 0), Color.blue, Vector2.zero);
        vh.AddTriangle(0, 1, 2);
        vh.AddTriangle(2, 3, 0);
    }
}

3.繪製正方形(繪製一個正方形)

using UnityEngine;
using UnityEngine.UI;

public class TestMesh : BaseMeshEffect {

    public override void ModifyMesh(VertexHelper vh)
    {
        vh.Clear();
        UIVertex[] verts = new UIVertex[4];

        verts[0].position = new Vector3(0, 0);
        verts[0].color = Color.red;
        verts[0].uv0 = Vector2.zero;

        verts[1].position = new Vector3(0, 100);
        verts[1].color = Color.green;
        verts[1].uv0 = Vector2.zero;

        verts[2].position = new Vector3(100, 100);
        verts[2].color = Color.black;
        verts[2].uv0 = Vector2.zero;

        verts[3].position = new Vector3(100, 0);
        verts[3].color = Color.blue;
        verts[3].uv0 = Vector2.zero;

        vh.AddUIVertexQuad(verts);
    }
}

二.相關api

using UnityEngine;
using UnityEngine.UI;

public class TestMesh : BaseMeshEffect {

    public override void ModifyMesh(VertexHelper vh)
    {
        vh.Clear();
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        vh.AddVert(new Vector3(100, 0), Color.blue, Vector2.zero);
        vh.AddTriangle(0, 1, 2);
        vh.AddTriangle(2, 3, 0);

        //頂點有4個,索引有6個
        Debug.Log(vh.currentIndexCount);
        Debug.Log(vh.currentVertCount);

        //PopulateUIVertex,返回頂點數據。當前取值範圍:0-3
        UIVertex vertex = new UIVertex();
        vh.PopulateUIVertex(ref vertex, 0);
        Debug.Log(vertex.color);
        vh.PopulateUIVertex(ref vertex, 3);
        Debug.Log(vertex.color);

        //SetUIVertex,設置頂點數據
        vertex.color = Color.yellow;
        vh.SetUIVertex(vertex, 3);
    }
}

輸出:

Stream流批量操作:

1.AddUIVertexStream,批量添加頂點

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TestMesh : BaseMeshEffect {

    public override void ModifyMesh(VertexHelper vh)
    {
        vh.Clear();
        List<UIVertex> verts = new List<UIVertex>();

        UIVertex vert0 = new UIVertex();
        vert0.position = new Vector3(0, 0);
        vert0.color = Color.red;
        vert0.uv0 = Vector2.zero;
        verts.Add(vert0);

        UIVertex vert1 = new UIVertex();
        vert1.position = new Vector3(0, 100);
        vert1.color = Color.green;
        vert1.uv0 = Vector2.zero;
        verts.Add(vert1);

        UIVertex vert2 = new UIVertex();
        vert2.position = new Vector3(100, 100);
        vert2.color = Color.black;
        vert2.uv0 = Vector2.zero;
        verts.Add(vert2);

        UIVertex vert3 = new UIVertex();
        vert3.position = new Vector3(100, 0);
        vert3.color = Color.blue;
        vert3.uv0 = Vector2.zero;
        verts.Add(vert3);

        List<int> indices = new List<int>() { 0, 1, 2, 2, 3, 0 };
        vh.AddUIVertexStream(verts, indices);
    }
}

2.AddUIVertexTriangleStream,批量添加三角形頂點,長度必須是3的倍數

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TestMesh : BaseMeshEffect {

    public override void ModifyMesh(VertexHelper vh)
    {
        vh.Clear();
        List<UIVertex> verts = new List<UIVertex>();

        UIVertex vert0 = new UIVertex();
        vert0.position = new Vector3(0, 0);
        vert0.color = Color.red;
        vert0.uv0 = Vector2.zero;
        verts.Add(vert0);

        UIVertex vert1 = new UIVertex();
        vert1.position = new Vector3(0, 100);
        vert1.color = Color.green;
        vert1.uv0 = Vector2.zero;
        verts.Add(vert1);

        UIVertex vert2 = new UIVertex();
        vert2.position = new Vector3(100, 100);
        vert2.color = Color.black;
        vert2.uv0 = Vector2.zero;
        verts.Add(vert2);

        vh.AddUIVertexTriangleStream(verts);
    }
}

3.GetUIVertexStream,獲取所有頂點數據

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TestMesh : BaseMeshEffect {

    public override void ModifyMesh(VertexHelper vh)
    {
        vh.Clear();
     
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        vh.AddTriangle(0, 1, 2);

        List<UIVertex> stream = new List<UIVertex>();
        vh.GetUIVertexStream(stream);
        foreach (UIVertex v in stream)
        {
            Debug.Log(v.color);
        }
    }
}

三、OnPopulateMesh

1、OnPopulateMesh函數:當一個UI元素生成頂點數據時會調用OnPopulateMesh(VertexHelper vh)函數,我們可以在這個函數中修改頂點的數據或者獲取頂點的數據。

2、VertexHelper結構:UI元素的頂點數據會填充這個數據結構,我們可以修改這個數據結構裏面的數據從而影響到頂點的一些屬性。

3、在Unity文檔中有如下的屬性和方法

AddVert:添加一個頂點到VertexHelper緩存中

AddTriangle:添加一個三角形到VertexHelper緩存中

例子:

①用AddVert和AddTriangle繪製一個三角形

創建一個腳本TestVertexHelper.cs並繼承Graphic,因爲OnPopulateMesh函數定義在Graphic中

首先用AddVert添加了三個頂點,三個頂點的關係如上圖
然後用AddTriangle添加三角形,參數是三角形頂點的索引
GPU在繪製的時候會按照 頂點0->頂點1->頂點2 來繪製一個三角形

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
 
        vh.AddTriangle(0, 1, 2);
    }
}

②用AddVert和AddTriangle繪製一個正方形

首先用AddVert添加了四個頂點,頂點的順序如圖
然後用AddTriangle添加了兩個三角形
vh.AddTriangle(0, 1, 2)表示用 頂點0,1,2 來繪製一個三角形
vh.AddTriangle(2, 3, 0)表示用 頂點2,3,0 來繪製一個三角形

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        //添加四個頂點
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        vh.AddVert(new Vector3(100, 0), Color.blue, Vector2.zero);
        //添加兩個三角形
        vh.AddTriangle(0, 1, 2);
        vh.AddTriangle(2, 3, 0);
    }
}

屬性currentIndexCount 和currentVertCount

currentVertCount:VertexHelper結構中有幾個頂點

currentIndexCount:VertexHelper結構中有幾個頂點索引

來打印一下剛纔繪製的正方形的信息

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        //添加四個頂點
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        vh.AddVert(new Vector3(100, 0), Color.blue, Vector2.zero);
        //添加兩個三角形
        vh.AddTriangle(0, 1, 2);
        vh.AddTriangle(2, 3, 0);
 
        Debug.Log("currentIndexCount " + vh.currentIndexCount);
        Debug.Log("currentVertCount " + vh.currentVertCount);
    }
}

可以看到頂點索引有四個,頂點有六個。頂點索引有四個(0,1,2,3)這個好理解,但是我們用AddVert添加了四個頂點,這裏怎麼顯示有六個呢?因爲unity會把三角形交界處的頂點分成兩個。即三角形(0,1,2)和三角形(2,3,0)重合的頂點0,2會被分成兩個頂點來處理。

PopulateUIVertex函數

PopulateUIVertex:返回指定索引的頂點數據,返回的頂點數據會填充UIVertex數據結構

例子:

使用PopulateUIVertex函數獲取索引爲2的頂點數據,然後打印出來

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        //添加四個頂點
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        vh.AddVert(new Vector3(100, 0), Color.blue, Vector2.zero);
        //添加兩個三角形
        vh.AddTriangle(0, 1, 2);
        vh.AddTriangle(2, 3, 0);
 
        UIVertex vertex = new UIVertex();
        vh.PopulateUIVertex(ref vertex, 2);
        Debug.Log("color " + vertex.color + " position " + vertex.position + " uv0 " + vertex.uv0);
    }
}

看到這個數據,和我們設置的第三個頂點的數據是一樣的

SetUIVertex函數

SetUIVertex:設置一個頂點的數據

例子:把上面第三個頂點的顏色設置爲了黑色(vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);),我們通過SetUIVertex函數把第三個頂點(索引爲2的頂點,索引從0開始)的三色設置爲黃色

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        //添加四個頂點
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        vh.AddVert(new Vector3(100, 0), Color.blue, Vector2.zero);
        //添加兩個三角形
        vh.AddTriangle(0, 1, 2);
        vh.AddTriangle(2, 3, 0);
 
        //得到第三個頂點(頂點索引爲2,從0開始)的顏色
        UIVertex vertex = new UIVertex();
        vh.PopulateUIVertex(ref vertex, 2);
        //設置顏色爲黃色
        vertex.color = Color.yellow;
        vh.SetUIVertex(vertex, 2);
    }
}

可以看到索引爲2的頂點變成了黃色

 

AddUIVertexQuad(UIVertex[] verts)函數

AddUIVertexQuad:增加一個長方形

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        UIVertex[] verts = new UIVertex[4];
        verts[0].position = new Vector3(0, 0);
        verts[0].color = Color.red;
        verts[0].uv0 = Vector2.zero;
 
        verts[1].position = new Vector3(0, 100);
        verts[1].color = Color.green;
        verts[1].uv0 = Vector2.zero;
 
        verts[2].position = new Vector3(100, 100);
        verts[2].color = Color.black;
        verts[2].uv0 = Vector2.zero;
 
        verts[3].position = new Vector3(100, 0);
        verts[3].color = Color.blue;
        verts[3].uv0 = Vector2.zero;
 
        vh.AddUIVertexQuad(verts);
    }
}

可以看到這個方法和繪製兩個三角形產生的效果是一樣的

 

public void AddUIVertexStream(List<UIVertex> verts, List<int> indices)函數

AddUIVertexStream:向VertexHelper中批量增加頂點數據,第一個參數爲頂點數據,第二個參數爲構成圖元的頂點索引目錄

假如我們要繪製兩個三角形,加入我們有兩個三角形,頂點索引分別爲(0,1,2),(2,3,0),那麼我們的indices應該定義爲

List<int> indices = new List<int>() { 0, 1, 2, 2, 3, 0 };

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        List<UIVertex> verts = new List<UIVertex>();
 
        UIVertex vert0 = new UIVertex();
        vert0.position = new Vector3(0, 0);
        vert0.color = Color.red;
        vert0.uv0 = Vector2.zero;
        verts.Add(vert0);
 
        UIVertex vert1 = new UIVertex();
        vert1.position = new Vector3(0, 100);
        vert1.color = Color.green;
        vert1.uv0 = Vector2.zero;
        verts.Add(vert1);
 
        UIVertex vert2 = new UIVertex();
        vert2.position = new Vector3(100, 100);
        vert2.color = Color.black;
        vert2.uv0 = Vector2.zero;
        verts.Add(vert2);
 
        UIVertex vert3 = new UIVertex();
        vert3.position = new Vector3(100, 0);
        vert3.color = Color.blue;
        vert3.uv0 = Vector2.zero;
        verts.Add(vert3);
 
        List<int> indices = new List<int>() { 0, 1, 2, 2, 3, 0 };
        vh.AddUIVertexStream(verts, indices);
    }
}

效果:

 void AddUIVertexTriangleStream(List<UIVertex> verts)函數

AddUIVertexTriangleStream:向VertexHelper中批量增加三角形頂點數據,參數的長度必須是三的倍數

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        List<UIVertex> verts = new List<UIVertex>();
 
        UIVertex vert0 = new UIVertex();
        vert0.position = new Vector3(0, 0);
        vert0.color = Color.red;
        vert0.uv0 = Vector2.zero;
        verts.Add(vert0);
 
        UIVertex vert1 = new UIVertex();
        vert1.position = new Vector3(0, 100);
        vert1.color = Color.green;
        vert1.uv0 = Vector2.zero;
        verts.Add(vert1);
 
        UIVertex vert2 = new UIVertex();
        vert2.position = new Vector3(100, 100);
        vert2.color = Color.black;
        vert2.uv0 = Vector2.zero;
        verts.Add(vert2);
 
        vh.AddUIVertexTriangleStream(verts);
    }
}

效果:

GetUIVertexStream(List<UIVertex> stream)函數

GetUIVertexStream:獲取當前VertexHelper中的所有頂點的信息

public class TestVertexHelper : Graphic
{
 
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        //添加三個頂點
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        //添加三角形
        vh.AddTriangle(0, 1, 2);
        //得到所有頂點的信息
        List<UIVertex> stream = new List<UIVertex>();
        vh.GetUIVertexStream(stream);
        foreach (UIVertex v in stream) {
            Debug.Log("color " + v.color + " position " + v.position + " uv0 " + v.uv0);
        }
    }
}

可以看到輸出日誌的值和輸入的頂點信息一樣

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章