OpenGL ES - glDrawElements - 难以理解索引

6
我想知道有没有人能帮我理解indices在glDrawElements中是如何工作的。在下面这个例子中(摘自http://www.everita.com/lightwave-collada-and-opengles-on-the-iphone),作者提到你只能有一个indices集,就像这个例子一样。
const GLushort tigerBottomIndices[] = {
0,1,2,
3,0,4,
1,5,6,
…

};

我的问题是这些索引描述的是什么?我是否正确地认为前三个是顶点位置,接下来的三个是相应的法线,最后三个是纹理坐标?

提前感谢!

#import "OpenGLCommon.h"

const Vertex3D tigerBottomPositions[] = {
{0.176567, 0.143711, 0.264963},
{0.176567, 0.137939, 0.177312},
{0.198811, 0.135518, 0.179324},
…
};
const Vertex3D tigerBottomNormals[] = {
{-0.425880, -0.327633, 0.350967},
{-0.480159, -0.592888, 0.042138},
{-0.113803, -0.991356, 0.065283},
…
};
const GLfloat tigerBottomTextureCoords[] = {
0.867291, 0.359728,
0.779855, 0.359494,
0.781798, 0.337223,
…
};
const GLushort tigerBottomIndices[] = {
0,1,2,
3,0,4,
1,5,6,
…
};

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);    

glBindTexture(GL_TEXTURE_2D, tigerTextures[5]);
glVertexPointer(3, GL_FLOAT, 0, tigerBottomPositions);
glNormalPointer(GL_FLOAT, 0, tigerBottomNormals);
glTexCoordPointer(2, GL_FLOAT, 0, tigerBottomTextureCoords);
glDrawElements(GL_TRIANGLES, 210, GL_UNSIGNED_SHORT, tigerBottomIndices);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableEnableClientState(GL_TEXTURE_COORD_ARRAY);
2个回答

27
每个索引数组中的值都指向一个位置、一个法线和一个纹理坐标的同一时间
它们只是以3个为一组进行组织,因为它们只是描述三角形的顶点,所以3个顶点=1个三角形,当然。
const GLushort tigerBottomIndices[] = {
0,1,2, // #1 Triangle
3,0,4, // #2 Triangle
1,5,6, // #3 Triangle

让我们选择这些索引中的第一个值,它是0

这意味着:

选择顶点位置编号0

同时,选择顶点法线编号0

并且选择纹理坐标编号0

const Vertex3D tigerBottomPositions[] = {
{0.176567, 0.143711, 0.264963}, // This is the position number 0
{0.176567, 0.137939, 0.177312},
{0.198811, 0.135518, 0.179324},
…
};
const Vertex3D tigerBottomNormals[] = {
{-0.425880, -0.327633, 0.350967}, // This is the normal number 0
{-0.480159, -0.592888, 0.042138},
{-0.113803, -0.991356, 0.065283},
…
};
const GLfloat tigerBottomTextureCoords[] = {
0.867291, 0.359728, // These are the tex-coords number 0
0.779855, 0.359494,
0.781798, 0.337223,
…
};

因此,这些信息将被发送到顶点着色器:

顶点位置:0.176567、0.143711、0.264963

顶点法线:-0.425880、-0.327633、0.350967

顶点纹理坐标:0.867291、0.359728

...

如果您不使用索引,OpenGL会按线性方式发送那些顶点数据,因此在发送顶点数据编号0之后,它会发送数组位置1处的数据,然后是2、3、4等等...
这很好,但有时您的三角形最终会有一个或两个相同的顶点。考虑一下这个问题:

enter image description here

您可以看到两个三角形组成了一个正方形,它们共享两个顶点0和2。因此,我们只需要4个顶点,而不是每个三角形需要3个顶点,因此总共需要6个顶点。这对性能有好处,特别是当您有数百个三角形的大型模型时。
为了绘制第一个三角形,我们需要顶点号码0、1和2,而对于第二个三角形,我们需要顶点号码0、2和3。
如果没有索引数组,OpenGL会尝试使用顶点0、1和2(对于第一个三角形没问题),但是对于第二个三角形,OpenGL会寻找顶点3、4和5。这是错误的。
这就是为什么我们创建索引数组的原因,以便OpenGL可以将正确的顶点发送到顶点着色器。在我们的情况下,索引数组如下:
const GLushort tigerBottomIndices[] = {
0,1,2,
0,2,3,
}

我所见过的最好的解释之一。谢谢。 - ControlAltDelete

1

索引是指数组元素的索引。索引0表示数组中的第一个元素,索引1表示第二个元素,依此类推。

在您的示例中,前三个顶点的索引0、1、2分别对应于数组中前三个项目的位置、中前三个元素(每个元素由三个浮点数组成)的法线以及纹理坐标相同。

glDrawElements调用中的第一个参数告诉OpenGL如何从已索引的顶点中形成原始图元。GL_TRIANGLES意味着每三个索引顶点形成一个三角形。

因此,具有索引0、1、2的顶点形成一个三角形;3,0,4形成下一个三角形;1,5,6形成另一个三角形,以此类推。


谢谢haffax,但我仍然感到困惑。所以在第一个索引(0,1,2)中,这只描述了顶点信息,还是法线和纹理坐标信息? - GuybrushThreepwood
所有三个顶点属性:位置、法线、纹理坐标。使用glXxxPointer函数,您可以定义每个属性数组的起始位置。索引从此开始计数。 - haffax

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接