轉自:
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);
}
}
}
可以看到輸出日誌的值和輸入的頂點信息一樣