赞
踩
此文从图形学的角度讲解了什么是顶点,以及Unity中的Mesh是如何组织顶点并利用什么组件对它们进行绘制的。
简单来讲,图元就是组成图像的基本单元,比如三维模型中的点、线、面等等
https://baike.baidu.com/item/%E5%9B%BE%E5%85%83/2303188?fr=aladdin
图形学的一个环节是建模,这里的建模和美术所说的建模类似,主要在于如何表示一个物体。
计算机中,要绘制一个物体和现实生活中一样,由点构成线,再由线构成面,最后由若干个面构成一个物体。
例如下图中,左图利用三个点绘制了一个三角形,而右图则通过两个三角形得到了一个四边形:
注:这里需要注意的是,很明显从左图中给定的三个点,有两种方式可以得到三角图元,即
它们的区别在哪里呢?类似于物理中左右手判断法则,拇指指示了三角图元的法线方向。法线其中一个作用是指明了三角图元的方向,如果从反方向看的话,这个图元是不可见的。(Unity中的Plane同理,只有一面可见)
法线另外的作用可以用来计算光照,不过那不在本文的讨论范围内,感兴趣的可以了解相关的图形学知识)
更复杂一些,即使是美术建模的模型,从图形学的角度上看,其实也就是一堆三角面片的集合:
因此,要表示一个物体,使用三角(triangle)图元作为基本元素就足够了。
(*注:图形接口(如OpenGL和DirectX3D)可能会提供其他规格如四边形的基本图元绘制的规则,但实际上出于统一、直观的原因,一般采用Triangle而不是Quad)
既然上面已经对图形的基本元素图元(primitive)有了一定的认识,那么图元究竟如何在计算机中表示呢?
其实上面的图(第一张图)已经暗示了,可以使用三维坐标来表示每一个点的位置。
假设我们有Vector2类,它表示一个二维坐标。(三维坐标系同理,只是多了一个维度z)
那么要绘制上图中的三角形,即问题在于表达三个点的坐标,也就可以表示为下面的代码:
(注: 数值无意义,仅表示数值1,单位需要定义)
Vector2[] vertices = new Vector2[]{
new Vector2( 0, 0 ), // p0
new Vector2( 0, 1 ), // p1
new Vector2( 1, 0 ), // p2
};
而如果要绘制四边形,也就需要六个点的坐标,如下面所示:
Vector2[] vertices = new Vector2[]{
// 三角图元 0
new Vector2( 0, 0 ), // p0
new Vector2( 0, 1 ), // p1
new Vector2( 1, 0 ), // p2
// 三角图元 1
new Vector2( 0, 1 ), // p1
new Vector2( 1, 1 ), // p3
new Vector2( 1, 0 ), // p2
};
事实上这些数据在OpenGL中,就是VBO(Vertex Buffer Object,顶点缓冲对象)
如果单纯使用顶点来表示(绘制)图形,是非常直观的——因为我们知道每一个顶点的位置信息,并且知道每三个点构成一个三角图元。然而从上面绘制四边形的数据中可以发现,三角图元1中有两个顶点的位置信息(p1和p3)和三角图元0是一样的。这也就增加了一些开销。
假设有n个面,而且每个面之间都是两两相连的(这要求n>=3),那么也就会多增加 2 * n个顶点的开销。如果是三维的Vector3(3 * 4 byte= 12 byte),将会增加 2 * n * 12 byte = 24 * n byte的开销。而一个模型少说都有上千个面,更不用说一个顶点不止保存有位置信息了(其他还会有法线信息,贴图纹理坐标信息等)。
总而言之,这个额外的存储开销是完全可以去除的,方法就是使用索引(Indices)。
简单来说,我们仍然使用vertices存储顶点的位置信息,但是vertices只存储不重复的部分,改为使用vertices数组的indices来表示三角图元。听上去有点拗口,那么就来看代码吧:
Vector2[] vertices = new Vector2[]{
new Vector2( 0, 0 ), // p0
new Vector2( 0, 1 ), // p1
new Vector2( 1, 0 ), // p2
};
int[] indices = new indices[]{
0, 1, 2 // 表示 0->1->2 构成一个三角图元
};
没错,indices就是这么一回事,原来是vertices数组中,每三个顶点表示一个三角图元,现在是indices数组中,每三个整型表示一个图元。这些整形不存储真正的数据,只有用到时才从vertices中取出,也就是所谓的索引了。
(你可能会觉得比起原来的,这不是额外增加了indices的开销吗,硬要回答的话,emm只能说这个是特殊情况)
为了让上面的indices不那么蠢,那么接下来看看原来的四边形,应用了indices后是怎样的:
Vector2[] vertices = new Vector2[]{
new Vector2( 0,
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。