glBlendFunc with transparent drawables

Hi there,

I’ve got a non-intuitive thing going on with glBlendFunc and a transparent drawable. Here’s what I do:

  1. Create a drawable that has a transparent background so that I can see the desktop through it.
  2. Draw a bitmap.
  3. Enable blending and call glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
  4. Draw a bitmap blended over the other one.
  5. Disable blending.

My second bitmap is blended with the first. Good. However the desktop background behind the first bitmap is also blended in!

If I use GL_SRC_ALPHA_SATURATE then the deskktop doesn’t show, but I lose the colour of my second bitmap.

If I use glReadPixels for the area where my second bitmap is to be blended, the surface underneath is the first bitmap - not the desktop.

What’s happening here?

Thanks for any help.

Kind regards,
Christopher

It isn’t clear what you expect to happen. What you’re describing seems reasonable.

Perhaps you should post some images and/or state your desired effect.

Originally posted by dorbie:
[b]It isn’t clear what you expect to happen. What you’re describing seems reasonable.

Perhaps you should post some images and/or state your desired effect.[/b]

Sorry for not being clearer - I don’t want to see the desktop underneath - I just want to see bitmap B blended over bitmap A.

Here’s an example:
http://www.classactionpl.com/desktopblend.jpg

Bitmap A is an image of the world - you’ll see part of Africa in the jpg - that’s bitmap A. Bitmap B is the translucent rectangle. You’ll see bitmap A through bitmap B (good), but you also see the desktop (those letters inside bitmap B are from the desktop behind).

Interestingly, when I read the pixels from the area where bitmap B is to be drawn i.e. before it is drawn, the pixels read are of Bitmap A - not of any desktop behind. So it appears that Bitmap A is all that is in my framebuffer prior to blending. However if I blend then my framebuffer appears to have bitmap A and the desktop in it as a destination. I just don’t understand.

'hope this is clearer.

-C

The drawable area’s opacity is determined by the alpha value of the pixel at that window location. The area where blending occurs will have an alpha value that is not fully opaque. So the desktop bleeds through. This is correct behavior.

Set the alpha channel to full opacity over the entire portion of the drawable you want to be fully opaque.

Originally posted by chemdog:
[b]The drawable area’s opacity is determined by the alpha value of the pixel at that window location. The area where blending occurs will have an alpha value that is not fully opaque. So the desktop bleeds through. This is correct behavior.

Set the alpha channel to full opacity over the entire portion of the drawable you want to be fully opaque.[/b]

I suspected something like this: so how do I set the opacity of the drawable selectively? Disclosure: I’m using OS X here and I think that I only get the option of stating that the drawable is entirely opaque or not. Is there a gl method of selecting a portion of the drawable and making it opaque?

You can also draw alpha channels and color component channels independently of all else. With or without blending.

glColorMask is your friend.

Alternatively…

If you have a windomanager composit going on based on a windowing system that uses framebuffer alpha, then just turn off blending in OpenGL altogether. Set alpha to the desired opacity on all stuff you draw and render away.

Originally posted by dorbie:

glColorMask is your friend.

You know, I just discovered glColorMask(1, 1, 1, 0) and all is now well. I didn’t understand that the alpha value of the resulting blend was also computed.

What would be ideal is to blend as I want (one minus src alpha), but have the result of the blend equate to an opaque alpha value. This is what glColorMask achieves, but I’m now curious if there’s a way of specifying the glBlendFunc in such a way that the resultant alpha will be 1.0.

Cheers,
-C