网格(Mesh)基础

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;

        }
    }
}

猜你喜欢

转载自blog.csdn.net/m0_57771536/article/details/127964559