If that means nothing to you, you might as well browse on… Geekspeak ensues! If it does, welcome to my short tutorial on what I last posted about, and specifically how to plug Pixel Bender filters into Adam Atomic‘s wonderful Flixel framework for Flash. Also apologies for the temporary blog theme, as I managed to screw up my previous stylesheet with no backup. Will do something when I have more time, I promise!
Anyway, I’ll leave the Pixel Bender Toolkit stuff itself to other people (there’s loads of tutorials and free sample code for writing the filters themselves…)
Just remember to alter your project properties to build for at least Flash Player 10 0 0 (right click on the project icon in the project explorer and choose Properties, you’ll find the setting in the Actionscript Compiler area, where you set your Flex SDK.)
Once you’ve created your compiled ‘.pbj’ filter in the Toolkit (from a ‘.pbk’, the code file), and stuck it somewhere suitable like your ‘data’ directory, the main problems I had were how to:
1. Load the filter in Flixell
You’ll need these includes:
import flash.display.Shader;
import flash.filters.ShaderFilter;
Make sure to use ‘octet-stream’ encoding. Embed it as a Class:
[Embed(source = "/../data/filter.pbj", mimeType = "application/octet-stream")] private var FilterCode:Class;
…and plug it into the Shader() constructor:
var coolShader:Shader = new Shader(new FilterCode());
2. Access your filter’s paramters:
You can access any of the parameters you defined in Pixel Bender toolkit like this:
coolShader.data.paramName.value
(*paramName being your parameter name, not the word paramName!)
Important to note that even if the parameter is a single float, you must pass the Shader a one-parameter array. So for example, my light position, which is a float3 of x,y and z would be accessed as follows:
coolShader.data.lightPosition.value=[x,y,z];
coolShader.data.lightAttenuation.value=[1.0];
3. [Optionally] Add additional inputs to the filter (by default, the input is also the output, but what if you need a fog texture, for example…)
Just refer to it as you would a parameter, only pass BitmapData in, and use the ‘input’ property instead of the ‘value’ one:
coolShader.data.fogMap.input = FlxG.addBitmap(ImgFog,false);
Obviously if your PB filter doesn’t need a second input (like a desaturation filter, for example), you can skip this step. Make sure you name your input the same as the input parameter in your PB code.
4. Apply the filter to the buffer
The Pixel Bender shader itself has to be wrapped up in a way Flash can understand. This is what the ShaderFilter class is for. You create one by passing the Shader to it. Add this to your setup code:
var coolFilter:ShaderFilter = new ShaderFilter(coolShader);
And then you can apply this filter as you would a normal Flash filter, and there are three ways to do this. I’m actually using the supposed slowest of the three apparently, but it seems to be the fastest in my results!
In your ‘PlayState’ add the following to an overridden postProcess() function:
FlxG.buffer.applyFilter(FlxG.buffer,new Rectangle(0,0,screenWidth,screenHeight),new Point(0,0),coolFilter);
The point is for the top-left, and the rectangle just specifies the bounds.
NOTES:
If you only want to store one reference, and aren’t switching shaders on an object, you can actually access the Shader parameters through the ShaderFilter, like so:
coolFilter.shader.data.fogMap.input = FlxG.addBitmap(ImgFog,false);
I’ve experimented with adding the filter in this way too, just like Flash’s in-built filters:
myGameState.filters=[coolFilter];
In Flixel, this works but operates on the post-transformed pixels (ie post-Flixel-scaling), whereas applying it to the BitmapData in postProcess() is pre-scale.
Make sure you don’t include loops in your .pbk code as they’re not supported in Flash, and avoid conditionals where possible, especially when sampling a texture within one.
BIG QUALIFIER:
I’m a pretty crappy coder, and have never posted this kind of thing before. Hope it was in some way helpful! Feel free to point out any errors which there are no doubt quite a few of… Thanks also to others who paved the way for this tutorial such as Salt and various other helpful bloggers.