假设您正在OpenGL中创建一个三维立方体。为对象(多维数据集)实现必要的顶点数据。使用指数有什么意义?
void CreateCube()
{
const Vertex VERTICES[8] =
{
{ { -.5f, -.5f, .5f, 1 }, { 0, 0, 1, 1 } },
{ { -.5f, .5f, .5f, 1 }, { 1, 0, 0, 1 } },
{ { .5f, .5f, .5f, 1 }, { 0, 1, 0, 1 } },
{ { .5f, -.5f, .5f, 1 }, { 1, 1, 0, 1 } },
{ { -.5f, -.5f, -.5f, 1 }, { 1, 1, 1, 1 } },
{ { -.5f, .5f, -.5f, 1 }, { 1, 0, 0, 1 } },
{ { .5f, .5f, -.5f, 1 }, { 1, 0, 1, 1 } },
{ { .5f, -.5f, -.5f, 1 }, { 0, 0, 1, 1 } }
};
const GLuint INDICES[36] =
{
0,2,1, 0,3,2,
4,3,0, 4,7,3,
4,1,5, 4,0,1,
3,6,2, 3,7,6,
1,6,5, 1,2,6,
7,5,6, 7,4,5
};
//....
glBufferData(GL_ARRAY_BUFFER, sizeof(VERTICES), VERTICES, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(INDICES), INDICES, GL_STATIC_DRAW);
在上面的例子中,在世界空间中创建了一个具有必要顶点的立方体。这些指数的相关性是什么?
发布于 2014-01-14 21:24:37
索引的存在是为了减少表示3D模型所需的内存占用,就像使用调色板来减少2D图像的内存占用一样。
索引允许您避免重复顶点的完整定义,如果必须复制顶点的数据,通常需要对复杂模型进行复制。
现代3D API使用三角形绘制;立方体的每个面都需要两个三角形:
A--B
|\ | This cube face has two triangles:
| \| ABD and ADC.
C--D
若要指定没有索引的面,必须指定顶点A, B, D, A, D, C
。在顶点缓冲区中重复两个顶点(A
和D
)。
但是,通过索引,您可以拥有一个顶点缓冲区,它只包含所需的顶点(A
、B
、C
和D
)和6个索引:0, 1, 3, 0, 3, 2
。由于指数通常比顶点小得多,而且许多顶点通常在实际模型中重复,这可以节省大量的空间。
请注意,一些顶点只共享部分属性。例如,当呈现一个具有纹理映射的立方体时,通常每个面都需要唯一的纹理坐标,因此您将有多个具有相同位置和不同纹理坐标的顶点。这种数量的复制是可以接受的,也是必要的;当您复制一整组顶点属性时,您就会开始看到索引的好处。
如果您的所有网格顶点都是100%不同的,则索引没有好处(实际上,您会在冗余索引缓冲区的消耗中使用更多的空间)。然而,这种情况并不总是发生。
发布于 2014-01-14 22:07:44
使用索引有三个主要目的:
其中第一个很明显,因为您可以在自己的代码中直接度量它:如果一个网格有50k个顶点,但是如果其中30k是重复的,那么就节省了内存。
第二条和第三条没有那么明显--你需要已经决定使用索引,并且你需要分析你的代码并隔离“之前”和“之后”的性能,以获得它们的度量。
对于第二种方法,硬件能够缓存最近转换的顶点的结果。如果出现了与最近转换的顶点相同的顶点,则可以使用缓存的版本,而不必再次执行计算。硬件使用索引来识别这些,因此索引对于获得这种行为是绝对必要的。
第三,无论GPU需要做多少工作,每个抽签调用都有一个CPU开销。如果其他一切都相同,在1抽签调用中绘制50k网格将比在10k绘图调用中绘制网格要快得多。但是如果你的网格是由多条组成的,或者(更糟糕的是)条和扇子的组合,你不可能在一次抽签调用中做到这一点,除非(1)使用索引,或者(2)引入退化的三角形。但是,由于指数比顶点小得多,所以在一般情况下,使用索引是首选的。
发布于 2014-01-14 21:20:40
指数表示由三个顶点组成的组构成立方体的面。不是三角形的每一组三个顶点都是三角形的面。
您可以精确地使用每个顶点一次,只需重复多次在多个三角形中使用的顶点,但这将意味着额外的顶点转换。使用索引时,只转换顶点一次,并根据需要使用它们。
https://gamedev.stackexchange.com/questions/68838
复制相似问题