In my ActionScript 3.0 Image Effects book I have a chapter in which I discuss Pixel Bender and demonstrate how to create a blending mode for the Flash Player. I also suggest the possibility of rewriting the standard Flash Player blend modes so that a percent parameter might be supported, as you find in Photoshop. Then you could apply a multiply blend mode at 50% as opposed to always 100%. In a previous chapter in the book I present the blending mode formulas to make doing that easier.
So I finally took my own suggestion :) I have written Pixel Bender shaders not just for the standard Flash Player blend modes (multiply, screen, overlay…), but for the standard Photoshop blend modes as well (color dodge, vivid light, hue…). Here’s an example of them at work:

I incorporated the blend modes into the aether effects library. To apply one of these blend modes at runtime, you need to either embed the shader byte code in the SWF or load in the shader at runtime. Embedding would look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package {
import aether .blendModes .HardMixBlendMode ;
import aether .blendModes .ShaderBlendMode ;
import flash.display.Bitmap;
import flash.display.Sprite;
[SWF (width=400 , height=602 )]
public class EmbeddingBlendMode extends Sprite {
[Embed (source= '/assets/hardMix.pbj', mimeType= 'application/octet-stream')]
private static const HardMixKernel :Class;
[Embed (source= '/assets/hydrant.jpg')]
private static const ForegroundImage :Class;
[Embed (source= '/assets/fungus.jpg')]
private static const BackgroundImage :Class;
public function EmbeddingBlendMode () {
var backgroundImage :Bitmap = new BackgroundImage () as Bitmap;
addChild(backgroundImage );
var foregroundImage :Bitmap = new ForegroundImage () as Bitmap;
addChild(foregroundImage );
ShaderBlendMode .setShaderClassPath (this);
foregroundImage .blendShader = new HardMixBlendMode (.5 ).shader ;
}
}
} |
In this case, the shader byte code is embedded into this class, and so I need to tell the ShaderBlendMode class where to find the shader. This is done through the static setShaderClassPath() method. All blend mode shaders will then look to this class for the byte code. By default, each BlendModeShader child class has an expected name of the shader that is assigned to a static shaderClass property. For HardMixBlendMode, it is “HardMixKernel”. For AddBlendMode it is “AddKernel”. Etc. So here in this class I embed the byte code with the class name HardMixKernel. If I wanted to use a different name, I could assign a new value to HardMixBlendMode.shaderClass.
Finally, I need to assign the actual Shader instance to the blendShader property of the bitmap, and this can be accessed through the shader property of a BlendModeShader instance. Since I am not looking to alter the 50% hard mix blend, I do not even need to save a reference to the blend mode shader, I just assign it directly to the bitmap.
If you are not embedding the byte code, you will need to load it at runtime. The following code does that (though I still embed the images just to save space here to focus on the blend mode code — if you are not using the mxmlc compiler obviously you will need to load the images or use another type of display object).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package {
import aether .blendModes .HardMixBlendMode ;
import aether .blendModes .ShaderBlendMode ;
import flash.display.Bitmap;
import flash.display.Sprite;
[SWF (width=400 , height=602 )]
public class LoadingBlendMode extends Sprite {
[Embed (source= '/assets/hydrant.jpg')]
private static const ForegroundImage :Class;
[Embed (source= '/assets/fungus.jpg')]
private static const BackgroundImage :Class;
private var _blendMode :ShaderBlendMode ;
public function LoadingBlendMode () {
var backgroundImage :Bitmap = new BackgroundImage () as Bitmap;
addChild(backgroundImage );
var foregroundImage :Bitmap = new ForegroundImage () as Bitmap;
addChild(foregroundImage );
ShaderBlendMode .shaderFilePath = "/pbjs/";
_blendMode = new HardMixBlendMode (.5 , foregroundImage );
}
}
} |
In this case I must specify through the static shaderFilePath where the shader will be loaded from. Just as with the shaderClass property, there is a shaderFile static property of each ShaderBlendMode that determines the name of the shader file to load. By default, the HardMixBlendMode uses “hardMix.pbj”. The MultiplyBlendMode uses “multiply.pbj”. I hope the pattern is obvious :). If you want to rename the shader file, you simply have to update the shaderFile value for the associated class.
One of the cool things about these blend modes is that if you assign a display object as the second parameter, as I did in this example, then the shader will reapply itself to the display object if its percentage ever changes (by default in the Flash Player, a shader is copied to the display object, there is no object reference that remains). So if you wanted to change the percentage of the blend mode applied, you would simply need to have:
1
| _blendMode.percent = 0.8; |
The display object would then be automatically updated with the new shader value.
To use these shaders, simply grab the aether effects library. There is a precompiled SWC as well as the original source for both the ActionScript and the Pixel Bender shaders. There are no dependencies in the shader blend modes on other pieces of the aether library, so if all you want is to use a blend mode you don’t get any excess baggage along with it.