PDA

View Full Version : How to do normal blending?



gekko513
03-19-2005, 02:58 AM
I want to do normal blending with OpenGL, like the blending between layers in Photoshop for example, but it doesn't seem possible with glBlendFunc.

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) does not work as expected because if I start with a transparent buffer, render a solid primitive and then render a semi-transparent, the result is semi-transparent even if I did render something totally solid in between.

That's just all wrong, and it does not work for me.

How can I do normal blending where the alpha value is calculated as 1 - (1-As)*(1-Ad) ?

gekko513
03-19-2005, 01:48 PM
I haven't found a general solution to this problem which I consider to be a gaping flaw in the OpenGL standard, but I have found a workaround for my case, so I thought I would let anyone who are interested know ...

I use glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
First I render a solid background, that covers most of the buffer, the edges are still transparent.
Then I render the semi-transparent primitives twice, first with the previously mentions blending and then with glBlendFunc(GL_ONE, GL_ONE), texture turned off and glColor4f(0.0, 0.0, 0.0, 1.0);

The solution does not seem very elegant and it seems suboptimal, but it works for me. However, this only works because all the semi-transparent primitives are rendered entirely inside the bounds of the solid background.

ZbuffeR
03-20-2005, 02:27 AM
I fail to see how you managed to not make it work :


// init part
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);


// in main loop
glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
glClear (GL_COLOR_BUFFER_BIT);


glPushMatrix ();

glBegin (GL_TRIANGLES);
glColor4f (1.0f, 1.0f, 0.5f, 1.0f);
glVertex2f (0.0f, 1.0f);
glVertex2f (0.87f, -0.5f);
glVertex2f (-0.87f, -0.5f);

glColor4f (0.0f, 1.0f, 0.5f, 0.5f);
glVertex2f (0.8f, 1.0f);
glVertex2f (0.0f, 0.0f);
glVertex2f (1.0f, 0.0f);
glEnd ();

glPopMatrix ();

Works perfectly for me.

Beware of the 'OpenGL is not working' ... it can be right on super fancy new stuff with beta drivers or for features almost never used. Not on something like that.

Edit: I suppose you are using textures. best way to control transparency like in photoshop is to use :

// allow to easily change color with a single glColor call
glEnable(GL_COLOR_MATERIAL);

// multiply texture with base color
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

/////////// for each layer :
// change transparency, t in [O,1] range
glColor3f(1.0f,1.0f,1.0f,t);
//bind texture
//draw stuff
///////

gekko513
03-20-2005, 06:05 AM
Your code works in the same way that I explained.
------------ Screenshot -----------------
http://lavacat.com/OpenGL17.png

I know it won't work because the blend function is by definition not usable for what I'm trying to do.

SRC_ALPHA, ONE_MINUS_SOURCE_ALPHA calculates the resulting alpha as As*Sa+Ad*Da which in this case is, 0.5*0.5+1.0*(1-0.5) = 0.75

I need the resulting alpha to be 1.0, like in photoshop blending, or window manager blending, but there is no suitable blending function for this. :(

ZbuffeR
03-20-2005, 02:50 PM
If I understand well, you want to separate rgb and alpha blending, there are extension to adress this (if supported by your hardware) : GL_EXT_blend_func_separate (and maybe GL_EXT_blend_equation_separate).

http://oss.sgi.com/projects/ogl-sample/registry/

By the way, how did you made the text appear behind... AH ! I see, when you say a transparent buffer, you mean some kind of overlaying GL drawing on top of desktop image. Am I right ?

gekko513
03-20-2005, 03:31 PM
Yes, I use OpenGL laid directly over the desktop, or directly in a transparent window, to be exact.

I'm not sure if I want to separate color and alpha blending, I'll take a look at the link. I do want to use as few extensions as possible for maximum compatibility, though.

I think I'll just stick to the work around that I found, since it seems to do the job well, in my case.

Edit: I looked at GL_EXT_blend_func_separate and with that I would almost be able to do what I want:

BlendFuncSeparateEXT(SRC_ALPHA, ONE_MINUS_SRC_ALPHA, SRC_ALPHA, ONE);

would have been nice. The alphas would have been additive instead of multiplicative which would be ideal, but I could have lived with that.

Thanks for helping out.