GLES20为什么纹理数据没有与顶点索引链接?

时间:2016-07-20 19:56:09

标签: android opengl-es 3d texture-mapping gles20

我试图渲染一个立方体并在所有面上应用单个纹理。 通过传递面部顶点的索引,以及使用尽可能小的顶点。例如:

顶点:

static final float FACE_VERTEX[] = {
        // front
        0.0f,  1.0f, 1.0f,     //0
        0.0f, 0.0f, 1.0f,     //1
        1.0f, 0.0f, 1.0f,      //2
        1.0f,  1.0f, 1.0f,      //3

        //back
        1.0f,  1.0f, 0.0f,      //4 - 3
        1.0f, 0.0f, 0.0f,      //5 - 2
        0.0f, 0.0f, 0.0f,     //6 - 1
        0.0f,  1.0f, 0.0f,     //7 - 0
}; 

索引:

static final int FACE_INDEX[] = {
        //front
        0,1,2, 0,2,3,
        //back
        4,5,6, 4,6,7,

        //left
        7,6,1, 7,1,0,

        //right
        3,2,5, 3,5,4,

        //top
        4,7,0, 4,0,3,

        //bottom
        1,6,5, 1,5,2

};

纹理映射数据:

final int textureCoordinateData[] =
        {
                // Front face
                0,0, 0,1, 1,1, 1,0,
                //back
                0,0, 0,1, 1,1, 1,0,
                //left
                0,0, 0,1, 1,1, 1,0,
                //right
                0,0, 0,1, 1,1, 1,0,
                //top
                0,0, 0,1, 1,1, 1,0,
                //bottom
                0,0, 0,1, 1,1, 1,0,
                //top
                0,0, 0,1, 1,1, 1,0,
                //bottom
                0,0, 0,1, 1,1, 1,0,


        };

纹理在立方体的所有面上渲染,顶部和底部除外。只有正面像素的第一行沿整个顶面和底面渲染(见截图):

enter image description here

我正在使用VBO将顶点/索引/纹理数据存储在GPU中,并使用

进行渲染
glDrawElements(GL_TRIANGLES, indexLength, GL_UNSIGNED_INT, 0);

然而,这个问题是因为纹理数据应该映射到传递的顶点数据(这对于立方体模型来说有点烦人)并且不是由索引计算的。

我的问题是: - 有没有办法保持顶点数据尽可能低并将纹理映射到索引数据? - 如果我创建36个顶点(有些是重复的)来解决纹理映射问题,但我创建了正确的索引来渲染立方体,它还会比使用glDrawArrays更快吗?或者我是否应该使用glDrawArrays并删除索引数据?

相关问题(没有回答我的问题):

OpenGL ES - texture map all faces of an 8 vertex cube?

如果您阅读了答案的第一条评论:

  

你是什么意思你必须使用24个顶点?如果你必须复制   顶点是什么是使用索引缓冲区,如果你   仍在向GPU发送重复数据?

1 个答案:

答案 0 :(得分:1)

实际上没有合理的方法来绘制纹理坐标少于24个顶点的立方体。那是因为......当使用OpenGL中形成顶点的定义时,它有24个顶点,这是顶点属性(位置,纹理坐标,法线等)的唯一组合。

您可以仅使用位置和纹理坐标略微减少数量,因为您的情况下的纹理坐标只是0和1值的组合。如果你不关心每个面上纹理的方向,你可以例如有1个顶点,它使用(0,0)表示所有3个相邻面的纹理坐标。当然,你不能为所有顶点做到这一点,但你可以稍微减少顶点的数量。

那么使用指数值得吗?正如您现在已经发现的那样,使用索引时可以轻松地使用24个顶点,但需要使用glDrawArrays()最直接使用的36个顶点,其中使用GL_TRIANGLES作为基元的单个绘制调用类型。所以它确实减少了顶点的数量。

如果为每个面单独进行绘制调用,也可以使用glDrawArrays()将其缩小为24个顶点,并使用GL_TRIANGLE_STRIP基本类型绘制面,每个顶点有4个顶点。这将导致6次绘制调用,并且也不需要进行许多小型绘制调用。

即使在多维数据集的情况下它看起来有问题,索引缓冲区通常也非常有用。一个立方体就是这么小而简单的形状,你发送顶点的方式无论如何都不会产生太大的影响。

在大多数用例中,您将拥有更复杂的形状,还有更多顶点通常定义光滑表面。在这种情况下,相同的顶点(具有相同的法线和纹理坐标)主要由多个三角形共享。绘制常规网格的一部分:

_____________
|  /|  /|  /|
| / | / | / |
|/__|/__|/__|
|  /|  /|  /|
| / | / | / |
|/__|/__|/__|

你可以看到内部顶点每个共享6个三角形。因此,对于相对较大的光滑表面,通常可以通过共享顶点将顶点数量减少大约6倍,这是使用索引数组允许的操作。如果您的几何图形足够大,那么将内存使用量减少几乎6倍就可以获得实质性的收益。