2013-05-31 5 views
2

Я пытаюсь загрузить свои текстуры, чтобы использовать их в своей игре. на данный момент для моей игры требуется 84 кадра изображения, чтобы работать так, как я ожидаю, но когда я загружаю это много изображений, это дает мне OutOfMemmory Exception.OutOfMemory Exception android OpenGLes LoadTextures

Есть ли лучший способ загрузить эти изображения?

Обнаружили, что каждый из них имеет 150x150px на устройствах HDPI.

устройство, в котором я работаю, является галактикой SII, ведь я считаю, что память кучи 50 МБ.

Вот где происходит исключение:

public void loadTextures(GL10 gl) { 
    InputStream is[] = new InputStream[textureCount]; 
    Bitmap bitmap[] = new Bitmap[textureCount]; 

    is[0] = context.getResources().openRawResource(R.drawable.bg_01); 
    is[1] = context.getResources().openRawResource(R.drawable.bg_02); 
    is[2] = context.getResources().openRawResource(R.drawable.bg_03); 

    is[3] = context.getResources().openRawResource(R.drawable.win_hud); 
    is[4] = context.getResources().openRawResource(R.drawable.heart); 

    is[5] = context.getResources().openRawResource(R.drawable.skyblue); 
    is[6] = context.getResources().openRawResource(R.drawable.heart); 
    is[7] = context.getResources().openRawResource(R.drawable.heart); 
    is[8] = context.getResources().openRawResource(R.drawable.heart); 
    is[9] = context.getResources().openRawResource(R.drawable.heart); 
    is[10] = context.getResources().openRawResource(R.drawable.heart); 

      //reserving numbers for more textures from 6 to 10. 


    is[11] = context.getResources().openRawResource(R.drawable.walking01); 
    is[12] = context.getResources().openRawResource(R.drawable.walking02); 
    is[13] = context.getResources().openRawResource(R.drawable.walking03); 
    is[14] = context.getResources().openRawResource(R.drawable.walking04); 
    is[15] = context.getResources().openRawResource(R.drawable.walking05); 

    is[16] = context.getResources().openRawResource(R.drawable.flying01); 
    is[17] = context.getResources().openRawResource(R.drawable.flying02); 

    is[18] = context.getResources().openRawResource(R.drawable.falling_01); 
    is[19] = context.getResources().openRawResource(R.drawable.falling_02); 
    is[20] = context.getResources().openRawResource(R.drawable.fallen); 

    is[21] = context.getResources().openRawResource(
      R.drawable.standingup_01); 
    is[22] = context.getResources().openRawResource(
      R.drawable.standingup_02); 

    is[23] = context.getResources().openRawResource(R.drawable.death_01); 
    is[24] = context.getResources().openRawResource(R.drawable.death_02); 
    is[25] = context.getResources().openRawResource(R.drawable.death_03); 
    is[26] = context.getResources().openRawResource(R.drawable.death_04); 
    is[27] = context.getResources().openRawResource(R.drawable.death_05); 
    is[28] = context.getResources().openRawResource(R.drawable.death_06); 


    is[29] = context.getResources().openRawResource(R.drawable.p_walk_1); 
    is[30] = context.getResources().openRawResource(R.drawable.p_walk_2); 
    is[31] = context.getResources().openRawResource(R.drawable.p_walk_3); 
    is[32] = context.getResources().openRawResource(R.drawable.p_walk_4); 
    is[33] = context.getResources().openRawResource(R.drawable.p_walk_5); 
    is[34] = context.getResources().openRawResource(R.drawable.p_walk_6); 

    is[35] = context.getResources().openRawResource(R.drawable.p_holding01); 
    is[36] = context.getResources().openRawResource(R.drawable.p_holding03); 

    is[37] = context.getResources().openRawResource(R.drawable.p_opening01); 
    is[38] = context.getResources().openRawResource(R.drawable.p_opening02); 


    is[39] = context.getResources().openRawResource(R.drawable.p_parachute01); 
    is[40] = context.getResources().openRawResource(R.drawable.p_parachute02); 
    is[41] = context.getResources().openRawResource(R.drawable.p_parachute03); 
    is[42] = context.getResources().openRawResource(R.drawable.p_parachute04); 
    is[43] = context.getResources().openRawResource(R.drawable.p_parachute05); 

    is[44] = context.getResources().openRawResource(R.drawable.p_closing01); 
    is[45] = context.getResources().openRawResource(R.drawable.p_closing02); 

    is[46] = context.getResources().openRawResource(R.drawable.p_cracking01); 
    is[47] = context.getResources().openRawResource(R.drawable.p_cracking02); 

    is[48] = context.getResources().openRawResource(R.drawable.p_fallen01); 

    is[49] = context.getResources().openRawResource(R.drawable.p_standing01); 
    is[50] = context.getResources().openRawResource(R.drawable.p_standing02); 
    is[51] = context.getResources().openRawResource(R.drawable.p_standing3); 

    is[52] = context.getResources().openRawResource(R.drawable.p_dead01); 
    is[53] = context.getResources().openRawResource(R.drawable.p_dead02); 
    is[54] = context.getResources().openRawResource(R.drawable.p_dead03); 
    is[55] = context.getResources().openRawResource(R.drawable.p_dead04); 
    is[56] = context.getResources().openRawResource(R.drawable.p_dead05); 
    is[57] = context.getResources().openRawResource(R.drawable.p_dead06); 
    is[58] = context.getResources().openRawResource(R.drawable.p_dead07); 
    is[59] = context.getResources().openRawResource(R.drawable.p_dead08); 
    is[60] = context.getResources().openRawResource(R.drawable.p_dead09); 

    is[61] = context.getResources().openRawResource(R.drawable.r_walking01); 
    is[62] = context.getResources().openRawResource(R.drawable.r_walking02); 
    is[63] = context.getResources().openRawResource(R.drawable.r_walking03); 
    is[64] = context.getResources().openRawResource(R.drawable.r_walking04); 
    is[65] = context.getResources().openRawResource(R.drawable.r_walking05); 
    is[66] = context.getResources().openRawResource(R.drawable.r_walking06); 
    is[67] = context.getResources().openRawResource(R.drawable.r_walking07); 
    is[68] = context.getResources().openRawResource(R.drawable.r_walking08); 
    is[69] = context.getResources().openRawResource(R.drawable.r_falling01); 
    is[70] = context.getResources().openRawResource(R.drawable.r_falling02); 

    is[71] = context.getResources().openRawResource(R.drawable.r_fallen); 

    is[72] = context.getResources().openRawResource(R.drawable.r_standingup01); 
    is[73] = context.getResources().openRawResource(R.drawable.r_standingup02); 

    is[74] = context.getResources().openRawResource(R.drawable.r_dyeing01); 
    is[75] = context.getResources().openRawResource(R.drawable.r_dyeing02); 
    is[76] = context.getResources().openRawResource(R.drawable.r_dyeing03); 
    is[77] = context.getResources().openRawResource(R.drawable.r_dyeing04); 
    is[78] = context.getResources().openRawResource(R.drawable.r_dyeing05); 
    is[79] = context.getResources().openRawResource(R.drawable.r_dyeing06); 
    is[80] = context.getResources().openRawResource(R.drawable.r_dyeing07); 
    is[81] = context.getResources().openRawResource(R.drawable.r_dyeing08); 
    is[82] = context.getResources().openRawResource(R.drawable.r_dyeing09); 
    is[83] = context.getResources().openRawResource(R.drawable.r_dyeing10); 




    for (int loop = 0; loop < textureCount; loop++) { 

     bitmap[loop] = BitmapFactory.decodeStream(is[loop]); 
     try { 
      is[loop].close(); 
      is[loop] = null; 
     } catch (IOException e) { 
     } 
    } 
    gl.glGenTextures(textureCount, textures, 0); 
    for (int loop = 0; loop < textureCount; loop++) { 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[loop]); 
     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.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, // OpenGL docs. 
       GL10.GL_NICEST); 
     gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, 
       GL10.GL_CLAMP_TO_EDGE); 
     gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, 
       GL10.GL_CLAMP_TO_EDGE); 

     GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[loop], 0); 
     bitmap[loop].recycle(); 
    } 
} 
+0

