views:

330

answers:

1

I've got a problem with openGL on iPhone which I'm sure must have a simple solution!

When I load a texture and display it, I get a lot of what I believe is called 'Colour Banding', whereby the colours, particularly on gradients, seem to get automatically 'optimized'.

Just to demonstrate that this wasn't anything wrong with my own code, I downloaded the iPhone 'Crashlanding' app and replaced the background image, and as you can see in the image below (Taken from the simulator), the exact same thing happens. The image on the left is the original PNG, and on the right is it in the game. It's almost as if it's palette is being downsized to a 256 colour one.

Screenshot

I'm sure this is related to the format I'm saving the image as, although it doesn't just happen with PNG's, it seems to happen no matter what image format I chose.

Doing my head in! If you want to recreate this, simply download the crash landing app, and replace the background. Thanks so much in advance for any help.

+1  A: 

iPhone does not support 24bit color format (8 bits per color). It supports (uncompressed):

  • 565 format, red = 5 bits, green = 6 bits, blue = 5 bits
  • 5551 format, red = 5 bits, green = 5 bits, blue = 5 bits, alpha (transparency) - 1 bit
  • 4444 format, 4 bits for red/green/blue/transparency.

So, if you'll draw gradient from 0 to 255 in red color, you'll see 256 gradations in 24bit format, but only 32 gradations in 565/5551 format or even 16 gradations in 4444. 24bit color is being transformed "on the fly", so it looks like it is being supported but it's not.

That's why there is color banding.

/That's true for OpenGL ES 1.0, don't know details about 2.0 yet/

Update: My mistake. iPhone does support other formats (8888), but, maybe, there is a conversion in the app itself?

Update 2: Ah, you are using cocos2d. And do not use (I assume) transparency in your image. Cocos2d transforms this kind of images to a 565 format. I think you'll have to modify cocos2d to "unimpliment" this optimisation, if you need.

Alexander Babaev
So it's the image format that's the problem.What program do I tell the artists to export with, and what options should they be ticking, in order to get exactly what they want from the final image?So far they've tried Pixelmator and Gimp, but they appear to get the same issues saving from both.
Chicknstu
Well, there's a problem. PNG format that is used to load images on the iPhone can use only 24bit images of 8bit with palette. So, in fact, I do not have any idea how to see in an editor what it will look like on the iPhone. The only instrument that they can use to get an idea what it will look like is "Posterise", but it is not flexible enough. Outside of that… I don't know really. That's another question and it is not my point of expertise, I'm a programmer :)
Alexander Babaev
Support for GL_RGB/GL_UNSIGNED_BYTE and GL_RGBA/GL_UNSIGNED_BYTE textures is mandated by the specifications for OpenGL ES 1.1 (see Table 3.4 in Section 3.6.2), and iPhone OS therefore supports them both. I assume based on your comment about using the CrashLanding sample app that you’re using the Texture2D class to load your image—have you verified that it’s not performing any format conversion on your behalf?
Pivot
Yes, I've found it here: "Best Practices for Working with Texture Data" in the docs. Sorry for wrong answer, corrected it.
Alexander Babaev
Here's a transcript of the codehttp://code.google.com/p/cocos2d-iphone/source/browse/branches/branch-0.1/OpenGLSupport/Texture2D.mThere is indeed a section that looks like it's doing a conversion, but removing it makes bad things happen. Images are corrupt or don't even display at all.
Chicknstu
Ah, I understand now. You do not use transparency in your image, right? That's why cocos2d transforms in to 565 format instead of 8888. That causes banding. Maybe you'll have to force cocos2d to do it.
Alexander Babaev
OK, solved. It seems that if you don't have any transparency in your image at all, Pixelmator (The art tool I'm using) saves out in 565 and doesn't have an alpha channel. Hence, it was going through that conversion process.The solution was to put a tiny negligible piece of transparency in the image so that it would save properly!Worse still, the fixed effect only showed up on the device, it still looks bad on the simulator.Thank so much for guiding me through this guys, you're amazing.
Chicknstu