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.
Related
I'm working through the openGL ES 2.0 guide, and I just stumbled on this note for the GenerateMipmap(target) command:
If the level zero array is stored in a compressed internal format, the error INVALID_OPERATION is generated.
The way I understand that is that there is no function to automatically generate mipmaps for compressed textures in openGL ES 2.0 - and everything else I've looked at seems to indicate that, even though I've never seen it concretely confirmed anywhere. I've seen that the Mali texture compression tool can automatically generate mipmaps - but that only works on Windows, Linux and OS X - and not on Android. I need my app to compress the textures and mipmap them (the idea is that a user can take an image and apply it as a texture - I've already taken care of the aspect that the texture has to have a widths and heights of 2^n and 2^m respectively). The ETC1Util takes care of compressing textures (although it only takes care of the ETC1 format, and I'm still looking for a solution for textures with an alpha channel - but that's a different question for a different day, if Google doesn't help me there).
My question is: how do you compress and mipmap textures - most importantly ETC1, but ideally also PVRTC, ATITC, S3TC and ETC2 - at runtime on Android?
There's nothing in OpenGL or OpenGLES for generating compressed textures.
Generally, creating compressed textures is slow, and people almost always generate them offline. For runtime generated textures, people usually keep them in basic formats like 8888, 565 or 4444 because the trade-off of compression-time vs rendering efficiency is just not worth it.
That said, it's possible to find open source code for generating most compressed formats, and there's nothing stopping you from plugging that code into your game code. For ETC1 there's this (github version). For S3TC (aka DXT) there's squish (or many others).
I use SurfaceView for my 2D Android game which I have almost completed. It's based on JBox2D. It is perfectly running on Samsung Galaxy S2, its FPS is 60. It is also running smoothly on HTC Explorer, its FPS is about 54. I thought that if my game was working well in these relatively old devices, it would be working better in the newer ones. But I was wrong! I saw yesterday the FPS value of my game on Galaxy Note 4 is varied between 22 and 45 depending on the number of game objects.
After investigating on this issue in Google and StackOverflow, I deduced that the new devices like Galaxy Note 4 which has higher resolutions (1440 x 2560) could not handle with their large images whereas the little ones can handle with their own smaller images (Galaxy s2:480 x 800, HTC Explorer:320 x 480). Yes, the new devices are surely faster than the older ones, but I think their huge resolutions of the newer devices are the reason of the slowness on the SurfaceView. Of course, this is valid under SurfaceView conditions. If I used OpenGL for my game, it would not be a problem for the new devices having high resolutions.
My bitmaps are designed for 800 x 1280 devices. According to the different device resolutions, my game rescales the images when they are loaded at the beginning of the each level by using createScaledBitmap.
I couldn't transform my game from SurfaceView to OpenGL platform because my game is about to finish and I didn't have enough knowledge about OpenGL.
What should I do?
I believe you have correctly identified the problem: newer devices have pixel counts like you'd find on a 27" monitor (2560x1440), because the manufacturers are chasing screen resolution like they do camera megapixels. The result is that rendering a full screen takes longer, especially when you're doing it in software. Faster CPUs and increased bus bandwidth can help, but full-screen software rendering is problematic.
The solution for Android is to make the Surface smaller, and let the hardware scale it up as it's being scanned out. This is significantly easier (and more efficient) than scaling up each individual item. You do this with the SurfaceHolder#setFixedSize() method. For example, for a 2560x1440 display, you could set the Surface size to 1280x720, and only render a quarter of the pixels. The display performs the pixel doubling (with bilinear filtering).
You can find a blog post here, and can see this in action in Grafika's "hardware scaler exerciser" activity (youtube demo video).
The various examples use GLES -- which also benefits from having fewer pixels to fill -- but applies to Canvas rendering as well.
I am working with AndEngine and OpenGL ES 2.0. I keep reading about GL_MAX_TEXTURE_SIZE and how I should keep my texures under 1024x1024. I started wrong before and while using tilesets in TMX extension (doesn't really matter what it is, if you don't know AndEngine) I get to a tileset that makes a texture wider than 1024px. I am thinking of splitting the tileset into two, making them "safe". But I can't find any device released in last couple of years that has this limit set under 2048x2048. Is there any list or website I can use to filter devices by GL_MAX_TEXTURE_SIZE?
I read the following questions:
Minimum required Texture Size for compliance with OpenGL-ES 2.0 on Android?
Is there any Android device with screen size greater than GL_MAX_TEXTURE_SIZE?
And I used this site to search for devices. But I can't search by/filter by GL_MAX_TEXTURE_SIZE, which makes the search tedious. I am asking mostly because I started wrong, it's a hobby project and the amount of work might be too large compared to the number of possible devices that will be enabled (I expect 0).
1024x1024 is about the safest you can go on any device, especially on older ones. Newer devices shouldn't have any problem, although I've seen recent devices (I recall a Galaxy Nexus, the newest ICS update fixed that though) render white quads with texture sizes of size 2048x1024.
If you're targeting new devices and want to keep older ones compatible, it shouldn't hurt to split your tilesets. After all, you aren't likely to do too many context switches if you use two or three spritesheets for background, etc.
If you still have the individual image files, breaking them into small sized Atlases or custom sized atlases is easy if you use the TexturePacker2 tool from the LibGdx library.
I don't know the exact limitation of devices, but it's always better to take into consideration the lowest end of device you want to support and build upward from there. Using the LibGdx tool, you can easily change your mind later, so it's the most flexible solution.
Look at:
LibGdx TexturePacker
I have an application which views zoomable images using OPENGLES2.0, and want to render large textures - 1920x2560 and larger - and get GL_INVALID_VALUE errors when trying to load them.
How do I go about doing this?
Mobile devices often cannot support textures bigger than 2048 pixels (width or height).
IOS devices such as IPAD for instance cannot support textures bigger than 2048x2048.
I have found the same limit on most of the Android devices where I have tested my PATRIA 3D engine hence I can only advice you to stay under this limit.
I suggest you to read carefully this official OpenGL document
http://www.opengl.org/resources/faq/technical/texture.htm
In particular point:
21.130 What's the maximum size texture map my device will render hardware accelerated?
My Android app has been out for several months and works fine on any number of WVGA phones like the Droid, Droid 2, Galaxy, etc.
On the Motorola Xoom, however, a small portion of the textures load with white boxes where the images should be.
Researching online the most usual cause for this appears to be not using power of two textures. This seems an unlikely explanation since they work fine on so many other devices. Also, I am using power of two textures. The one caveat there is that I'm loading a bunch of bitmaps into a 1024 by 1024 texture dynamically. The code I'm using is from a now defunct library called Rokon, the relevant texture atlas code is here: http://code.google.com/p/rokon/source/browse/trunk/src/com/stickycoding/rokon/TextureAtlas.java?r=260 -- Like I said, I'm skeptical this could be the cause since it works on so many other devices AND many of the textures I am loading this way do work fine.
But I'm not sure what else could be causing it. A memory issue seems unlikely given that amount of memory available on the Xoom compared to the other devices the app works on.
Right now I don't own a zoom, but I can replicate the issue via DeviceAnywhere (where I see white backgrounds).
Nothing of interest shows up in LogCat either.
I know this isn't much to go on, but I'm at a loss here, what kinds of potential causes should I be looking at here? Thanks in advance for any ideas.
Try using glGetError() to see if OpenGL throws any errors
Is your application 2D or 3D? When you're drawing your sprites on the screen; which method are you using?
If your texture is white during onDrawFrame that probably depends on:
An untextured quad (using VBO:s or standard Vertex Arrays) - probably not, because it works on other devices
Xoom lacks support of the draw_texture extension - if you're using 2D
Xoom lacks support of VBO:s (Vertex Buffer Objects) - probably not, almost every Android device out there supports VBO:s
Do you have any sort of texture compression implemented that Xoom doesn't support?
At runtime, use this code to get the extensions and check if they're available:
String extensions = gl.glGetString(GL10.GL_EXTENSIONS);
boolean supportsDrawTexture = extensions.contains("GL_OES_draw_texture");
// Continue here and sooner or later you should see where Xoom lacks support
// where other devices doesn't.
Is it possible that you're falling foul of Android's automatically-resize-bitmaps behaviour? Print out the bitmap sizes as they are loaded to check, or move them to res/drawable-nodpi to avoid the behaviour entirely.
Is it possible that your texture exceeds 2048 pixels width or height? That's the maximum allowed texture size on XOOM.