2

我正在尝试加载我的纹理以便在我的游戏中使用它们。目前,我的游戏需要 84 个图像帧才能按预期工作,但是当我加载这么多图像时,它给了我 OutOfMemmory 异常。

有没有更好的方法来加载这些图像?

每个 Obs 在 HDPI 设备上都有 150x150px。

我正在运行的设备是 Galaxy SII 女巫,我相信它有 50mb 的堆内存。

这是发生异常的地方:

    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();
    }
}
4

3 回答 3

1

由于您需要同时在屏幕上显示所有这些,因此优化是完全不可能的。我建议您牢记“高效显示位图”教程,因为它提供了一些关于如何避免可怕java.lang.OutofMemoryError: bitmap size exceeds VM budget错误的提示。

还有一些其他的事情浮现在脑海中。首先,我建议不要先加载所有InputStreams 然后循环。为什么不在循环中加载流?也许写下要加载到文件中的图像名称并对其进行迭代。

此外,根据我的经验,BitmapFactory.decodeFileDescriptor()造成的麻烦更少。虽然我不确定它会解决问题,但在这一点上它不会受到伤害!

于 2013-06-27T13:58:59.800 回答
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 个加载的位图等等......

于 2013-07-01T12:02:18.657 回答
0

据我所知,有一种方法可以绑定纹理缓冲区,以便将其加载到 GPU RAM,这将减少您的堆使用量。我正在阅读有关此内容的信息,但不确定该怎么做。也许 glBindTexture() 正在做同样的事情,不知道。

如果您将所有纹理文件合并到一个文件中并在 onSurfaceCreated() 中仅加载一次,这也很好;

也看看这个问题: How to load textures in OpenGL ES Effectively

于 2013-07-04T12:00:46.523 回答