I would like to know if there is any kind of limitation on the texture size that can be used in any Android Opengl Es 2.0 projects. I understand that having a huge texture of size 4096x4096 is a bit meaning less as it is rendered on a small screen. But What if the requirement is to switch between many textures at run time? And If I want to have a texture atlas to do a quick single upload instead of multiple smaller texture upload. Please let me know your ideas in this regards.
Also I am sure there has to be a limitation on the size of image that can be processed by a device, as the memory on the device is limited. But I would like to know if it is resolution based or is it size based. I mean if a device has a limitation of 1024x1024 image size can it handle a compressed texture of size 2048x2048 that would be of same size approx as uncompressed 1024x1024.
Also please let me know on an general basis usually how much the limitation on texture size or resolution normal devices running android 2.2 and above would be.
Also please let me know if there are any best practices when handling high resolution images in opengles 2.0 to get best performance in both load time and also run time.
There is a hardware limitation on the texture sizes. To manually look them up, you can go to a site such as glbenchmark.com (Here displaying details about google galaxy nexus).
To automatically find the maximum size from your code, you can use something like:
int[] max = new int[1];
gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, max, 0); //put the maximum texture size in the array.
(For GL10, but the same method exists for GLES20)
When it comes to the processing or editing of an image you usually use an instance of Bitmap when working in android. This holds the uncompressed values of your image and is thus resolution dependant. However, it is recommended that you use compressed textures for your openGL applications as this improves the memory-use efficiency (note that you cannot modify these compressed textures).
From the previous link:
Texture compression can significantly increase the performance of your
OpenGL application by reducing memory requirements and making more
efficient use of memory bandwidth. The Android framework provides
support for the ETC1 compression format as a standard feature [...]
You should take a look at this document which contains many good practices and hints about texture loading and usage. The author explicitly writes:
Best practice: Use ETC for texture compression.
Best practice: Make sure your geometry and texture resolutions are
appropriate for the size they're displayed at. Don't use a 1k x 1k
texture for something that's at most 500 pixels wide on screen. The
same for geometry.
Related
I would like to know if there is any kind of limitation on the texture size that can be used in any Android Opengl Es 2.0 projects. I understand that having a huge texture of size 4096x4096 is a bit meaning less as it is rendered on a small screen. But What if the requirement is to switch between many textures at run time? And If I want to have a texture atlas to do a quick single upload instead of multiple smaller texture upload. Please let me know your ideas in this regards.
Also I am sure there has to be a limitation on the size of image that can be processed by a device, as the memory on the device is limited. But I would like to know if it is resolution based or is it size based. I mean if a device has a limitation of 1024x1024 image size can it handle a compressed texture of size 2048x2048 that would be of same size approx as uncompressed 1024x1024.
Also please let me know on an general basis usually how much the limitation on texture size or resolution normal devices running android 2.2 and above would be.
Also please let me know if there are any best practices when handling high resolution images in opengles 2.0 to get best performance in both load time and also run time.
There is a hardware limitation on the texture sizes. To manually look them up, you can go to a site such as glbenchmark.com (Here displaying details about google galaxy nexus).
To automatically find the maximum size from your code, you can use something like:
int[] max = new int[1];
gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, max, 0); //put the maximum texture size in the array.
(For GL10, but the same method exists for GLES20)
When it comes to the processing or editing of an image you usually use an instance of Bitmap when working in android. This holds the uncompressed values of your image and is thus resolution dependant. However, it is recommended that you use compressed textures for your openGL applications as this improves the memory-use efficiency (note that you cannot modify these compressed textures).
From the previous link:
Texture compression can significantly increase the performance of your
OpenGL application by reducing memory requirements and making more
efficient use of memory bandwidth. The Android framework provides
support for the ETC1 compression format as a standard feature [...]
You should take a look at this document which contains many good practices and hints about texture loading and usage. The author explicitly writes:
Best practice: Use ETC for texture compression.
Best practice: Make sure your geometry and texture resolutions are
appropriate for the size they're displayed at. Don't use a 1k x 1k
texture for something that's at most 500 pixels wide on screen. The
same for geometry.
My question may not be very correct, but let me describe it in details. I use cocos2d-x (renders using opengl-es 2) game engine to show images on Android device. In some cases when image dimensions are very large the images are not being displayed. They just get skipped. But I see that the size of the image is smaller then the size of my device VRAM. Checked with this method with /dev/graphics/fb0: How to measure VRAM consumption on Android?. So my file size is 532,042 bytes, its dimension are 2160x1224 and my vram size is 3072000 bytes. Why this image is not being handled by the device? And what is the criteria and limit? How can I check the limit for a device?
Why this image is not being handled by the device?
Because there's a difference between how much can be placed in RAM and the maximum size of a single chunk of data that can be processed. There's a certain limit to each GPU on the maximum size of an image it can handle. The size of the RAM just tells you, how many images will fit there. However OpenGL's memory model is purely abstract and the amount of VRAM doesn't tell you anything about how many textures you can load. Data can and will be swapped in and out of VRAM whenever required. The actual limit is in fact the amount of memory available to your system as a whole.
I can't tell you for Cocos2D but in OpenGL and OpenGL-ES you can query the maximum sizes supported for various texture types using glGetInteger OpenGL-ES glGetInteger reference. In your case you're probably interested in the value GL_MAX_TEXTURE_SIZE. Note that for texture targets other than GL_TEXTURE_1D and GL_TEXTURE_2D different values must be queried.
I'm working on this photo app that uses OpenGL 2.0 with a Renderer, an off-screen GLSurfaceView and some shader scripts (*.fsh and *.vsh).
after loading the shader scripts from Assets folder, preparing the GL surface and context, etc, etc we finally call GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4); and it works quite nicely and it generates the bitmaps with the effects.
The problem, OF COURSE, is the memory limitations and any large enough bitmap (regardless of device, not so big for old Gingerbread and very large images for the Nexus 10) and it will produce and OutOfMemoryException.
I'm not so knowledgeable in OpenGL and the way I know to deal with very large amounts of data is to use a stream so it's not necessary to hold it all in memory.
So the question is, is there a way to do apply an openGl shader/renderer through a Stream instead of a in-memory Bitmap ? If yes, any pointer to a link or base procedure?
Not exactly sure what you mean by Stream but here's another solution. Split rendering up into multiple passes. Fore instance, if you have a 512x512 texture and a corresponding quad to texture but can only afford to upload a 256x256 due to memory restrictions do the following:
split up the texture into 4 chunks
create a single, fitting texture object
for each chunk
upload the current chunk into the tex objects data store
draw 1/4 of the quad, e.g. top-left and texture accordingly
Note that the above example assume a 512x512 texture and screen-size. In any case, I think you get the idea.
Obviously, this is the usual memory/performance trade-off.You circumvent memory restrictions by using more bandwidth for transfers and do more rendering.
Note: I'm a desktop GL guy and I'm not quite sure how memory is split up betweem the GPU and the rest, or if there even is some dedicated VRAM. I assume you've got a limited amount available for GL resources which is even smaller than the overall system memory.
I am trying to write a libgdx livewallpaper (OpenGL ES 2.0) which will display a unique background image (non splittable into sprites).
I want to target tablets, so I need to somehow be able to display at least 1280x800 background image on top of which a lot more action will also happen, so I need it to render as fast as possible.
Now I have only basic knowledge both about libgdx and about opengl es, so I do not know what is the best way to approach this.
By googling I found some options:
split texture into smaller textures. It seems like GL_MAX_TEXTURE_SIZE on most devices is at least 1024x1024, but I do not want to hit max, so maybe I can use 512x512, but wouldn't that mean drawing a lot of tiles, rebinding many textures on every frame => low performance?
libgdx has GraphicsTileMaps which seems to be the tool to automate drawing tiles. But it also has support for many features (mapping info to tiles) that I do not need, maybe it would be better to use splitting by hand?
Again, the main point here is performance for me - because drawing background is expected to be the most basic thing, more animation will be on top of it!
And with tablet screen growing in size I expect soon I'll need to be able to comfortably render even bigger image sizes :)
Any advice is greatly appreciated! :)
Many tablets (and some celphones) support 2048 textures. Drawing it in one piece will be the fastest option. If you still need to be 100% sure, you can divide your background into 2 pieces whenever GL_MAX_TEXTURE happens to be smaller (640x400).
'Future' tables will surely support bigger textures, so don't worry so much about it.
For the actual drawing just create a libgdx mesh which uses VBOs whenever possible! ;)
Two things you dindn't mention will be very important to the performance. The texture filter (GL_NEAREST is the ugliest if you don't do a pixel perfect mapping, but the fastest), and the texture format (RGBA_8888 would be the best and slowest, you can downgrade it until it suits your needs - At least you can remove alpha, can't you?).
You can also research on compressed formats which will reduce the fillrate considerably!
I suggest you start coding something, and then tune the performance up. This particular problem you have is not that hard to optimize later.
I'm trying to develop an app that uses opengl on android, and ideally make it run on any phone as old as the original droid (or at least any phone that has OpenGL ES 2.0 support). Currently, I'm using a 2048x2048 ETC1 texture compression. It works fine on the Droid X I'm testing it on, but I currently don't have an original droid to test it on, and I can't find much data on this topic either. I know the G1 didn't do well with textures bigger than 512x512, and the droid seems to do fine with images as large as 1024x1024, but what about 2048x2048? (Again, etc1 compression, so it's about 2 MB large). Also, because ETC1 doesn't support alpha, I would like to load up another ETC1 texture to support an alpha channel. Is this a pipe dream?
Basically, I would like to know how much space I have to load texture data in android phones no older than the original droid, at least without the whole thing slowing down drastically.
You can query the MAX_TEXTURE_SIZE to get the maximum texture size, or you can look up your phone on http://glbenchmark.com (you can find the Droid info here). The G1 did not support GLES 2.0, AFAIK.
Loading up several textures should definitly work, especially when they are not more than 2 MB each. But you will of course be restricted by the size of the memory available.
Also, to have optimal performance you should mipmap your textures. Since you are using ETC, this must be done offline.
For a guide to how to use ETC1 with alpha, see here.