PDA

View Full Version : OpenGL blending equations



soconne
06-01-2004, 02:48 PM
Is there a website that lists all the equations used for the different OpenGL blending modes, for instance

glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR);
glBlendFunc(GL_ONE, GL_DST_COLOR);
...

Anybody know of a site?

yooyo
06-01-2004, 04:01 PM
src factor (apply to src_color - incoming color):
GL_ZERO, GL_ONE, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, and GL_SRC_ALPHA_SATURATE

dest factor (apply to existing framebuffer color):
GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, and GL_ONE_MINUS_DST_ALPHA

Blending equation:
result_color = src_factor(incoming_color) + dst_factor(framebuffer_color).

Meaning of factors:
GL_ZERO(col) = 0 * col = 0
GL_ONE(col) = 1 * col = col
GL_DST_COLOR(col) = framebuffer_color * col
GL_ONE_MINUS_DST_COLOR(col) = (1 - framebuffer_color) * col
GL_SRC_ALPHA(col) = col.a * col
GL_ONE_MINUS_SRC_ALPHA(col) = (1 - col.a) * col
GL_DST_ALPHA(col) = framebuffer_color.a * col
GL_ONE_MINUS_DST_ALPHA(col) = ( 1 - framebuffer_color.a) * col
GL_SRC_ALPHA_SATURATE(col) = (f, f, f, 1)*col; f=min(col.a, 1-framebuffer_color.a)

examples:
glBlendFunc(GL_ONE, GL_ONE)
1 * src_col + 1 * framebuffer_color = src_col + framebuffer_color => color add

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
src_col.a * src_col + (1 - src_col.a) * framebuffer_color => decal

glBlendFunc(GL_DST_COLOR, GL_ZERO)
framebuffer_color * src_col + 0 * framebuffer_color = framebuffer_color * src_col => modulate colors

yooyo

idr
06-01-2004, 07:21 PM
Uh...you're at the site. :) All of the relevent information is listed on pages 178 and 179 (pages 191 and 192 of the pdf) of the OpenGL 1.5 spec.

sqrt[-1]
06-01-2004, 10:17 PM
Also keep in mind there is a glBendFunc and a glBlendEquation function that do different things ...

soconne
06-02-2004, 04:20 AM
Thanks for all that information, but I'm having a little problem. I'm trying to implemented glBlendFunc(GL_DST_COLOR, GL_ZERO), and this is what I do for a single pixel

for each R, G, B value

srcR/=255.0;
dstR/=255.0;
newR = srcR*dstR + 0*srcR;
newR*=255.0;
if(newR > 255) newR = 0;

But doing this doesn't get me even close to the result of what OpenGL displays. This for some reason, simply makes whatever was in the destination image become darker, but doesn't blend the two correctly. Is this the correct way for GL_DST_COLOR, GL_ZERO ?

ZbuffeR
06-02-2004, 07:57 AM
I guess :
if(newR > 255) newR = 0;
should read :
if(newR > 255) newR = 255;

soconne
06-02-2004, 08:07 AM
Oh, type in my post. I meant to put if(val > 255) val = 255.

Anyway, still have this problem. Anybody?

ZbuffeR
06-02-2004, 10:54 AM
With glBlendFunc(GL_DST_COLOR, GL_ZERO) you actually multiply incoming image and framebuffer. As colors are taken in the range [0,1], it must darken the image (only white leave it as is).

You can do some experiments with Photoshop or Gimp, use 2 layers, the top one in 'multiply' mode.

If you don't see such effect in OpenGL, it is a bug, because I do see that !

soconne
06-02-2004, 11:04 AM
Well I've come up with the following code below, and it only seems to work for the following situations:

glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR);
glBlendFunc(GL_ONE, GL_ONE);

All other situations do not produce the correct result.

Any help with the code below is much appreciated.



for(int i=0; i < 3; i++)
{

c0 = dst[i]/255.0;
c1 = src[i]/255.0;

if(blend0 == GL_ZERO)
newc0 = 0*c0;
else if(blend0 == GL_ONE)
newc0 = 1*c0;
else if(blend0 == GL_SRC_COLOR)
newc0 = c0*c0;
else if(blend0 == GL_DST_COLOR)
newc0 = c1*c1;
else if(blend0 == GL_ONE_MINUS_SRC_COLOR)
newc0 = (1-c0);
else if(blend0 == GL_ONE_MINUS_DST_COLOR)
newc0 = (1-c1);

if(blend1 == GL_ZERO)
newc1 = 0*c1;
else if(blend1 == GL_ONE)
newc1 = 1*c1;
else if(blend1 == GL_SRC_COLOR)
newc1 = c0*c0;
else if(blend1 == GL_DST_COLOR)
newc1 = c1*c1;
else if(blend0 == GL_ONE_MINUS_SRC_COLOR)
newc1 = (1-c0);
else if(blend0 == GL_ONE_MINUS_DST_COLOR)
newc1 = (1-c1);


val = (newc0+newc1)*255;
if(val > 255) val=255;
if(val < 0) val=0;

dst[i] = (char)val;
}

plasmonster
06-02-2004, 11:23 AM
Try it this way:

c0 = src[i]/255.0;
c1 = dst[i]/255.0;

zeckensack
06-02-2004, 09:59 PM
Originally posted by oconnellseanm:
Well I've come up with the following code below <...>Here you go. I've marked the places where I made corrections.

for(int i=0; i < 3; i++)
{

c0 = src[i]/255.0; //<-
c1 = dst[i]/255.0; //<-

if(blend0 == GL_ZERO)
newc0 = 0*c0;
else if(blend0 == GL_ONE)
newc0 = 1*c0;
else if(blend0 == GL_SRC_COLOR)
newc0 = c0*c0;
else if(blend0 == GL_DST_COLOR)
newc0 = c0*c1; //<-
else if(blend0 == GL_ONE_MINUS_SRC_COLOR)
newc0 = c0*(1-c0); //<-
else if(blend0 == GL_ONE_MINUS_DST_COLOR)
newc0 = c0*(1-c1); //<-

if(blend1 == GL_ZERO)
newc1 = 0*c1;
else if(blend1 == GL_ONE)
newc1 = 1*c1;
else if(blend1 == GL_SRC_COLOR)
newc1 = c0*c1; //<-
else if(blend1 == GL_DST_COLOR)
newc1 = c1*c1;
else if(blend0 == GL_ONE_MINUS_SRC_COLOR)
newc1 = (1-c0)*c1; //<-
else if(blend0 == GL_ONE_MINUS_DST_COLOR)
newc1 = (1-c1)*c1; //<-


val = (newc0+newc1)*255;
if(val > 255) val=255;
if(val < 0) val=0;

dst[i] = (char)val;
}

knackered
06-02-2004, 11:32 PM
You've yet to address the efficiency of your code, I take it? :)