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

Load huge texture in parts in OpenGL ES 2.0

我想在 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 函数,但我不明白你在哪里初始化全尺寸纹理,或者预先提供全尺寸纹理的大小。

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

使用 glTexImage2D()data 参数的 null 值分配存储。使用 glTexSubImage2D().

上传补丁

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

根据 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 大小的位图组合而成。