2011-09-09 146 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使用限制非常輕鬆。