在OpenGL ES 2.0中加载部分巨大的纹理

时间:2017-12-11 14:07:58

标签: android opengl-es textures opengl-es-2.0 android-bitmap

我希望将巨大的位图作为纹理加载到Android上的图形卡内存中,在OpenGL ES 2.0中,用作纹理图集,最大的尺寸。我的设备的最大纹理大小为8192x8192。

我知道我可以通过以下方式将位图加载为纹理:

// create bitmap
Bitmap bitmap = Bitmap.createBitmap(8192, 8192, Bitmap.Config.ARGB_8888);
{ // draw something
    Canvas c = new Canvas(bitmap);
    Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
    p.setColor(0xFFFF0000);
    c.drawCircle(4096, 4096, 4096, p);
}
// load as a texture
GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);

然而,(毫不奇怪)我在尝试创建这样大小的位图时得到java.lang.OutOfMemoryError

是否可以加载部分?由于它是一个纹理图集,它可以从较小的位图组装而成。我查看了texSubImage2D函数,但我不知道在哪里初始化全尺寸纹理,或者事先提供完整纹理的大小。

2 个答案:

答案 0 :(得分:1)

在GL方面,您需要分配完整存储空间,然后对其进行修补。

使用glTexImage2D()null参数设置data值来分配存储空间。使用glTexSubImage2D()上传补丁。

请注意,这仍然需要256MB内存,因此在许多预算设备上,您仍会获得OOM ...

答案 1 :(得分:0)

根据solidpixel的回答,这是一个完成工作的代码:

GLES20.glTexImage2D ( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 8192, 8192, 0,
        GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);

Bitmap bitmap = Bitmap.createBitmap(1024, 1024, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
for (int i = 0; i < 8; ++i) {
    for (int j = 0; j < 8; ++j) {
        // clear the bitmap
        c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        { // draw something
            p.setARGB(255, 32 * i, 32 * j, 255 - 32 * j);
            c.drawCircle(512, 512, 512, p);
        }
        // load as part of a texture
        GLUtils.texSubImage2D(GL_TEXTURE_2D, 0, i * 1024, j * 1024, bitmap);
    }
}

此处纹理由64个1024x1024大小的位图组合而成。