I’m happy to announce that we’ve added additive blend support to Corona. It’s available starting in Corona daily build #497.

What’s additive blends? It’s a cool way to get glow effects. It’s also known as “Linear Dodge” for the Photoshop buffs among you.

In the rest of this post, I’ll break it down into its gory details with code, math, and pictures.

Whenever you’re doing alpha blends between two different objects, you’re doing compositing. By default, Corona does the standard “normal” blend which is what most of us think intuitively think of when we say blend two objects together, i.e. the painter’s algorithm.

So if you use the following code, which places a transparent PNG on top of a background…

[cc lang=”lua”]local bkgd = display.newImage( “blendmode_bg.jpg” )
local laser = display.newImage( “blendmode_laser2.png” )[/cc]

…You’d get:

For the math buffs among you, the equation for normal blends looks like this:

colorFinal = (colorTop)*(alphaTop) + (colorBottom)*(1 – alphaTop)

Now, there are a ton of possible blend modes. Photoshop has around 2 dozen. It turns out that there’s another way to do blends which is incredibly useful. That’s the additive blend mode (a.k.a. linear dodge for you Photoshop types). This blend mode merely adds the pixel values of two overlapping objects on a per-channel basis (up until saturation):

The blending equation here looks (if the sum exceeds saturation, then the channel just takes on the max value):

colorFinal = (colorTop)*(alphaTop) + (colorBottom)

To do this, you just need to set a new “blendMode” property of the display object:

[cc lang=”lua”]local bkgd = display.newImage( “blendmode_bg.jpg” )
local laser = display.newImage( “blendmode_laser2.png” )
laser.blendMode = “add”
[/cc]

The other value for blendMode is “normal” which is the default.

There are a couple of limitations. This only works on vector and image objects. This does not work on groups. And we’re not supporting fancy things like using masks simultaneously (that will have to wait until we introduce shaders), so your mileage may vary.

Special thanks to Joe Kauffman for sharing some image files for me to use. You can also thank him for guilting me into adding this feature. I know he and several others have been waiting awhile, so I finally found some free time to implement it.

  1. Fantastic! Any chance of adding a subtractive blend mode with the same restrictions? Seems it should just be a duplication of the additive code, with one slight change:

    colorFinal = colorBottom – (colorTop)*(alphaTop)

    This could be useful in certain situations where using a black image with normal blend mode is too limiting.

  2. Where the hell’s X-Pressive?!? Particle Candy needs this update to achieve super awesomeness!!! :)

    Very glad to see this addition!!

    Shoop da woop.

  3. Don’t worry -we are back at our office now, so you can expect a blend mode update within the next couple of days.

    This is indeed a great feature and a huge step forward -thumbs up! We will also provide samples with the next Particle Candy update to show what cool things you can do using additive blend mode.

  4. Great, this is excellent, but what about ‘SCREEN’ blend modes? I would like to make anaglyphing of images, which requires ‘SCREEN’ mode. I currently use it in Flash for my stereoscopic 3D panorama engine at http://www.3d-360.com and would like to port this to Iphone using Corona (as no Flash…)

  5. You should have sent this out on email. Not to late. Do it, all those that have signed up for Corona info and are designers are gonna want to know about this. Me especially. I only found it today, by accident.

  6. Now that this is implemented, wouldn’t adding most of the other common blend modes (i.e. the ones in photoshop) just be a matter of typing in the formulas for each one?

  7. #define ChannelBlend_Normal(A) ((unsigned char)(A))
    #define ChannelBlend_Invert(A) ((unsigned char)(255-A))
    #define ChannelBlend_Lighten(A,B) ((unsigned char)((B > A) ? B:A))
    #define ChannelBlend_Darken(A,B) ((unsigned char)((B > A) ? A:B))
    #define ChannelBlend_Multiply(A,B) ((unsigned char)((A * B) / 255))
    #define ChannelBlend_Average(A,B) ((unsigned char)((A + B) / 2))
    #define ChannelBlend_Add(A,B) ((unsigned char)(min(255, (A + B))))
    #define ChannelBlend_Subtract(A,B) ((unsigned char)((A + B > 8)))
    #define ChannelBlend_Exclusion(A,B) ((unsigned char)(A + B – 2 * A * B / 255))
    #define ChannelBlend_Overlay(A,B) ((unsigned char)((B < 128) ? (2 * A * B / 255):(255 – 2 * (255 – A) * (255 – B) / 255)))
    #define ChannelBlend_SoftLight(A,B) ((unsigned char)((B >1)+64))*((float)B/255):(255-(2*(255-((A>>1)+64))*(float)(255-B)/255))))
    #define ChannelBlend_HardLight(A,B) (ChannelBlend_Overlay(B,A))
    #define ChannelBlend_ColorDodge(A,B) ((unsigned char)((B == 255) ? B:min(255, ((A << 8 ) / (255 – B)))))
    #define ChannelBlend_ColorBurn(A,B) ((unsigned char)((B == 0) ? B:max(0, (255 – ((255 – A) << 8 ) / B))))
    #define ChannelBlend_LinearDodge(A,B)(ChannelBlend_Add(A,B))
    #define ChannelBlend_LinearBurn(A,B) (ChannelBlend_Subtract(A,B))
    #define ChannelBlend_LinearLight(A,B)((unsigned char)(B < 128)?ChannelBlend_LinearBurn(A,(2 * B)):ChannelBlend_LinearDodge(A,(2 * (B – 128))))
    #define ChannelBlend_VividLight(A,B) ((unsigned char)(B < 128)?ChannelBlend_ColorBurn(A,(2 * B)):ChannelBlend_ColorDodge(A,(2 * (B – 128))))
    #define ChannelBlend_PinLight(A,B) ((unsigned char)(B < 128)?ChannelBlend_Darken(A,(2 * B)):ChannelBlend_Lighten(A,(2 * (B – 128))))
    #define ChannelBlend_HardMix(A,B) ((unsigned char)((ChannelBlend_VividLight(A,B) < 128) ? 0:255))
    #define ChannelBlend_Reflect(A,B) ((unsigned char)((B == 255) ? B:min(255, (A * A / (255 – B)))))
    #define ChannelBlend_Glow(A,B) (ChannelBlend_Reflect(B,A))
    #define ChannelBlend_Phoenix(A,B) ((unsigned char)(min(A,B) – max(A,B) + 255))
    #define ChannelBlend_Alpha(A,B,O) ((unsigned char)(O * A + (1 – O) * B))
    #define ChannelBlend_AlphaF(A,B,F,O) (ChannelBlend_Alpha(F(A,B),A,O))

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>