【问题标题】:OpenGL ES - glDrawElements - Trouble Understanding IndicesOpenGL ES - glDrawElements - 无法理解索引
【发布时间】:2012-03-05 17:04:46
【问题描述】:

我想知道是否有人可以帮助我了解索引如何与 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);

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 谢谢haffax,但我还是很困惑。那么在第一个索引 (0,1,2) 中,这只是描述了顶点信息,还是描述了法线和纹理坐标信息?
    • 所有三个顶点属性:Position、Normal、TexCoord。使用 glXxxPointer 函数,您可以为每个属性定义数组的开始。索引从此开始计数。
    【解决方案2】:

    索引数组中的每个值同时指向位置、法线和纹理坐标。

    它们仅以 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等...

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

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

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

    看,没有索引数组,opengl 会尝试使用顶点 0、1 和 2(第一个三角形可以),但对于第二个三角形,opengl 会寻找顶点 3、4 和 5。这是错误的。

    这就是我们创建索引数组的原因,因此 opengl 可以为顶点着色器发送正确的顶点。在我们的例子中,我们的索引数组看起来像这样:

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

    【讨论】:

    • 我见过的最好的解释之一。谢谢
    猜你喜欢
    • 2012-11-10
    • 2015-04-08
    • 2013-09-30
    • 2011-06-10
    • 2010-11-24
    • 2011-08-12
    • 1970-01-01
    • 2014-09-10
    • 2013-09-14
    相关资源
    最近更新 更多