1. 概述
在文章Unity3D學習筆記2——繪製一個帶紋理的面中使用程式碼的方式建立了一個Mesh,不過這套介面在Unity中被稱為簡單介面。與其相對應的,Unity還提供了一套高階API來建立Mesh。
2. 詳論
根據Unity文件的論述,使用高階介面能夠得到更高的效能,能夠跳過一些驗證檢查。但是這並不是最關鍵的,簡單介面有個最大的缺點是頂點個數超過65535個時就有問題(至少在2019.4.3f1版本還是這樣)。
話不多說,直接上程式碼:
using UnityEngine;
using UnityEngine.Rendering;
[ExecuteInEditMode]
public class Note4Main : MonoBehaviour
{
public Material material;
// Start is called before the first frame update
void Start()
{
Mesh mesh = new Mesh();
mesh.name = "quad";
//頂點資料
VertexAttributeDescriptor[] vertexAttributeDescriptorList = new[]{
new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3),
new VertexAttributeDescriptor(VertexAttribute.Normal, VertexAttributeFormat.Float32, 3),
new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 2)};
const int vertexCount = 4;
const int verticesAttributeBufferLength = vertexCount * (3 + 3 + 2);
float[] verticesAttributeBuffer = new float[verticesAttributeBufferLength] {
-5, -5, 0, 0, 0, -1,0, 0,
-5, 5, 0, 0, 0, -1, 0, 1,
5, -5, 0, 0, 0, -1, 1, 0,
5, 5, 0, 0, 0, -1, 1, 1
};
mesh.SetVertexBufferParams(vertexCount, vertexAttributeDescriptorList);
mesh.SetVertexBufferData(verticesAttributeBuffer, 0, 0, verticesAttributeBufferLength, 0);
int[] triangles = new int[6] { 0, 1, 2, 1, 3, 2 };
int indexCount = triangles.Length;
//頂點索引檔案
mesh.SetIndexBufferParams(indexCount, IndexFormat.UInt32);
mesh.SetIndexBufferData(triangles, 0, 0, indexCount);
//子Mesh描述
mesh.subMeshCount = 1;
SubMeshDescriptor subMeshDescriptor = new SubMeshDescriptor(0, indexCount);
mesh.SetSubMesh(0, subMeshDescriptor);
MeshFilter mf = gameObject.GetComponent<MeshFilter>();
if (mf == null)
{
mf = gameObject.AddComponent<MeshFilter>();
}
mf.sharedMesh = mesh;
MeshRenderer meshRenderer = gameObject.GetComponent<MeshRenderer>();
if (meshRenderer == null)
{
meshRenderer = gameObject.AddComponent<MeshRenderer>();
}
meshRenderer.material = material;
}
// Update is called once per frame
void Update()
{
}
}
最後可以直接得到與Unity3D學習筆記2——繪製一個帶紋理的面一樣的效果。如果有一些圖形基礎,就會很容易理解這段程式碼。都是申請一個buffer,定義頂點的描述資訊,這裡是按照x,y,z,nx,ny,nz,u,v的順序,一個頂點一個頂點進行排列。接著是定義一個頂點索引buffer;不同的是增加了一個對於子mesh的描述。在Unity裡,一個Mesh可以包含多個子Mesh,每個子Mesh都能對應MeshRenderer中的多個材質中的一個。
3. 其他
- 根據官方文件論述,這套高API效能更高。但個人使用感覺不是很明顯。跳過驗證的設定也可能帶來一些其他問題,我一般用預設設定。
- 另一個優點是,可以避免簡單介面中頂點個數超過65535時Mesh繪製不正確的問題。理論上,繪製的批次越少越好,這就要求儘可能合批次繪製,同樣頂點個數的物體分多個mesh繪製,效能比不上使用一個大的Mesh一次繪製。
- 官方文件還提到了有其他介面可以通過C# Jobs和Burst建立Mesh,C# Jobs與多執行緒相關,難道意味著可以在多執行緒下建立Mesh了?有待進一步研究。