Java 加载多纹理openGL

Java 加载多纹理openGL,java,android,opengl-es,Java,Android,Opengl Es,我刚开始使用openGL,我需要加载动画位图的分配,我可以让它在几帧内工作得很好,但是当我尝试加载所有帧时内存不足,如何一次只加载几帧?这是我用来加载纹理的代码 public void loadGLTexture(GL10 gl, Context context) { Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.r1); Bitmap bitmap01 = Bit

我刚开始使用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();      
}   

}

好吧,这是在应用程序进程可用的(非常有限的)内存中加载许多位图的经典问题。我不打算讨论这个问题,只需说pre-Honeycom这些位图是从堆外加载的,从Honeycom和beyond加载到堆上,但问题仍然存在:128x256像素的位图将占用内存中的4*128*256字节。你的应用程序通常有16到48兆的可用内存(取决于设备和Android版本)


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

首先,您可以在缩放图像后立即回收位图。其次,您应该预先设置它们的比例,也就是说,从一开始就将它们存储为512x512

但最重要的是,您应该为此创建纹理图集。本质上,您可以使用单个大纹理并将所有片段存储在那里,而不是使用多个纹理。设想是创建一个2048x2048纹理,它可以存储16个512x512像素的“cel”(4行,每行4个cel),然后在屏幕上绘制四边形时,改变纹理坐标以显示特定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使用限制非常宽松