前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Unity3D学习笔记5——创建子Mesh

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

作者头像
charlee44
发布2022-07-12 16:59:54
6150
发布2022-07-12 16:59:54
举报
文章被收录于专栏:代码编写世界代码编写世界

目录

1. 概述

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

2. 详论

2.1. 实现

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

代码语言:javascript
复制
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的描述:

代码语言:javascript
复制
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上挂接的材质个数也要对应:

代码语言:javascript
复制
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高级接口
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-07-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 概述
  • 2. 详论
    • 2.1. 实现
      • 2.2. 解析
      • 3. 参考
      相关产品与服务
      图像处理
      图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档