2011-09-09 112 views
0

我刚刚开始使用openGL我需要为动画加载位图的分配我可以让它工作很好几帧,但是当我尝试加载所有帧时,内存不足我怎么才能加载一次几帧?这是我使用加载纹理加载多个纹理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

好代码,它是装载在提供给您的应用程序的过程中(很有限的)存储许多位图的经典问题。我不会深究这一点,只要说Honeycomb之前这些位图是从Honeycomb中加载的,而且它们已经加载到堆上了,但问题仍然存在:128x256像素的位图需要4 * 128 *内存中有256个字节。而且,您的应用程序通常具有16至48兆的可用内存(取决于设备和Android版本)。

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

0

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

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

对于离线生成,有一些实用程序可以提供帮助; 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); 

最后一行分配尺寸(2048×2048)

然后为每个位图的空白图像,你可以使用:

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

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