Premultiplied alpha trouble

Oldtimer
Posts: 834
Joined: 2002.09
Post: #1
Hi all!

I've been working on premultiplying all the El Ballo texture files, and they look just fine in Preview and Photoshop. However, when I load them into the actual game, they blow up and produce very odd color values. Here's a composited screenshot of what's happening: top half is using my pre-multiplied textures and bottom half is using the non-premmed ones. I've tried with glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA) as well, but with the same results.
[Image: premprob.jpg]
Can anyone guess as to what is going wrong here? It looks as if pure yellow goes into pure cyan, which would mean that (pure red + pure green) becomes (pure green + pure blue) (#FFFF00 -> #00FFFF). Also, if you look at the text in the upper half, right below GL_SRC_ALPHA: that text is black in the texture, but is completely transparent here. Looks to me as if the pixels become badly swizzled somewhere, but the same code works if I just use the non-premultiplied textures instead. Any guesses?
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
The correct blend function for premultiplied images is ONE, ONE_MINUS_SRC_ALPHA.

Are you sure you haven't accidentally swizzled your textures' color channels during premultiplication? That's what it looks like's happened to me...
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #3
OK, fixed that. Turned out to be a very subtle bug in my file loading code (which ought to have broken every file loaded since the dawn of this game) which caused a pointer offset which, yes, in a way swizzled the channels. Now, however, everything looks great. Except, whenever I draw with an glColor* alpha less than 1, I get a strange glowing effect. Similarily, half-transparent textures look awfully dark. Any hints?
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #4
any glColor calls you make must also be premultiplied.

Eg, if you would have done glColor4f(r, g, b, a); , instead do glColor4f(r*a, g*a, b*a, a);
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #5
Why do you want to premultiply everything? Unlike Quartz, there's really no penalty in GL.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #6
because premultiplication avoids halos around sprites when they're bilinearly filtered, and it's simpler than ensuring that the color channels bleed into the transparent areas appropriately.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #7
RGB * alpha * one = RGB * alpha. There's no difference between premultipling the alpha, using GL_ONE for the src blending factor and not premultipling the alpha, using GL_SRC_ALPHA for the src blending factor. Except, of course, that premultipling destroys your RGB data so you can't turn the alpha channel off whenever you want to.
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #8
Well, my problem is that I have bright halos around my quads. (This is 2D all the way, you see) Arekkusu, could you elaborate on your second post? Not quite following you here...
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #9
There's no requirement to premultiply your texel data.

If you take some RGB+A image from photoshop, and premultiply it (for example with tiffutil, or programatically) then you build an RGBA texture out of it and blend it into your scene with glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA). That's fine, the resulting framebuffer pixel is src_rgb * src_alpha * one + dst_rgb * (one - src_alpha);

Alternatively you can take some RGB+A image from photoshop as is, build an RGBA texture out of it and blend it into your scene with glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). The resulting framebuffer pixel is src_rgb * src_alpha + dst_rgb * (one - src_alpha).

It's exactly the same. That's what I was saying. I've done it both ways.

If you have fringes, check your image data. In hex.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #10
As I said, the problem is only when the nonpremultiplied image is bilinearly filtered. halfway between an opaque green texel and a transparent white texel, a semitransparent light-green fragment is generated, which produces the effect of a light halo. Halfway between an opaque green texel and a transparent black texel, a semitransparent dark-green fragment is generated, which produces the effect of a dark halo. Only if the transparent texel is the same shade of green as the opaque one is the halo eliminated.

By contrast, if the image is premultiplied there is only one case -- an opaque green texel next to a transparent black texel. In this case the filtered fragment (semitransparent dark green) is actually a premultiplied pure green, the desired color. No halo is visible.

So, premultiplication isn't the only solution, but it is the most practical solution -- premultiplication of the image is easier than ensuring the transparent texels are the same color as the surrounding opaque texels.
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #11

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #12
Thanks for the insightful discussion, both Keith and Arekkusu (actually, I have no idea what your real name is. Smile ) It seems to work fine now, and my haloes are gone. Wohoo! Smile

Reubert, that's very cool, and I've seen it in files exported from Illustrator, just never knew what the heck was going on. Thanks for posting!
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #13
(arekkusu == alex)
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #14
Alex, got that. Very cool web page. Too bad Ivan just translates into Iwan, which isn't very cool at all.
EDIT: Oh, you edited your post. Disregard the web page stuff. Smile
Quote this message in a reply
Member
Posts: 184
Joined: 2004.07
Post: #15
I haven't used premultiplied alpha before (it sounds like a good idea) though correct me if I'm wrong- if you have a particularly transparent amount of color, then your precision goes down provided you are using integral channels (e.g. if you were making a 1/2 transparent image, then you'd only use values 0-127 instead of the whole range of 0-255 of a byte.) I assume that's the downside of using premultiplied alpha?


After a quick google, this is the problem I had in mind: http://www.teamten.com/lawrence/graphics...plication/

Though it does sound like the benefits outweigh the downside. In my game I actually intentionally make some of the black haloes because it gives an interesting look to some of the icons. The rest of my images I have a blurred copy of the image in the transparent pixels to make sure surrounding pixels aren't black or white.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Trouble with alpha when drawing into FBO TomorrowPlusX 19 11,323 Oct 23, 2012 02:07 PM
Last Post: TomorrowPlusX
  Premultiplied alpha halos IBethune 5 4,075 Feb 11, 2007 01:56 PM
Last Post: OneSadCookie
  png without alpha fine, png with alpha, nothing dave05 6 6,838 Jun 11, 2005 10:31 AM
Last Post: dave05
  How can I load a PNG without premultiplied alpha? Prime 6 7,488 Feb 15, 2005 08:52 PM
Last Post: arekkusu