I have a very basic knowledge of using OpenGL, especially on Android. I'm developing an app that uses OpenGL in order to switch between full screen images in a fast way (since it's too slow using the normal Android framework).
What I've found is that in order to load textures, I need to do something like:
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuffer.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
_gl = gl;
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), _imageResourceId);
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
Now, since the images are meant to be full screen (and they are quite large - 1024x1024), this takes some time, especially since I need to load 5 of them at the same time.
So I need to ask some questions regarding tips of improving the code, especially about efficient loading (but also using less memory if possible):
if I decode the bitmap to not have transparency pixels, by using the RGB_565 format, will it boost the speed of loading the images to OpenGL (or the decoding phase)?
does the input bitmap have to have a width and height that are powers of 2 or can I let OpenGL take only the part that it wants, which will have this rule? I mean, maybe I can make the
texImage2D
command to take only a part of the bitmap?maybe I can even decode only this part from the beginning (so if I have a huge image of 10000x10000, I can decode only a 1024x1024 part of it and give it to OpenGL)?
is it possible to load and show just the first image, and in the background load the rest? I've heard that you can't send the bitmaps to OpenGL in a thread that is not the one that handles it. Does it make sense to load them on the
onDrawFrame
method of theGlRenderer
, say, the second time it get called?I remember I've heard of a tip about merging multiple images into a single image (one after another, from left to right), so that it might have some speed boost for the decoding phase. Not sure what is the name of this technique. Is it still possible for OpenGL ES on Android?
is it possible to avoid creating a Bitmap instance and let the decoding done in a more native way (NDK , perhaps)? According to my tests, decoding a PNG file of size 1024x1024 on an emulator takes about 400ms-700ms, yet sending it to OpenGL takes about 50ms-70ms.
using Procrank, I've found out that OpenGL can take a lot of memory. Is it possible to make it use less memory? Maybe use better textures types?
since Android can work on many kinds of devices, is it possible to put in the manifest a requirement of how much memory is needed for the app to run, so that people with too little memory won't be able to install it?
@Majid Max :
so it's enough to decode this way and send it to OpenGL, or should I also set something special when sending to openGL?
there is no such a command to take a partial part of the bitmap?
I meant, can I decode only a partial part of the file to be stored in a bitmap, instead of all of the bitmap?
so the only thing I can do I to load everything in the beginning, and then use it all? How could it be? How do games handle it? I mean, they do show one stage after another, even with something that looks like an OpenGL generated progress bar. This is very problematic.
what I'm describing is available on the web too. For example, instead of loading multiple tiny images, the webpage contain a single image and maps what part of it should be shown where. Another name for it is sprites. Example here .
I see. I guess I should also call glDeleteTextures when I see there aren't used anymore, right?
how do I do that? What should I change in the code?
what happens when I use a lot of memory? Is there such a thing as virtual RAM (uses internal storage perhaps) when there is no free RAM? I've heard about it on Google IO video, but it seems like they weren't sure about the answer as well. Link here. They only said to expect more crashes when such a thing occurs.
@Majid Max :
1+2+3. ?
this might work. You mean that I make a new thread that will load the bitmaps, and then send the results back to the OpenGL thread which will bind the textures to the bitmap? Maybe I could use a similar approach to asyncTask, and use publishprogress.
that's also a good thing. Do you have any link I should read about it? Or maybe a snippet to change in my code?
thanks.
so i think it's the easiest thing to use ETC1. However it doesn't support transparency at all, so according to this link, I need to use another texture just for that, but I can't find a sample for this.
what can I assume about the available memory that I can use? Can I assume, for example, that all Android devices can offer me 200MB of video memory that I can use for OpenGL?