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学习笔记5——创建子Mesh的更多相关文章

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

    目录 1. 概述 2. 详论 3. 其他 4. 参考 1. 概述 在文章Unity3D学习笔记2--绘制一个带纹理的面中使用代码的方式创建了一个Mesh,不过这套接口在Unity中被称为简单接口.与其 ...

  2. Unity3D学习笔记——游戏组件之Mesh(网格组件)

    Mesh:网格组件.主要用于设置外形和外表. Mesh Filter:网格过滤器.就是为游戏对象添加一个外形. 例:设置外形为Sphere  如果获取的网格拥有蒙皮信患,Unity将自动创建一个skn ...

  3. Unity3D学习笔记3——Unity Shader的初步使用

    目录 1. 概述 2. 详论 2.1. 创建材质 2.2. 着色器 2.2.1. 名称 2.2.2. 属性 2.2.3. SubShader 2.2.3.1. 标签(Tags) 2.2.3.2. 渲染 ...

  4. Unity3D学习笔记2——绘制一个带纹理的面

    目录 1. 概述 2. 详论 2.1. 网格(Mesh) 2.1.1. 顶点 2.1.2. 顶点索引 2.2. 材质(Material) 2.2.1. 创建材质 2.2.2. 使用材质 2.3. 光照 ...

  5. Unity3D学习笔记6——GPU实例化(1)

    目录 1. 概述 2. 详论 3. 参考 1. 概述 在之前的文章中说到,一种材质对应一次绘制调用的指令.即使是这种情况,两个三维物体使用同一种材质,但它们使用的材质参数不一样,那么最终仍然会造成两次 ...

  6. Java学习笔记-多线程-创建线程的方式

    创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...

  7. springmvc学习笔记---idea创建springmvc项目

    前言: 真的是很久没搞java的web服务开发了, 最近一次搞还是读研的时候, 想来感慨万千. 英雄没落, Eclipse的盟主地位隐隐然有被IntelliJ IDEA超越的趋势. Spring从2. ...

  8. unity3d学习笔记(一) 第一人称视角实现和倒计时实现

    unity3d学习笔记(一) 第一人称视角实现和倒计时实现 1. 第一人称视角 (1)让mainCamera和player(视角对象)同步在一起 因为我们的player是生成的,所以不能把mainCa ...

  9. Unity3D学习笔记7——GPU实例化(2)

    目录 1. 概述 2. 详论 2.1. 实现 2.2. 解析 3. 参考 1. 概述 在上一篇文章<Unity3D学习笔记6--GPU实例化(1)>详细介绍了Unity3d中GPU实例化的 ...

  10. Unity3D学习笔记8——GPU实例化(3)

    目录 1. 概述 2. 详论 2.1. 自动实例化 2.2. MaterialPropertyBlock 3. 参考 1. 概述 在前两篇文章<Unity3D学习笔记6--GPU实例化(1)&g ...

随机推荐

  1. go语言 包依赖管理-构建完整的依赖项目:目录结构及包的调用

    目录结构: <home>/ |-- greetings/ |-- hello/1.分别进入对应目录创建以上目录结构 //bash切换到用户主目录 cd $HOMEPAHT$ //bash新 ...

  2. Informix 4gl错误代码信息和更正

    (一)Informix信息和更正 出版日期:6 1996 年 年 1 11 月 0 成功. 操作成功.当 SQL 语句成功地执行时,数据库服务器把这个 SQLCODE 值返回给应用程序. 100 没有 ...

  3. 基于ZXing.NET实现的二维码生成和识别客户端

    一.前言 ZXing.Net的一个可移植软件包,是一个开源的.多格式的1D/2D条形码图像处理库,最初是用Java实现的.已经过大量优化和改进,它已经被手动移植.它与.Net 2.0..Net 3.5 ...

  4. AI图形算法之一:液位计识别

    AI人工智能的主要应用之一就是图形化处理和识别,之前写了两篇,分别是: AI图形算法的应用之一:通过图片模板对比发现油田漏油 AI图形算法的应用之一:仪表识别 经过几个晚上的辛苦,液位计识别也测试成功 ...

  5. ORB-SLAM3测试

    (一)环境搭建教程 1.Ubuntu18.04从零开始搭建orb slam3及数据集测试:https://blog.csdn.net/Skether/article/details/131320852 ...

  6. git中的ole mode 和 new mode提示问题

    git status 显示如下(文件内容其实并没有改变): old mode 100644 new mode 100755 原因是: 使用chmod修改过文件权限后,filemode会有变化. 解决办 ...

  7. 解决ADS1.2与MDK4.7冲突问题

    需要添加2个系统变量. 1,在我的电脑点击属性--->高级--->环境变量---->系统变量,增加环境变量名: ARMCC5LIB 变量值:C:\Keil\ARM\ARMCC\lib ...

  8. Seaurl-分享一个云上网址收藏网站

    前言 最近网上发现一个强大的网址收藏网站,点击这里打开,分享给大家,希望大家会喜欢. 网址空间 "网址空间"是一个专业的在线平台,它允许用户分享他们在日常生活和工作中频繁访问的网站 ...

  9. 新来个架构师,把Xxl-Job原理讲的炉火纯青

    大家好,我是三友~~ 今天来继续探秘系列,扒一扒轻量级的分布式任务调度平台Xxl-Job背后的架构原理 公众号:三友的java日记 核心概念 这里还是老样子,为了保证文章的完整性和连贯性,方便那些没有 ...

  10. 【UniApp】-uni-app-全局数据和局部数据

    前言 好,经过上个章节的介绍完毕之后,了解了一下 uni-app-全局样式和局部样式 那么了解完了全局样式和局部样式之后,这篇文章我再来给大家介绍一下 UniApp 中全局数据和局部数据 搭建演示环境 ...