如何在OpenGL ES 2.0中管理多个纹理?

时间:2016-03-16 12:44:47

标签: android opengl-es textures

我有一个带有6种不同纹理的OpenGL ES 2.0应用程序。我需要的是同时绘制和移动它们。我能够做到这一点,但运动是滞后的,因为我一直在将位图加载到纹理中。对于每个纹理,我在Render方法上执行以下操作:

    setupImage(texture1);
    GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBufferT1);
    GLES20.glVertexAttribPointer(mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 0, uvBufferT1);
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, indicesT1.length, GLES20.GL_UNSIGNED_SHORT, drawListBufferT1);

在setupImage方法中,我这样做:

    // Create the bitmap
    int id = mContext.getResources().getIdentifier("drawable/texture1", null, mContext.getPackageName());
    Bitmap bmp = BitmapFactory.decodeResource(mContext.getResources(), id);

    // Bind texture to texturename
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);

    // Set filtering
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

    // Set wrapping mode
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

    // Load the bitmap into the bound texture.
    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);

    // Free bitmap
    bmp.recycle();

这显然是错误的。但是,我不知道如何将每个位图加载到不同的纹理中,然后如何在Render方法上切换活动纹理。

那么,我怎样才能实现这一点,以显示和移动所有六种纹理并具有流畅的运动?

1 个答案:

答案 0 :(得分:6)

你是对的,你所做的是非常浪费。维护纹理的一种简单方法是以更智能的方式简单地使用textures[]数组。

有没有想过为什么那个变量是一个大小为1的数组?好吧,你可以使用它来保存超过1个纹理!只需将其定义为更大的数组(大小为6)。完成此操作后,您将能够在应用程序启动时将多个位图加载到纹理中,然后在您即将绘制它时绑定正确的纹理。

以下是一个例子:

private int[] textures = new int[6];

private void loadTexture(Bitmap bitmap, int textureIndex) {
    GLES20.glGenTextures ( 1, textures, textureIndex );

    GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, textures[textureIndex] );

    //.. call glTexParameter as needed

    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
}

当应用启动时,上面的代码应该被调用一次,以便为要加载为纹理的每个位图。如果您有很多位图,您可能需要考虑某种即时纹理加载和卸载 - 但是根据您的需要,它应该足以一次加载它们。

稍后,当您要绘制某个纹理时,请确保首先绑定正确的纹理:

GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[textureIndex]);

这将简单地告诉OpenGL图层它将用于即将到来的绘制调用的预加载纹理。请务必在每次绘制前调用此方法,以确保每次都绘制正确的纹理。请注意,此时,OpenGL不会重新创建整个纹理,而是只使用已经加载的纹理,使其非常高效。