Требуется ли использование всех 84 изображений в то же время, имея в виду, все 84 на экране одновременно? Тип разрешения дает это, но просто спрашивает, чтобы мы были на одной странице! – Eric

+0

Да, игра похожа на растения против зомби, и в зависимости от вашего уровня на экране могут появляться все виды зомби. – Moondustt

+0

Я вижу. К сожалению, в плане оптимизации не так много. Я напишу ответ с некоторыми рекомендациями, которые вы можете прочитать. Они должны помочь! – Eric

ответ

1

Как вам требуется все те, на экране одновременно, оптимизация совершенно невозможно. Я бы рекомендовал вам принять урок Displaying Bitmaps Efficiently, так как он предлагает несколько советов о том, как избежать страшной ошибки java.lang.OutofMemoryError: bitmap size exceeds VM budget.

Есть еще несколько вещей, которые приходят на ум. Во-первых, я бы рекомендовал не загружать все InputStream s до и после этого. Почему бы не загрузить поток в цикле? Возможно, пишите имена изображений для загрузки в файл и итерации по ним.

Также, по моему опыту, BitmapFactory.decodeFileDescriptor() вызывает меньше проблем. Хотя я не уверен, что это решит проблему, это не может повредить на этом этапе!

+0

Я изменю цикл, и я увижу, что произойдет. – Moondustt

