Thread: OpenGL: Pixel addition

  1. #1
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879

    OpenGL: Pixel addition

    Hey guys,
    I'm trying to figure out a way to render content in my scene such that it gets rendered *additively*. I've been experimenting with glBlendFunc() and glTexEnvi(), but I always seem to end up with an ordinary transparency effect with the resulting pixel value somewhere between the source and destination.

    Can someone post a snippet of code with working pixel addition, i.e. where the resulting pixel is *brighter* than either the source or destination? I'm sure it's not as difficult as I'm making it, but I can't quite get it right.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Additive blending is as simple as:

    Final = Pixel1 + Pixel2;

    This will cause values to go out of range very fast and usually this type of operation will need some limits and/or coefficients imposed on it. You could only add 50% of pixel1 with 50% of pixel2 and so on.

    I'm not sure how to do it in OpenGL but in Direct3D HLSL it's as simple as this:

    Code:
    float4 PixelShader(float2 texture_uv : TEXCOORD0,float2 texture2_uv : TEXCOORD1) : COLOR
    {
        float4 texcolor1 = tex2D(TextureSampler1,texture_uv);
        float4 texcolor2 = tex2D(TextureSampler2,texture2_uv);
    
        return (texcolor1 + texcolor2);
    }
    You could also do an exposure filter:
    Code:
    float4 PS(float2 tex : TEXCOORD0) : COLOR
    {
         return 1.0f - exp(-tex2D(ColorMapSampler,tex) * exposure) * 1.75f;
    }
    This is:
    1.0f - e^(-color * exposure) * <some_brightness_constant>

    If you are doing a post process bloom you can set exposure fairly high and the bloom filter will take care of the rest. Without shaders you will have to perform this operation on each channel of the color. This shader also assumes the human eye sees RGB in equal amounts which is not true in real life.

    Note that the following color channels are in range 0.0f to 1.0f to make things much simpler.

    In C++ code additive pixel blending is:
    Code:
    RGB color1;
    RGB color2;
    
    RGB final_color;
    
    final_color.red = color1.red + color2.red;
    final_color.green = color1.green + color2.green;
    final_color.blue = color1.blue + color2.blue;

    Color modulation (dark colors in color2 darken the final color, light colors in color2 do not affect the final color since any number * 1.0f is the same number)
    This is also known as light mapping.
    Code:
    RGB color1;
    RGB color2;
    
    RGB final_color;
    
    final_color.red = color1.red * color2.red;
    final_color.green = color1.green * color2.green;
    final_color.blue = color1.blue * color2.blue;

    Linear interpolation between colors:
    Code:
    float lerp(float v1,float v2,float lerp)
    {
        return v1 + lerp * (v2 - v1);
    }
    
    RGB color1;
    RGB color2;
    
    RGB final_color;
    
    float lerp_factor = 0.5f;
    final_color.red = lerp(color1.red,color2.red,lerp_factor);
    final_color.green = lerp(color1.green,color2.green,lerp_factor);
    final_color.blue = lerp(color1.blue,color2.blue,lerp_factor);
    Color averaging:
    Code:
    RGB color1;
    RGB color2;
    
    RGB final_color;
    
    final_color.red = (color1.red + color2.red) * 0.5f;
    final_color.green = (color1.green + color2.green) * 0.5f;
    final_color.blue = (color1.blue + color2.blue) * 0.5f ;
    Bilinear interpolation of 4 colors
    Code:
    float lerp(float v1,float v2,float lerp)
    {
        return v1 + lerp * (v2 - v1);
    }
    
    RGB color1;
    RGB color2;
    RGB color3;
    RGB color4;
    
    RGB temp_color1;
    RGB temp_color2;
    RGB final_color;
    
    float lerp_factor = 0.5f;
    
    temp_color1.red = lerp(color1.red,color2.red,lerp_factor);
    temp_color1.green = lerp(color1.green,color2.green,lerp_factor);
    temp_color1.blue = lerp(color1.blue,color2.blue,lerp_factor);
    
    temp_color2.red = lerp(color3.red,color4.red,lerp_factor);
    temp_color2.green = lerp(color3.green,color4.green,lerp_factor);
    temp_color2.blue = lerp(color3.blue,color4.blue,lerp_factor);
    
    final_color.red = lerp(temp_color1.red,temp_color2.red,lerp_factor);
    final_color.green = lerp(temp_color1.green,temp_color2.green,lerp_factor);
    final_color.blue = lerp(temp_color1.blue,temp_color2.blue,lerp_factor);
    Ok so I don't have any OpenGL code. But hopefully the color formulas can help later on.
    Last edited by VirtualAce; 12-02-2008 at 12:54 AM.

  3. #3
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Additive blending in OpenGL: glBlendFunc(GL_SRC_ALPHA, GL_ONE) -- as far as I could work out :-). [edit]Oops, you want brighter.[/edit]

    Or you can read from the frame buffer, just don't try and call glReadPixels() many times per frame if you're wanting the destination pixel colour. It's very slow.
    Last edited by zacs7; 12-02-2008 at 12:44 AM.

  4. #4
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Heh thanks Bubba, I understood this much already

    zacs:
    GL_SRC_ALPHA, GL_ONE should theoretically be (Cs * As) + Cd, right? In which case I'm pretty sure it should work.

    My test code is the following:
    Code:
    glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT);
    glDisable(GL_DEPTH_TEST);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    glColor4f(1,1,1,.19f); //.19f just on the offchance that overflow mucks things up. 0.2f has same result.
    
    drawUntexturedSquareAtOffset(0);
    drawUntexturedSquareAtOffset(0.1);
    drawUntexturedSquareAtOffset(0.2);
    drawUntexturedSquareAtOffset(0.3);
    drawUntexturedSquareAtOffset(0.4);
    What I expect to see is 5 overlapping squares spaced 0.1 apart, with the overlapping region going progressively from near-black to near-white as I move from left to right. While the squares do show up and the overlap gets progressively brighter, it ends at a dark gray color instead of white. The same happens if I use glColor4f(0.2,0.2,0.2,1).

    If I use glColor4f(0.4,0.4,0.4,1) then it simply reaches the 'max' dark gray value on the 2nd or 3rd square and remains at that color for the 4th and 5th. However if I use glColor4f(0.7,0.7,0.7,1) then it seems to saturate at a higher brightness, all the way up to (1,1,1,1) where everything is saturated at white.

    If I add either of the following lines, while setting glColor4f(0.2,0.2,0.2,1):
    Code:
    glTexEnvi(GL_TEXTUER_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); //default GL setting
    or
    glTexEnvi(GL_TEXTUER_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
    or
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    GL_ADD causes it to hit white on the 4th square (i.e. early), but GL_REPLACE seems to give the desired/expected result. What I don't understand is why GL_MODULATE causes the color to hit saturation at a dark gray. I don't have any lighting enabled, and nothing else is rendered to the screen.


    I really gotta get this sorted out, it's driving me nuts. Thoughts please?
    Last edited by Hunter2; 12-02-2008 at 12:28 PM.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  5. #5
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    I still don't know what was wrong. But, I created a new project, and rewrote the damn thing while testing it line by line, and it worked. *shrug*
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 05-04-2007, 01:09 AM
  2. Linking OpenGL in Dev-C++
    By linkofazeroth in forum Game Programming
    Replies: 4
    Last Post: 09-13-2005, 10:17 AM
  3. OpenGL Window
    By Morgul in forum Game Programming
    Replies: 1
    Last Post: 05-15-2005, 12:34 PM
  4. OpenGL .dll vs video card dll
    By Silvercord in forum Game Programming
    Replies: 14
    Last Post: 02-12-2003, 07:57 PM
  5. opengl code not working
    By Unregistered in forum Windows Programming
    Replies: 4
    Last Post: 02-14-2002, 10:01 PM