Mini-tutorial: Additive Blending

I have been getting a few requests lately about the hows and whys of additive blending so I thought I would whip up a quickie little tutorial to get those interested parties on the path to easy glowiness. But first, the standard disclaimer.

I AM NOT A GOOD TEACHER!!! Here is why. I dont really know OpenGL. I dont know much about the limitations of JOGL either. What I do know is that with Processing, I can make OpenGL calls that can do great things but as for why they work or why they might be better or why I didnt optimize them further, the simple answer is that I am learning just like the rest of you. So please keep these 2 points in mind when you read the rest of this post.

1) If you have problems with the source code, please research the answer yourself. I wont be able to help you understand why you are getting an error with Processing v.123 on Windows running Vista with 2 webcams attached and Java version 1.4 with a cat on your lap and the right mouse button pressed. I would probably just refer you to the Discourse section of Processing.org.

2) If you can improve this code or help me understand more about why it works, please post your comments here instead of emailing me so that others can benefit from your knowledge. Im sure there are ways to make the following info much tighter and stronger… so chip in your 2 cents so we can all be a bit richer.

On the left is a screengrab from the supernova project without any blending. On the right, I have added additive blending and disabled the depth test. Suddenly, the orb glows are more glowy and the overlap issue goes away entirely. Lets look at the code.

First, you will need to make a new PGraphicsOpenGL and GL object. Before you can do this, you need to make sure you import the proper libraries. Stick this code in with your other import statements if you have any. The top one makes sure you can use the OPENGL renderer specified in your size() method, and the second is the JOGL stuff you will need.

import processing.opengl.*;
import javax.media.opengl.*;

Then you make your PGraphicsOpenGL and GL objects.

PGraphicsOpenGL pgl;
GL gl;

In your setup code, you will need to define these pgl and gl objects so put in the following after your size() method.

pgl = (PGraphicsOpenGL) g;
gl = pgl.gl;

Almost there! The only thing left is to do the additive blending magic. It is soooo easy! You will kick yourself. Stick this at the beginning of your draw method.

pgl.beginGL();

// This fixes the overlap issue
gl.glDisable(GL.GL_DEPTH_TEST);

// Turn on the blend mode
gl.glEnable(GL.GL_BLEND);

// Define the blend mode
gl.glBlendFunc(GL.GL_SRC_ALPHA,GL.GL_ONE);

pgl.endGL();

Voila! Glowy good times. The BlendFunc takes several parameters. Check here for a sample as to why I dont bother getting too invested in the ‘why’ this works.

Go and glow.

UPDATE (April 4, 2007)…………………………………………….
Got a correction from up high. Mr. Fry informs us that:
pgl = (PGraphicsOpenGL) g;
gl = pgl.gl;

should go inside draw(). in fact, it should just look like:

void draw() {
pgl = (PGraphicsOpenGL) g; // g may change
gl = pgl.beginGL(); // ho ho fancy

// blah blah blah
}

because in some (rare) cases, ‘g’ will have changed, and in others, the
‘gl’ object associated may also have changed (so beginGL() is set to
return the gl object to insulate you from such cases).

Danke Mr. Fry.

