OpenGL ES - glDrawElements - 麻烦理解指数

时间:2012-02-14 10:08:35

标签: iphone objective-c xcode opengl-es indices

我想知道是否有人可以帮助我理解指数如何与glDrawElements一起使用。在下面的例子中(摘自http://www.everita.com/lightwave-collada-and-opengles-on-the-iphone),作者提到你只能有一组索引,在这种情况下

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 个答案:

答案 0 :(得分:26)

索引数组中的每个值都指向位置,法线和纹理坐标的同一时间

它们只是以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,
…
};

所以这些信息会被发送到顶点着色器:

VertexPosition:0.176567,0.1743711,0.264963

VertexNormal:-0.425880,-0.327633,0.350967

VertexTextureCoordinates:0.867291,0.359728

...

如果你使用索引,opengl会线性发送这些顶点数据,所以在发送顶点数据0后,它会在数组的第1位发送数据,然后是2,3, 4等...

这很好但有时你的三角形最终会有一个或两个相同的顶点。考虑一下:

enter image description here

你可以看到2个三角形形成一个正方形,它们有两个共同的顶点,0和2.所以我们只有4个而2个traingles使用相同的数据,而不是6个顶点,每个三角形为3个。 2个顶点。这对性能有好处,特别是当您拥有包含数百个三角形的大型模型时。

为了绘制第一个三角形,我们需要顶点编号0,1和2,而对于第二个三角形,我们需要顶点编号0,2和3。

请注意,如果没有索引数组,opengl会尝试使用顶点0,1和2(第一个三角形可以)但是对于第二个三角形,opengl会查找顶点3,4和5.这是错误的。< / p>

这就是我们创建索引数组的原因,因此opengl可以为顶点着色器发送正确的顶点。在我们的例子中,我们的索引数组如下所示:

const GLushort tigerBottomIndices[] = {
0,1,2,
0,2,3,
}

答案 1 :(得分:1)

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

在您的示例中,第一个索引0,1,2对前三个顶点进行寻址,这三个顶点具有数组Vertex3D的前三个tigerBottomPositions项的位置,前三个元素的法线tigerBottomNormals(3个浮点数形成一个法线向量)和纹理坐标相同。

glDrawElements调用中的第一个参数告诉OpenGL如何从索引顶点形成基元。 GL_TRIANGLES表示每三个索引顶点形成一个三角形。

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