Just in time for Halloween, today’s tutorial covers Corona blend modes and how they can be used to achieve creative visual effects within your app, all in the convenient “one line of code” style that is utilized in many of Corona’s APIs. Blend modes are useful for numerous visual effects, and designers experienced in applications like Photoshop should be familiar with them. For those who don’t know what blend modes are, please continue reading.

Throughout this tutorial, we’ll be using two Halloween-themed images: a spooky swamp and some wisps. If you wish to practice blending effects as you follow this tutorial, you may download the source images here.

Layers and Pixels

Just like most graphics applications and development languages, Corona utilizes layers to arrange visual objects in an ordered z-index from back to front. Layers are referred to as display groups in Corona but their usage is exactly the same.

Layering the wisps atop the background yields the following predictable result…
As you can see, each pixel that comprises the forward objects (wisps) overlaps anything behind it, rendering the pixel(s) behind effectively null. This is known as the “Painter’s Algorithm” — the analogy being that with physical paint on a physical canvas, every stroke of paint goes on top of something else on the canvas.

About Visual “Blending”

While basic layering is a useful and necessary technique in app development, it’s rather limiting in terms of creative visual effects. Thus, most graphic applications — and now Corona too — allow you to utilize blending across layers.

At the core level, blending is a method to combine (blend) overlapping pixels across multiple layers using mathematical algorithms. Instead of a forward pixel simply overlapping and hiding the pixel(s) behind it, blending allows you to factor multiple pixels into the final visual result.

Using the Painter’s Algorithm analogy, imagine that every stroke of physical paint that you apply to the canvas changes (blends) with whatever is currently underneath. As you apply more paint in multiple layers, the topmost layer blends with the current result underneath. This is essentially how blending works on a digital painting canvas, except that digital blending effects appear differently than physical paint on a canvas.

Expanding on the digital environment, blending occurs on all three color channels — red, green, and blue (RGB). I won’t go into detail about the color channels except to note (for beginners) that each channel must be in the range of 0 to 255, with 0 being “none” and 255 being “maximum” in regards to how much of that channel is “mixed” into the final color. An RGB value of (0,0,0) will produce pure black, while a value of (255,255,255) will produce pure white. A detailed explanation and reference site can be viewed here.

For purposes of this tutorial, you must only remember the range of 0-255 for each color channel to see how each blend mode affects each channel and thus the final color of that pixel.

object.blendMode

To apply a blend mode to an object in Corona, you simply use the blendMode parameter and specify one of the following three options: add, multiply, screen, or normal. For example…

wisps.blendMode = "add"

I’ll discuss each of the first three blend modes in detail below. The “normal” blend mode (default) is effectively no blend mode — use it to set or revert a display object to standard visual behavior.

Note that you must apply blend modes on a per-object basis, similar to object:setFillColor(). You cannot apply a blend mode to an entire display group in one line of code. If you wish to accomplish such a task, you can loop through the display group’s child objects and apply a blend mode to each of them.

Blend Mode “add”

The add blend mode is useful for glowing visual effects like fire, lasers, exaggerated lighting, etc. Also known as linear dodge in most graphic applications, it simply adds the value of each color channel across layers. Here is a basic example of additive blending:

Let’s get technical now! The RGB values for the corresponding objects are as follows:

background:      ( 34, 34, 44 )
red circle:      ( 255, 51, 51 )
green circle:    ( 0, 153, 51 )
blue rectangle:  ( 102, 153, 204 )

With each object set to blendMode=“add”, Corona’s OpenGL engine simply adds the channel values for each pixel.

Let’s do some basic math: for the left-side portion of the red circle that is isolated by itself, factor in the background color only since that’s the underlying color behind the red circle.

R: 34 + 255 = 289
G: 34 + 51  = 85
B: 44 + 51  = 95

The R (red) value exceeds 255 (the maximum limit) and thus it will be capped at 255. The final yielded RGB color value thus becomes (255,85,95), in contrast to the red circle’s “self” RGB value of (255,51,51). Compare the two images and notice that the blend-enabled red circle is slightly lighter than the normal red circle.

Let’s inspect a more complex section: the small yellow portions where the red and green circles intersect, above and below the blue rectangle.

R: 34 + 255 + 0   = 289
G: 34 + 51  + 153 = 238
B: 44 + 51  + 51  = 146

Sum the values for each channel including the background, cap any value at a maximum of 255, and the final RGB value becomes (255,238,146).

