在 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 大小的位图组合而成。
我想在 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 大小的位图组合而成。