+0

Пожалуйста, дайте мне знать, как это происходит! – Eric

+0

Я попытался для (INT петли = 0; цикл Moondustt

1

Изменить код вы к чему-то вроде этого:

public void loadTextures(GL10 gl) { 
    int[] ids = new int[texturesCount]; 
    ids[0] = R.drawable.bg_01; 
    // rest of id's 

    gl.glGenTextures(textureCount, textures, 0); 

    for (int loop = 0; loop < textureCount; loop++) { 
     Bitmap bm = BitmapFactory.decodeResource(context.getResources(), ids[loop]); 
     if (null == bm) { 
      // handle error 
     } 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[loop]); 
     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.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, // OpenGL docs. 
       GL10.GL_NICEST); 
     gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, 
       GL10.GL_CLAMP_TO_EDGE); 
     gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, 
       GL10.GL_CLAMP_TO_EDGE); 

     GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bm, 0); 
     bm.recycle(); 
    } 
} 

Таким образом, вы не будете иметь одновременное 84 открыты потоки, 84 загруженных растровых изображений и так далее ...

+0

Я пробовал это, но он использует еще больше памяти кучи, 42 мб. – Moondustt

+0

Это сработало, или у вас все еще есть OOM? Как вы измеряли потребление памяти? Я понятия не имею, как вы могли выделить 42 МБ, поскольку все ваши текстуры составляют около 8 МБ (84 * 150 * 150 * 4) – arcone1

+0

Я думаю, bm.recycle(); освободит память некоторое время в будущем, а не мгновенно, я думаю, что даже запуск ручной коллекции gc не поможет, но это не так важно, система освободит память, когда она понадобится при таком подходе, поэтому я бы сказал, что это лучше, чем оригинальный! Его также важно преобразовать в совместимый с opengl формат, тогда он будет использовать только половину пространства в родном RAM –

0

Насколько я знаю, там это способ привязки текстурного буфера, чтобы он был загружен в ОЗУ GPU, что уменьшит использование кучи. Я читал об этом, но не знаю, как это сделать. Возможно, glBindTexture() делает то же самое, не знаю.

Также хорошо, если вы присоедините все ваши файлы текстур в одном файле и загрузите его только один раз в onSurfaceCreated();

Взгляните на этот вопрос тоже: How to load textures in OpenGL ES efficiently