How does the add blend look in our Halloween scene? With the wisps set to blendMode=“add”, the effect is considerably more creative! The white wisps shine intensely and the darker wisps (formerly dark purple) glow with a more subtle effect (the result of a darker shade being added to the underlying pixels).

Although not illustrated in this tutorial, if there are any black pixels in an additive blend, they will effectively disappear (become fully transparent). Why? Because their RGB values are (0,0,0) and thus nothing is added to the pixels which reside behind. What shows through is only the pixels behind, unaffected by the blend.

In summary, the add blend mode simply adds each color channel and yields the final value, capped at 255 (pure white). This is why additive blending is useful for bright, colorful, enhanced effects such as lasers, fire, flashes, etc.

IMPORTANT NOTE:  While we are inspecting the math at a technical level to fully understand what’s happening, you as the developer/designer do not need to calculate this in your Corona app. Corona’s graphics engine handles everything for you on the fly. The only “calculation” you must perform is how to design your blend-enabled objects so that they provide the desired visual effect when blending is enabled.

Blend Mode “multiply”

Although the name is somewhat misleading, the multiply blend mode actually makes objects behind darker, and thus it’s useful for creating shadow effects.

Instead of adding the color channel values, the multiply blend mode (you guessed it) multiplies them. This can result in RGB channel values as high as 65025 (255*255), which you’d then expect to be capped at 255 like the channels in the additive blend. So why does a multiply blend darken what’s behind it? Because in addition to multiplying the pixels, the final result is divided by 255 as well. Here’s the formula:

resulting color = ( top color * bottom color ) / 255


Let’s inspect the values for our test objects again:

background:      ( 34, 34, 44 )
red circle:      ( 255, 51, 51 )
green circle:    ( 0, 153, 51 )
blue rectangle:  ( 102, 153, 204 )

Now let’s do the math on the left-side portion of the red circle (look closely, it’s dark now!).

R: ( 34 * 255 ) / 255 = 34
G: ( 34 * 51 )  / 255 = 6.8
B: ( 44 * 51 )  / 255 = 8.8

You can see how the formula actually yields lower values (and thus darker, visually) because of the division factor performed post-multiplication. The effect of black pixels must be mentioned as well. Using black (0) in a multiply blend will always yield black, because the factor of 0 in the multiplication part of the equation yields 0 in every instance, hence pure black as a visual result.

And here is our Halloween scene with the wisps set to blendMode=“multiply”

You can see that all wisps now darken the region behind them. Certainly this isn’t a desirable effect in this scene, but it exhibits how the multiply blend can be used for shadow effects.

And what happened to the white wisps? Using white (255) in an multiply blend effectively makes those pixels invisible. The color channels are multiplied by 255 and then divided by 255, canceling out both factors and leaving only the underlying pixels showing through.

Blend Mode “screen”

The screen blend mode can be used to lighten underlying regions without lightening the darkest areas excessively. The algorithm for this blend mode is complicated: the channel values are negated, multiplied, and then negated again. Here’s the formula:

resulting color = 255 - ( ( ( 255 - top color ) * ( 255 - bottom color ) ) / 255 )

This yields an inverse effect of the multiply blend, and thus a lightening effect. At the same time, while the effect can be similar to the add blend, it’s not as extreme and you will not get the blown-out bright colors that can occur with an additive blend.

Because the formula for the screen blend is complex, and you won’t need to actually calculate any of this in your code, I won’t work through the math. Instead, observe the actual effect of the screen blend in our Halloween scene…

This is a pleasant and convincing effect for the most part, especially on the lighter wisps. Note that the effect isn’t as drastic as the additive blend. However, the darker wisps lose a bit of emphasis and those might be better served by an additive blend.

In Summary

