One of the biggest gotchas with textures on
Apple devices is the issue of premultiplied alpha.
If the RGB components in an image have already been scaled by their
associated alpha value, the image is considered to be premultiplied.
Normally, PNG images do not store premultiplied RGB values, but Xcode does
some tampering with them when it creates the application bundle.You might recall that we passed in a flag to
the CGBitmapInfo mask that’s related to this; Example 1 shows a snippet of the
ResourceManager class, with the flag of interest highlighted in bold. Example 1. Using a CGContextCGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big; CGContextRef context = CGBitmapContextCreate(data, description.Size.x, description.Size.y, description.BitsPerComponent, bpp * description.Size.x, colorSpace, bitmapInfo); CGColorSpaceRelease(colorSpace); CGRect rect = CGRectMake(0, 0, description.Size.x, description.Size.y); CGContextDrawImage(context, rect, uiImage.CGImage); CGContextRelease(context);
|
For nonpremultiplied alpha, there’s a flag
called kCGImageAlphaLast that you’re welcome to try,
but at the time of this writing, the Quartz implementation on the iPhone
does not support it, and I doubt it ever will, because of the funky
preprocessing that Xcode performs on image files. So, you’re stuck with premultiplied alpha.
Don’t panic! There are two rather elegant ways to deal with it: Use PVRTexTool
to encode your data into a PVR file. Remember,
PVRTexTool can encode your image into
any OpenGL format; it’s not restricted to the
compressed formats. Or, adjust your blending equation so that
it takes premultiplied alpha into account, like so: glBlendFunction(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
By using GL_ONE for the
sfactor argument, you’re telling OpenGL there’s no
need to multiply the RGB components by alpha.
In Figure 1, the
left column contains a normal texture, and the right column contains a
texture with premultiplied alpha. In every row, the
dfactor argument is
GL_ONE_MINUS_SRC_ALPHA.The following list summarizes the best results
from Figure 1: For textures with straight alpha, set
sfactor to GL_SRC_ALPHA and
dfactor to
GL_ONE_MINUS_SRC_ALPHA. For textures with premultiplied alpha, set
sfactor to GL_ONE and
dfactor to
GL_ONE_MINUS_SRC_ALPHA. To check whether a texture has
premultiplied alpha, disable blending, and look at the
silhouette.
|