IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 杂篇-01-Unity中创建Mesh时遇到的问题 -> 正文阅读

[游戏开发]杂篇-01-Unity中创建Mesh时遇到的问题

摘要

今天在做水渲染时,需要手动创建一个顶点数很多的Mesh让波形更加精准,写一个MeshCreater脚本,其中遇到了一些Unity限制的问题。

MeshCreater

首先了解Unity的Mesh

  • 每一个GameObj 拥有两个组件MeshFilter和MeshRender,MeshFilter存储Mesh,MeshRender渲染Mesh

1.Mesh类

包含变量

  • Vector3[] vertices 顶点信息

  • Vector2[] uv 每个顶点对应的uv信息

  • int[] triangles 三角形包含的顶点的下标(构成面)

2.MeshFilter类

继承自Component,需要挂到GameObj上

包含变量

  • Mesh (可以是assert直接赋值,或者程序赋值)

3.MeshRender类

继承自Component,需要挂到GameObj上

自动获取Menfilter中的mesh信息,进行渲染,其中可以为各个submesh添加独立material

问题

在制作MeshCreater时,制作了个showvertex的脚本用于显示mesh的顶点,发现以下问题

  • 每个Mesh只是一个独立的模型信息,Mesh的Vertex不会随着物体的Transform改变,需要对vertex进行Transform.transformPoint(vertex)处理后才能和游戏物体的vetex重合。

  • 使用OnDrawGizmos 内用Gizmos绘制物体可以在Editor下进行辅助绘制,这些绘制不会再Game中出现

另一个问题,即Unity单个mesh绘制的顶点数 不能超过65535,如果超过则必须拆分绘制使用SetTriangles

在进行水渲染的时候需要大量密集的mesh顶点,超过65000很正常

  • 拆分绘制中遇到很多问题

    此时我的基本理解是,一个triangles[]中的最大和最小下标的差值不能超过65000

    submesh共用vertices,使用独立的triangles,根据baseVertex对triangles中的值进行偏移

    • 拆分成多少个submesh,每个submesh中的三角形数据如何取?

      • 如果按照60000为一个submesh,也就是直接将mesh中前编号为0~60000的顶点作为一个triangles,编号为后面的继续分组,那么如何确定细分的这个vetices对应的triangles的大小呢?如16个顶点,2x8的顶点对应1x7=7个正方形,需7x2x3=42大小的triangle,4x4的顶点对应3x3=9个正方形,需9x2x3=54大小的triangle,这还是规则情况下,如果60000个顶点由13*1000的mesh分割开来,必定是一个多矩形和,更加复杂。舍弃该方法。

      • 按长宽关系分割,除了某些情况如长宽大于60000,根本无法分割成整宽或者整长的mesh

        分割出来的mesh只有长宽值为1无法构成正方形,根本无法构成三角形

    • 多个submesh之间的triangle信息缺失

      这里对Unity内部的处理caculateBounds = true 之后和其为false值 究竟有什么区别?还是有疑问

上次讲到在创建均匀的正方形Mesh时,如果长宽乘积超过65535就会出现问题,所以尝试使用SubMesh来多次绘制,在取各个SubMesh的Triangles值时遇到很多问题。下面来解决

设置缓冲区格式

最简单的方法莫过于修改这个65535的限制

mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32

一般默认的indexFormat设置的是16位 对应最大值就是65535 2^16-1(index是无符号的)

修改为32位后最大值变为4294967295即2^32-1

这样做对于每个mesh来说存储空间更大了,在有大量mesh时会消耗更多的资源,同时不是所有的设备平台的GPU都支持32位索引,在使用时需要慎重。

SubMesh.SetTriangles

官方文档提供的方案是使用该函数使用对超过65535索引值的顶点进行访问,具体通过参数baseVertex对索引值进行偏移

public void SetTriangles (int[] triangles, int submesh, bool calculateBounds= true, int baseVertex= 0);

现在问题是在生成width*height个顶点的矩形场景下取triangles

创建mesh流程

  • 设置trianglesGroup[] []

  • 遍历Mesh的每个正方形,将每个正方形的顶点索引转化为2个三角形 即6个triangles值放在trianglesGroup[GIndex] [index]下

如何控制GIndex 和 Index 使得 trianglesGroup中的所有值都在65535范围内,且可以设置对应的Vertex偏移。

尝试解决思路

  • 一旦出现一个三角形内的两个顶点索引之差>65535则问题必无法解决,因为其需要共用同一个Vertex偏移,无论如何控制都无法保证其中两个值在0~65535范围内。所以使用该方法无法从根本上解决问题。所以最终方案不会选择该方法,下面只是为了好玩尝试在限制条件内尝试解决一下。

  • 为了防止边界问题,可以修改为生成width*height宽高的矩形,

    • 对应(width+1) x (height+1)个顶点,width x height 个小正方形,对应width x height x 6 个triangle

    • 每个小正方形看做独立单元,不考虑顶点重合和不重合的情况

    • 当索引到第index个小正方形 ,index > 65000时 切换到另一个triangles数组存储值

    • 为了为每个triangles分配空间,需要提前计算出每个triangles数组的大小 (如果用交错数组的话)

      • 每个正方体占用6大小的triangles

      • 先计算出总共需要squireSize个正方形,则需要squireSize * 4 / 65000 + 1个triangles,

    • 新的问题,实际上(x,y)的正方形其包含的四个顶点的下标最大值为y x (width+1) + x ,并不是第x个正方形的顶点最大值为(y x width + x)*4 , 所以该方法根本无法使用 :( 不过采用正方体的width和height更加便于理解,保留该设置。

  • 在进行vertex生成时就对编号进行处理,使得每个正方形的四个角的编号相同

    • 这样做的后果是,必须每个正方形单独分配4个顶点,否则根本无法实现(或者实现起来非常复杂)

总结

  • Unity中Mesh的顶点数量默认最大值为65535,如果超过会出现问题,可以通过以下代码修改限制为2^32-1

mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32

  • 在外部导入模型的时候,可使用submesh,在外部的Maya,Max等建模的时候设置好顶点范围

    • 如帽子,衣服,裤子,头部等等分成独立的submesh,使得每个个体顶点数在限制范围内

  • submesh也以采用不同的材质,可以做出某些效果。

思考

  • 引擎的限制,会导致其对美术资源有一定的限制,所以对美术资源的把关非常重要,有时候会为了效果去研究修改引擎底层的限制,有时候为了表现的性能,平台的兼容,研究开发能力的限制,导致不得不牺牲效果。需要在技术和美术之间的权衡,这是一件非常需要经验的事情,只能慢慢向前走了。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-08-28 09:41:08  更:2021-08-28 09:41:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 10:38:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码