Blend modes in Corona can be a powerful tool in the proper circumstances. Implementing them is simple — just one line of code — and Corona’s graphics engine does all of the math for you, dynamically and below the surface. Ultimately, which blend modes you utilize will depend on your scene and the effect(s) you wish to achieve. If you have further questions, please join the discussion below. Happy Halloween!

  1. Nice posting. All Corona blend modes are already available with Kwik 2. You set a blend mode in a Photoshop layer (or layers), Kwik reads it and write the correct Lua code for the images. Hopefully other modes will come in the next Corona bits.
    Alex

  2. Brent Sorrentino says:

    Thanks for your input Alex! I should also note that the “add” blend mode is supported in Particle Candy. It seems that the other modes (“multiply” and “screen”) are not supported by P.C. at this time unless their documentation is out of date. In any case, the additive blend is probably the most useful in terms of particle effects, and it’s great that X-Pressive has enabled it.

  3. Great tutorial, Brent! Quick question – are Blend Modes are still restricted to Display Images? Or can we apply a Blend Mode (multiply in particular) to an entire Display Group filled with various images, shapes, etc?

    Thanks,
    David

    • Brent Sorrentino says:

      Hi David,
      At this time, blend modes can’t be applied on a group-wide basis in just one line. But, it should be quite fast to just loop through the group’s children using the “.numChildren” parameter and apply a blend mode to them… I imagine you’re not constantly changing blend modes in “game time”, but perhaps I’m mistaken.

      • Thanks for the quick reply, Brent! Sadly, applying multiply to all the children within my Display Group won’t achieve the effect I’m hoping to accomplish.

        I’m trying to create a night/darkness effect where each of the characters in my game have vision/light source. I was planning on creating a Display Group with a black rectangle in the background, then create white circles on top for each unit. By applying Multiply to the entire Display Group – the darkness would be opaque and the white circles would become transparent. Have any other ideas how I could achieve this effect?

        Thanks!
        David

        • Brent Sorrentino says:

          Hi David,
          If I understand correctly, you want to create the effect of a very dark room (or night environment) and have objects (characters) moving around that have a sort of “flashlight glow” around them? And this glow visually illuminates only the effect around them?

          You might find a working visual solution by darkening the entire background with an overlaying black, 0.7 or 0.8 opacity rectangle. This would allow some background to show through, whether that’s grass, a street, or some terrain.

          Then for the “light sources”, you create a fuzzy (blurred) medium-grey circle which goes between your character(s) and the background. Set this circle to the ADD blend mode, which will provide more “light” depending what it lays over. The lighter the shade of gray (or white) will give more light, while a dark charcoal grey should give a very dim light effect.

          Do you have a graphics program like Photoshop or even something less fancy and overpriced? Most graphics programs feature basic blend modes and you can experiment with them before you code the Corona blend modes. Remember that ADD is usually called “linear dodge” in graphics programs, but it’s exactly the same blend mode. Screen and Multiply are usually the same name.

  4. Hi Brent,

    is there any way to permanently apply one image to another with a blendmode applied? So that you could apply one image to another repeatedly and draw lines / shapes etc with that image (kind of like using an image as a brush on another image) ?

    • Brent Sorrentino says:

      Hi Stephen,
      Just so I understand, do you mean like “painting” a composite collection of “brush strokes”, so that they meld into one, and then using that composite object with a blend mode over something else? Can you describe in detail the kind of app you’re envisioning?

      Thanks, Brent

  5. Stephen Allen says:

    Hi Brent,

    I’m thinking of the scenario where an image is drawn repeatedly onto another image and moved slightly each time to make ‘brush strokes’. For example, the spray tool in the average paint utility. If a blend mode was applied with every draw some pretty cool effects could be made, e.g. using the ‘add’ blend mode to lighten the screen where the player is rubbing his/her finger.

    Someone else mentioned possibly using the display.captureBounds() method but I’m not sure if that would be fast enough for such real-time effects.

    • Brent Sorrentino says:

      Hi Stephen,
      In this case, I think you can just create a “brush stroke” image (like a spatter dot). Then, just layer them atop each other, blending “add” applied to each one. These objects will blend-add atop each other, creating an interesting additive effect. Is this what you had in mind?

  6. So nicely written about blending modes & how easily corona lets us do it!! Anyways Can you pl guide me how to blur the image (the only portions where user touches, real-time) without any lag in performance/faster. Can corona help me making such android app? or I should look into openGL approach? I’m a beginner in corona. Please help me..thanks a tone.

    • Brent Sorrentino says:

      Hi Megha,
      At this time, you can’t blur images in Corona, but this sort of functionality -will- be coming in the upgraded graphics engine that should be entering beta testing before too long. This will allow you to do various “Photoshop” OpenGL filters and effects on images, including blur. I believe it may also allow for a blur just around a touch area, but that functionality may not be available from the very beginning (rather it would be added sometime later than the initial launch of the new graphics engine).

      Here is a short preview:
      http://www.coronalabs.com/blog/2013/05/29/corona-weekly-update-photoshop-style-filter-effects/

      Take care,
      Brent

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>