Unity3D学习笔记5——创建子Mesh

简介: Unity3D学习笔记5——创建子Mesh

Unity3D学习笔记5——创建子Mesh

目录

1. 概述

在文章Unity3D学习笔记4——创建Mesh高级接口通过高级API的方式创建了一个Mesh,里面还提到了一个SubMesh的概念。Mesh是对于三维物体对象的封装概念,一个很容易的需求是,有的地方我希望用到材质A,有的地方我希望用到材质B,我不想把这个Mesh进行拆分,那么很简单,就在这个Mesh中划分两个子Mesh就可以了。

2. 详论

2.1. 实现

我们创建如下脚本,并且随便挂接两个不同的材质在属性material1和属性material2上:

using UnityEngine;
using UnityEngine.Rendering;
[ExecuteInEditMode]
public class Note5Main : MonoBehaviour
{
    public Material material1;
    public Material material2;
   
    // Start is called before the first frame update
    void Start()
    {
        Mesh mesh = CreateMesh();
        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>();
        }
        Material[] materials = new Material[2];       
        materials[0] = material1;
        materials[1] = material2;
        meshRenderer.materials = materials;
    }
    Mesh CreateMesh()
    {
        Mesh mesh = new Mesh();
        const int vertexCount = 8;
  
        Vector3[] vertices = new Vector3[vertexCount]
        {
            new Vector3(-5, 0, 0),
            new Vector3(-5, 5, 0),
            new Vector3(5, 0, 0),
            new Vector3(5, 5, 0),
            new Vector3(-5, -5, 0),
            new Vector3(-5, 0, 0),
            new Vector3(5, -5, 0),
            new Vector3(5, 0, 0),
        };
        Vector3[] normals = new Vector3[vertexCount]
        {
            new Vector3(0, 0, -1),
            new Vector3(0, 0, -1),
            new Vector3(0, 0, -1),
            new Vector3(0, 0, -1),
            new Vector3(0, 0, -1),
            new Vector3(0, 0, -1),
            new Vector3(0, 0, -1),
            new Vector3(0, 0, -1),
        };
        Vector2[] uv = new Vector2[vertexCount]
        {
            new Vector2(0, 0),
            new Vector2(0, 1),
            new Vector2(1, 0),
            new Vector2(1, 1),
            new Vector2(0, 0),
            new Vector2(0, 1),
            new Vector2(1, 0),
            new Vector2(1, 1),
        };
        mesh.vertices = vertices;
        mesh.normals = normals;
        mesh.uv = uv;
        int[] triangles = new int[12] { 0, 1, 2, 1, 3, 2, 4, 5, 6, 5, 7, 6 };
        MeshUpdateFlags flags = MeshUpdateFlags.DontValidateIndices | MeshUpdateFlags.DontResetBoneBounds
         | MeshUpdateFlags.DontNotifyMeshUsers | MeshUpdateFlags.DontRecalculateBounds;
        //MeshUpdateFlags flags = MeshUpdateFlags.Default;
        int indexCount = triangles.Length;
        mesh.SetIndexBufferParams(indexCount, IndexFormat.UInt32);
        mesh.SetIndexBufferData(triangles, 0, 0, indexCount, flags);
        mesh.subMeshCount = 2;
        SubMeshDescriptor subMeshDescriptor1 = new SubMeshDescriptor(0, 6);
        mesh.SetSubMesh(0, subMeshDescriptor1, flags);
        SubMeshDescriptor subMeshDescriptor2 = new SubMeshDescriptor(6, 6);
        mesh.SetSubMesh(1, subMeshDescriptor2, flags);
        return mesh;
    }
    // Update is called once per frame
    void Update()
    {
        
    }
}

我这里得到的效果如下:

2.2. 解析

很明显,我这里创建了两个四边形,并且将其放到一个Mesh下。创建顶点属性我使用的是简单接口,创建顶点索引属性信息使用的是高级接口。关键点在于对SubMesh的描述:

mesh.subMeshCount = 2;
SubMeshDescriptor subMeshDescriptor1 = new SubMeshDescriptor(0, 6);
mesh.SetSubMesh(0, subMeshDescriptor1, flags);
SubMeshDescriptor subMeshDescriptor2 = new SubMeshDescriptor(6, 6);
mesh.SetSubMesh(1, subMeshDescriptor2, flags);

SubMeshDescriptor类定义了从那个顶点索引开始,之后多长的空间是一个SubMesh,也就是对Mesh做了一个划分。另外,GameObject上挂接的材质个数也要对应:

MeshRenderer meshRenderer = gameObject.GetComponent<MeshRenderer>();
if (meshRenderer == null)
{
    meshRenderer = gameObject.AddComponent<MeshRenderer>();
}
Material[] materials = new Material[2];       
materials[0] = material1;
materials[1] = material2;
meshRenderer.materials = materials;

MeshRenderer上能挂接多个材质,有多少个SubMesh就应该有多少个材质,它们是一一对应的。数量没对应上Unity编辑器会报错。

通过划分SubMesh的方式来描述一个Mesh通常是用于存在多个材质的情况,如果使用的都是同一个材质,就最好不要作SubMesh划分。我们打开Frame Debug,可以看到:

一个Mesh分成了居然两个渲染指令来实现!原因在于图像引擎通常是一个状态机,一个材质需要对应一个渲染指令,这就是为什么我们往往要尽可能复用材质,减少不同材质的个数。

3. 参考

  1. Unity3D学习笔记4——创建Mesh高级接口

分类: Unity3D

标签: Mesh , Unity3D


相关文章
|
编解码 图形学
浅谈Unity之ShaderGraph学习笔记-03
每日记录自己学习unity的心得和体会
|
3月前
|
缓存 图形学
Unity3D学习笔记12——渲染纹理
Unity3D学习笔记12——渲染纹理
40 2
|
3月前
|
API C# 图形学
Unity3D学习笔记9——加载纹理
Unity3D学习笔记9——加载纹理
41 2
|
3月前
|
API 图形学 异构计算
Unity3D学习笔记7——GPU实例化(2)
Unity3D学习笔记7——GPU实例化(2)
27 2
|
3月前
|
存储 缓存 图形学
Unity3D学习笔记11——后处理
Unity3D学习笔记11——后处理
60 1
|
3月前
|
测试技术 C# 图形学
Unity3D学习笔记10——纹理数组
Unity3D学习笔记10——纹理数组
50 0
|
3月前
|
图形学 异构计算
Unity3D学习笔记8——GPU实例化(3)
Unity3D学习笔记8——GPU实例化(3)
46 0
|
3月前
|
存储 API 图形学
Unity3D学习笔记6——GPU实例化(1)
Unity3D学习笔记6——GPU实例化(1)
60 0
|
3月前
|
API C# 图形学
Unity3D学习笔记4——创建Mesh高级接口
Unity3D学习笔记4——创建Mesh高级接口
39 0
|
3月前
|
C# 图形学 C语言
Unity3D学习笔记3——Unity Shader的初步使用
Unity3D学习笔记3——Unity Shader的初步使用
47 0