Rule #1, RTFM. I'm afraid I break this rule quite often and when it comes to learning something as arcane as OpenGL, you're gonna have to even if the docs suck.
I ran into this problem after testing on the emulator and my Sony Xperia x10 mini fine, but surprisingly my Samsung Galaxy S failed to render the textures.
I soon discovered that for OpenGL 1.x, the dimensions of texture bitmaps have to be in the power of 2. That means the width or height can be any combination of 1, 2, 4, 8, 16, 32, 64, 128, 256, etc.
2x512, 16x64, 8x256, whatever. If any of those were a non-power of two (NPOT), you run the risk of it not loading on some devices.
Obvious fixes
Two ways of dealing with it. First method is obvious, resize your bitmap so it's in the right size in the power of 2's. If you're still running into errors, see the section below.
Second way to use OpenGL 2.x, which allows for NPOT texture files to be loaded. This is a choice between dumping support for older devices or using a newer API.
I believe you'll need at least SDK API level 8 and ensure all devices have OpenGL 2.x and need to set something in the Android manifest.
Not so obvious fixes
Alright, so you've tried the first two methods. But there are many other possible issues you will run into.
Other people had suggestions of putting the drawables into the "/res/raw" folder instead. That isn't an issue if you're using the InputStream method of loading bitmaps.
Others had the solution of putting it into /res/drawable-nodpi. That didn't work for me either.
Why all this hassle? The answer is simple, it's because the Android framework can't be trusted to load the bitmaps accurately. Manufacturers may tweak the source, image compression upon loading works differently across devices, etc etc.
To ensure that it loads exactly the way you've created it, ensure that this function isn't changing your bitmaps:
Bitmap bm = BitmapFactory.decodeResource(context.getResources(), resID)
For the textures to load properly, swap it for this longer snippet to prevent bitmap transformation:
InputStream is = context.getResources().openRawResource(resID);
try {
bitmap = BitmapFactory.decodeStream(is);
}
finally {
//Always clear and close
try {
is.close();
is = null;
}
catch (IOException e) {
}
}
Give it a shot, it'll probably work. Tested on Android 1.6 (Sony Xperia x10 mini) and Android 2.3.6 (Samsung Galaxy S).
Sources
- android - OpenGL ES Textures do not display properly on HTC Magic (1.6) but display fine on Emulator and Mytouch 4g
- android - Opengl ES Texture working on Emulator but not on Divice
- android - Trying to draw textured triangles on device fails, but the emulator works. Why?
- Factor: a practical stack language: OpenGL textures and the power-of-two size restriction
- android - Can OpenGL ES render textures of non base 2 dimensions?
- Draw text in OpenGL ES (Android)
- java - Android - OpenGL - Emulator vs Actual Device