3D渲染中索引的目的是什么?


11

假设您正在OpenGL中创建3D立方体。为对象(多维数据集)实现必要的顶点数据。使用索引的意义是什么?

v

 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);

在上面的示例中,创建了具有世界空间中必要顶点的多维数据集。指数的相关性是什么?


1
在许多地方,您会看到人们称呼他们的面孔。那就是它们。每个面通常由3个顶点组成,形成一个三角形。因此,每个3个索引对应于最终网格中的一个三角形。它们之所以称为索引,是因为它们主要是实际顶点信息在顶点数组中位置的偏移量。我想您可能需要了解有关索引的全部信息:)
Grimshaw

Answers:


24

存在减少表示3D模型所需的内存占用量的指标,其方式与使用调色板来减少2D图像的内存占用量的方式非常相似。

索引允许您避免重复顶点的完整定义,如果您必须复制该顶点的数据(通常需要对复杂模型进行此操作)。

现代的3D API使用三角形渲染。立方体的每个面都需要两个三角形:

A--B 
|\ |   This cube face has two triangles:
| \|   ABD and ADC.
C--D

要指定不带索引的面,必须指定vertices A, B, D, A, D, C。在顶点缓冲区中重复了两个顶点(AD)。

然而,随着指数的,你可以只包含所需顶点(顶点缓冲区ABC,和D)和6个指标:0, 1, 3, 0, 3, 2。由于索引通常比顶点小得多,并且在实际模型中通常会重复许多顶点,因此可以节省大量空间。

请注意,某些顶点将仅共享部分属性。例如,使用纹理贴图渲染多维数据集时,通常每个面都需要唯一的纹理坐标,因此您将拥有多个具有相同位置和不同纹理坐标的顶点。重复的数量是可以接受且必要的;当您复制整套顶点属性时,您将开始看到索引带来的好处。

如果确实所有网格顶点都是100%不同的,那么索引就没有好处(实际上,冗余索引缓冲区的消耗将占用更多空间)。但是,这并不总是发生。


1
应该改为0,1,3,0,1,2吗?
Sad CRUD开发人员

实际上是0、1、3、0、3、2,谢谢(基于A = 0,B = 1,C = 2,D = 3)。我更新了答案。

也许值得一提的,即在一个三角形网孔的邻近于顶点的三角形的平均数量是6
阿恩

7

使用索引有三个主要目的:

  • 通过启用从原始网格中删除重复的顶点来减少内存需求。
  • 通过使重复的顶点仅被转换一次来减少顶点着色器的计算。
  • 连接原语,从而使您减少绘制调用。

其中第一个很明显,因为您可以直接在自己的代码中对其进行测量:如果一个网格有50k个顶点,但如果其中有30k个顶点是重复的,则可以节省内存。

第二和第三个并不是那么明显-您必须已经决定使用索引,并且需要分析代码并隔离“之前”和“之后”性能以进行度量。

对于第二个,硬件能够缓存最近转换的顶点的结果。如果出现与最近转换的顶点相同的顶点,则可以使用缓存的版本,而不必再次执行所有计算。硬件使用索引来标识这些,因此索引对于获得此行为是绝对必要的。

对于第三个,无论需要执行多少GPU工作,您进行的每个绘制调用都会占用CPU开销。如果其他所有条件都相等,则在1个绘制调用中绘制50k网格比在10k绘制调用中绘制网格要快得多。但是,如果您的网格是由多个条带组成的,或者(甚至更糟)是由条带和扇形的组合组成的,则不能在没有(1)使用索引或(2)引入退化的三角形的情况下,在单个绘制调用中完成它。但是,由于索引比顶点小得多,因此在通常情况下首选使用索引。


0

索引说明由三个顶点组成的组一起形成了立方体的面。并非三角形的三个顶点的每个集合都是三角形的面。

您可以只使用一次每个顶点,并且只需重复使用多个三角形中的多个顶点即可,但这意味着额外的顶点转换。使用索引时,顶点仅变换一次,并根据需要使用多次。


当你指的是三角形?
Sad CRUD开发人员

现代图形硬件将所有内容渲染为三角形。

1
如果您真的想了解发生了什么,请获取一些方格纸,绘制3D顶点,并在INDICES指定的顶点之间绘制线。
ggambett
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.