1.Mesh概念与组成
Unity中想要显示一个3D模型,必须要知道该模型的形状,这个形状其实就是mesh数据。有了mesh数据后,再通过Mesh Filter组件将mesh数据发送给Mesh Renderer组件进行渲染。Mesh Filter组件不一定每个gameObject对象都有,但是Mesh Rnderer组件是一定有的。我们也可以自定义mesh的数据,然后挂上一个Mesh Renderer组件从而渲染出我们想要的效果。
Mesh概念:Mesh是模型的网格,通过点构成线,再由线构成三角形,最后由三角形构成面,然后通过材质来进行网格表面的表达,如阴影,贴图等。Unity除了ui的mesh,其他都需要MeshFilter来确定网格形状,通过Material以及MeshRenderer来进行网格渲染。
Mesh组成:
1.顶点坐标(vertex):顶点是网格最基础的组成部分,可通过mesh.vertices获取和赋值。
mesh.vertices是一个Vector3的数组,每个Vector3为此顶点与此游戏物体的相对坐标(local position)。
顶点的位置,数量没有任何限制。几个同样的顶点可以组合成若干不同形状,不同数量的三角形。
2.法线(normal):法线就是垂直于面的一条线,它有方向,没有大小。可通过mesh.normals获取和赋值。法线数组存放mesh每个顶点的法线,大小与顶点坐标对应,normal[i]对应顶点vertex[i]的法线。法线向外的面就是正面,相反的就是背面,一般来讲,从正面看才能看到面,背面看面是看不到的。可以通过mesh.RecalculateNormals()来计算。
3.纹理坐标(uv):Unity中想要显示一个3D模式,必须要知道该模式的形状,这个形状其实就是mesh数据。有了mesh数据后,再通过Mesh Filter组件将mesh数据发送给Mesh Renderer组件进行渲染。Mesh Filter组件不一定每个gameObject对象都有,但是Mesh Rnderer组件是一定有的。那么我们就可以自定义mesh的数据,然后挂上一个Mesh Renderer组件从而渲染出我们想要的效果。
uv值用处很多,例如材质texture的采样,或是利用它的一些特性(范围0-1;同一个uv区域每个像素的uv值皆不同)进行GPU内的一些计算。mesh.uv作为一个Vector2数组与mesh.vertices的长度必须一致,每个uv的顺序与vertices的顺序也是一一对应,既uv[0]代表的是vertices[0]的uv值。而与三角形组成的顺序无关。当每个顶点被赋予uv值后,在片段着色阶段,片段着色器将会根据顶点的uv值将此三角形覆盖的每个像素的uv值进行自动插值。uv插值是以三角形为单位进行的,既三角形ABC内各个像素的uv值与其他周边三角形各顶点的uv值是无关的。
4.三角形序列(triangle):triangles是一个int数组,这个数组是包含顶点数组索引的三角形列表。
三角形数组的大小是3的倍数,每三个int代表的是由哪三个顶点并由什么顺序(朝向)来组成一个三角形。
mesh.triangles决定了网格中的三角形的形状和朝向。三角形的渲染顺序与三角形的正面法线呈左手螺旋定则。三角形的三个点顺时针的是朝向我们,逆时针则背对我们。
5.MeshFilter(网格过滤器):MeshFilter含有一个Public成员 Mesh。在Mesh中存储着三维模型的数据(uv,triangle,vertex等)
二.四边形Mesh源码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class QuadMeshTest:MeshTest
{
//2 * size
public int size = 20;
//顶点
protected override Vector3[] Vertices
{
get
{
Vector3[] vertices = new Vector3[4];
vertices[0] = new Vector3(-1, 1, 0) * size;
vertices[1] = new Vector3(-1, -1, 0) * size;
vertices[2] = new Vector3(1, -1, 0) * size;
vertices[3] = new Vector3(1, 1, 0) * size;
return vertices;
}
}
//三角形序列
protected override int[] Triangles
{
get
{
//顺时针面向
int[] triangles = new int[6]
{
1, 0, 3, 3, 2, 1
};
// //逆时针背对
// int[] triangles = new int[6]
// {
// 1, 2, 3, 3, 0, 1,
// };
//
// //双面网格
// int[] triangles = new int[12]
// {
// 1, 2, 3, 3, 0, 1, 1, 0, 3, 3, 2, 1
// };
return triangles;
}
}
protected override string MeshName
{
get
{
return "QuadMesh";
}
}
//纹理坐标
protected override Vector2[] Uvs
{
get
{
Vector2[] uvs = new Vector2[4];
uvs[0] = new Vector2(0, 1);
uvs[1] = new Vector2(0, 0);
uvs[2] = new Vector2(1, 0);
uvs[3] = new Vector2(1, 1);
return uvs;
}
}
//法线
protected override Vector3[] Normals
{
get
{
mesh.RecalculateNormals();
return mesh.normals;
}
}
}