14 Responses to “Mini-tutorial: Additive Blending”

  1. Simon says:

    Thanks for sharing your tips Robert. That’s really cool!
    I’ve begun to do some research on additive blending just after seeing your so beautilfull vid with trentemoller… (a lot of time, believe me. Not for the trick but because I think it’s the very first time I’ve seen something like that done in processing. I really love it!…. that’s it for the sentimental part, snif).

    For people who don’t like the opengl documentation there is another fonction very usefull.

    glBlendEquation allow you to specify how the colors are blended (GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, GL_MIN, GL_MAX).

    Thank’s again, I finally take a look to opengl through java and I think I really like that. It look really promising.

    Take care. And keep inspirate me ;-) .

  2. Edwin says:

    I’d also like to thank you for sharing this with us!
    I found your website recently after a friend of mine recommended processing to me and I started to make some experiments with it. Man your work has been so inspiring! When I saw that piece in which you use the Boards of Canada song I was amazed! What a nice pair :)

    I hope you can visit my site, nothing too fancy… but I managed to make a little something with motion detecion and show it in public for the first time.

    I hope my english is not that bad, heh ;)

    Thanks again, and keep up this beautiful work!

  3. JohnG says:

    I was playing around with similar stuff a while back, and found a way to mix solid 3D stuff with additive blending.

    With gl.glDisable(GL.GL_DEPTH_TEST); you can’t have glowing things partly hidden behind solid things, yet without it you have to mess around with z-sorting.

    However there’s a third way: gl.glDepthMask(false); this disbales writing anything to the depth buffer, so your glowing objects can’t hide things behind them, *but* they can hide behind other 3D objects. Just set it back to true once you’ve finished drawing the glowing parts.

  4. flight404 says:

    Wonderful additions. I didnt know about glBlendEquation or glDepthMask. Thanks for the info!

  5. flight404 says:

    Here is a question for you random geniuses… should the glEnable and glBlendFunc calls exist between pgl.beginGL() and pgl.endGL()? It seems to work fine without them. Also, JohnG, when I play with the glDepthMask, the 3D shapes I draw never clear. I tried playing with glClear but no go. Suggestions?

  6. Aaron says:

    Hey Robert,

    There is a really good explanation of all the math behind alpha blending in this 3 part blog series:

    http://blogs.msdn.com/etayrien/archive/2006/12/07/alpha-blending-part-1.aspx
    http://blogs.msdn.com/etayrien/archive/2006/12/12/alpha-blending-part-2.aspx
    http://blogs.msdn.com/etayrien/archive/2006/12/19/alpha-blending-part-3.aspx

    Part 3 is where they get into additive blending specifically, but you’ll have a much clearer idea of how different blending modes work (and how the depth buffer fits in) after reading the series.

  7. flight404 says:

    Great links Aaron. Thanks!
    And Gilbert, I am going to delete your two comments and add your emailed explanation in a separate post. I didnt see any character limit for comments so not sure what else to do except post it separately. Thanks for taking the time to write it up.

  8. JohnG says:

    Not sure what you mean by “3d shapes never clear” but here’s a pseudo code example of how I use it:

    //draw starts…

    //Draw solid 3D objects

    pgl.beginGL();
    gl.glDepthMask(false);
    gl.glBlendFunc( GL.GL_SRC_ALPHA, GL.GL_ONE );
    pgl.endGL(); // I think you can do it like this…
    // draw blended objects;

    pgl.beginGL();
    gl.glDepthMask(true);
    gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
    pgl.endGL();

    //draw more 3D if you want, but will always be “in-front-of” the transparent parts

  9. Hugues says:

    I’m trying to make the same king of glow/blending effect but using a sphere as supporting structure. How is it possible ?
    I mean, using a gradient orb works when mapped on a “simple” square, but what about a 3D sphere ?

  10. flight404 says:

    John, this is what I meant about the 3D shapes never clearing.
    http://www.flickr.com/photos/flight404/443162524/
    http://www.flickr.com/photos/flight404/443166441/
    I am drawing a box() and it is rotating around in the space that is filled with a few audio responsive glow images. The box redraws on itself over and over leaving this (admittedly interesting) unintended effect. This only happens when I draw the box before the glows. If I do it the way you specified, it works as you said it would. But if I switch it up so the blended objects draw last and the 3D shapes draw first, I get the odd effect. Id like to figure out how to capitalize on it though. I like the images that I put up on flickr.

  11. flight404 says:

    Huzzah, I figured it out. I just put in gl.glClear(GL.GL_DEPTH_BUFFER_BIT) before drawing the solids (which I an drawing before the blended stuff) and I get the expected results. Gotta go slow though… worried I might fall into the lens flare / page curl trap and end up overusing something because it is pretty and easy. But still, I love it!

  12. [...] Since yesterday I’m testing the texture implementation of Andreas’ surface library (thanks for sending the early version) in combination with various blending modes (already documented and described by Robert Hodgin a few weeks ago – Mini-tutorial: Additive Blending pt. 1 / pt. 2). After increasing the Eclipse startup memory settings, I was able to load even highres textures and to write highres stills using the TileSaver class by Marius once again. [...]

  13. [...] all manner of distractions » Blog Archive » Mini-tutorial: Additive Blending (tags: Programming howto Graphics blog design Java development tutorials generative processing OpenGL tutorial) Visit my other sites: Photo Gallery | Insane in the Membrane | Main website « links for 2008-10-29 [...]

  14. [...] mode done, through openGL render from processing, I followed a clear but not too explanatory tutorial on the flight404 blog. The additive blending does achieve a more interesting composite but also results in aliasing of [...]