当前位置:网站首页>Unity3d learning notes 5 - create sub mesh

Unity3d learning notes 5 - create sub mesh

2022-07-07 23:21:00 charlee44

1. summary

In the article Unity3D Learning notes 4—— establish Mesh Advanced interface Through advanced API The way to create a Mesh, It also mentioned a SubMesh The concept of .Mesh It is the encapsulation concept of three-dimensional objects , An easy requirement is , I want to use materials in some places A, I want to use materials in some places B, I don't want to put this Mesh To break up , So it's very simple , That's it Mesh Divided into two sub Mesh That's all right. .

2. Detailed discussion

2.1. Realization

We create the following script , And casually attach two different materials in the attribute material1 And attribute material2 On :

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()
    {
    
        
    }
}

The effect I get here is as follows :

imglink1

2.2. analysis

Obviously , I created two quadrangles here , And put it in a Mesh Next . I use a simple interface to create vertex attributes , Creating vertex index attribute information uses a high-level interface . The key point is to SubMesh Description of :

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 Class defines which vertex index to start with , How long is the space after that SubMesh, That is to say Mesh Made a division . in addition ,GameObject The number of materials attached to the should also correspond :

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 It can be connected with multiple materials , How many SubMesh How many materials should there be , They are one-to-one . The quantity is not corresponding Unity The editor will report an error .

By dividing SubMesh To describe a Mesh It is usually used when there are multiple materials , If you use the same material , You'd better not do SubMesh Divide . We turn on Frame Debug, You can see :
imglink2

One Mesh It is divided into two rendering instructions ! The reason is that image engine is usually a state machine , A material needs to correspond to a rendering instruction , This is why we tend to reuse materials as much as possible , Reduce the number of different materials .

3. Reference resources

  1. Unity3D Learning notes 4—— establish Mesh Advanced interface
原网站

版权声明
本文为[charlee44]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/188/202207072022149636.html