加载多个纹理openGL

时间:2011-09-09 00:17:17

标签: java android opengl-es

我刚刚开始使用openGL我需要为动画加载大量的位图我可以让它在几帧中工作得很好但是当我尝试加载所有帧时耗尽内存我怎样才能加载几帧一次?这是我用来加载纹理的代码

public void loadGLTexture(GL10 gl, Context context) {


    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.r1);
    Bitmap bitmap01 = Bitmap.createScaledBitmap(bitmap, 512, 512, false);

    Bitmap bitmap2 = BitmapFactory.decodeResource(context.getResources(),R.drawable.r2);
    Bitmap bitmap02 = Bitmap.createScaledBitmap(bitmap2, 512, 512, false);

    Bitmap bitmap3 = BitmapFactory.decodeResource(context.getResources(),R.drawable.r3);
    Bitmap bitmap03 = Bitmap.createScaledBitmap(bitmap3, 512, 512, false);


    try {

    bitmap = bitmap01;
        bitmap2 = bitmap02;
        bitmap3 = bitmap03;
    } finally {
    }

    //Generate there texture pointer
    gl.glGenTextures(3, textures, 0);

    //Create  Texture and bind it to texture 0
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

    //Create  Texture and bind it to texture 1
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[1]);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap2, 0);

    //Create  Texture and bind it to texture 2
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[2]);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap3, 0);


    //Clean up
    bitmap.recycle();
    bitmap2.recycle();
    bitmap3.recycle();      
}   

}

2 个答案:

答案 0 :(得分:2)

嗯,这是在应用程序进程可用的(非常有限的)内存中加载到许多位图的经典问题。我不打算进入这个,足以说这些位于Honeycomb之前的这些位图是从Honeycomb开始加载的,而且它们已经装在堆上,但问题仍然存在:128x256像素的位图需要4 * 128 *内存中256字节。而且你的应用程序通常有16到48兆的可用内存(取决于设备和Android版本)。

这里的好消息是,一旦你加载一个位图并用它创建一个opengl纹理,你不再需要那个Bitmap对象,你可以回收它并使其为null。因此,您可以尝试加载(并且,从我的代码中看到,缩放)第一个位图,然后创建第一个纹理对象,然后回收并取消引用第一个位图。然后继续对第二个纹理对象的第二个位图执行相同的操作。

答案 1 :(得分:0)

首先,您可以在缩放图像后立即回收位图。其次,你应该预先缩小它们,也就是说,将它们存储为512x512。

但最重要的是,你应该为此创建一个纹理图集。基本上,您可以使用单个大型纹理而不是使用多个纹理,并将所有片段存储在那里。这个想法是创建一个2048x2048纹理,它可以存储16个“cels”的512x512像素(每行4个4个cels),然后在屏幕上绘制四边形时,改变纹理坐标以显示特定的cel

对于离线生成,有许多实用程序可以提供帮助; TexturePacker是一个,还有很多其他的。要在代码中执行此操作,您可以生成一次纹理:

gl.glGenTextures(1, textures, 0);

//Create  Texture and bind it to texture 0
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, 2048, 2048, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, null);

最后一行分配一个大小为空的图像(2048x2048)

然后,对于每个位图,您可以使用:

int xoffset = (imageIndex % 4) * 512;
int yoffset = (imageIndex / 4) * 512;
GLUtils.texSubImage2D(GL10.GL_TEXTURE_2D, 0, xoffset, yoffset, bitmap);

这会将您的位图加载到纹理的一部分中。正如@Joseph暗示的那样,GL纹理上RAM使用的限制非常宽松。