boostworthyisryantaylor

FP10: Setup, Pixel Bender, and Shaders

The beta of Flash Player 10 has recently arrived and if you haven't been experimenting with it, you are definitely missing out. In order to start publishing for FP10, you will need to start by downloading a recent Flex 3 SDK build (May 15th, 2008 or later). Once you have downloaded a recent nightly build of the SDK, go ahead and extract it and copy the folder to the Flex Builder 'sdks' directory. Now you are ready to get setup in Flex Builder; here is the way that I have had success doing so:

1.) Create a new ActionScript project.

2.) In the area that allows you to select the SDK version that you would like to use, click the 'Configure Flex SDKs...' link.

3.) Add a listing for the nightly build that you recently copied into the Flex Builder 'sdks' directory.

4.) Back at the previous window, go ahead and select that SDK as the one that you would like to target for your project.

5.) In the build path window, toggle over to the 'Library path' tab and remove the 'playerglobal.swc' listing under the SDK if one exists.

6.) Click the 'Add SWC' button and browse to the nightly build SDK directory. From there, browse to 'frameworks/libs/player/10/' and select the 'playerglobal.swc' file.

7.) Once added, click the arrow next to 'playerglobal.swc' so that you can see it's settings. Double-click 'Link Type' and set it to 'External' if it isn't already.

8.) Finish setting up your new project.

9.) Once the project is setup and ready to go, navigate to the 'Project > Properties > ActionScript Compiler' window and make sure that you are targeting Flash Player version '10.0.0'.

10.) Last, but not least, make sure that your launcher settings are set to launch your SWF file directly rather than the HTML wrapper.

If you have a hex editor handy, you can confirm that your SWF file is being compiled for FP10 by examining the fourth byte (it should be '0A'). The big problem that currently exists at the moment is that code completion works for new classes (such as 'Shader' for instance), but not new properties of existing classes from FP9 (such as the 'z' property of 'Sprite'). What is strange is that I was able to create a hybrid SDK using some of the lib files from an early release of ***** *** and have full code completion and everything. With the latest builds, this trick no longer works. Interestingly enough, Matt Chotin notes that their recent changes may prevent full code completion in Flex Builder 3 for FP10 from ever working from here forward, but will undoubtedly be resolved in Flex Builder 4. Hopefully they will either further revise the SDK or release a patch for Flex Builder 3 that resolves this issue. That aside, you can still develop for FP10 using the downloadable documentation that Adobe has made public.

Assuming that you are setup and ready to go at this point, one of the first things that you might be interested in trying out is the use of a Pixel Bender file in ActionScript. Make sure that you have the latest version of the Pixel Bender Toolkit from Adobe Labs since a lot has changed since the early AIF Toolkit release. Go ahead and launch the toolkit. Before getting started, there are a couple of very nice documents that I highly recommend you read under the help menu (the spec and tutorial). If you are new to programming pixel shaders, those documents will help you wrap your head around the concepts and get you started with the new language.

If you have been experimenting with Pixel Bender since the early days when it was known as Hydra, one of the first things that you will need to note is the now mandatory meta data after the kernel defintion as seen in my simple color filter example below.

CODE:
  1. <languageVersion : 1.0;>
  2. kernel ColorFilter
  3. <   
  4.     namespace : "AIF";
  5.     vendor : "Ryan Taylor";
  6.     version : 1;
  7.     description : "Simple color filter example.";
  8. >
  9. {
  10.     // Uncomment this for testing in the toolkit using an image file.
  11.     //input image4 image;
  12.  
  13.     output float4 result;
  14.  
  15.     parameter float4 color
  16.     <
  17.         minValue:float4(0, 0, 0, 0);
  18.         maxValue:float4(1, 1, 1, 1);
  19.         defaultValue:float4(0, 0, 0, 1);
  20.     >;
  21.  
  22.     void evaluatePixel()
  23.     {
  24.         result = color;
  25.     }
  26. }

What this shader does is simply set all output pixels to a given R, G, B, and A value based on a float of 0.0 to 1.0 for channel (later interpolated to 0 to 255). If you were to run and test this script in the toolkit, you would want to uncomment that input line that I have commented out and load an image in. Otherwise, no pixel region will be defined and you won't be able to see your changes to the sliders in the right panel. By the way, if you are new to this stuff, notice how you define a parameter with a minimum, maximum, and default value, then the corresponding slider is automatically created for you when you run script so that you can test changes to the value in real time. Pretty cool stuff.

Go ahead and save the script as a 'pbk' file to a sample project; something like './src/filters/ColorFilter.pbk' will do nicely. Now, to get the filter out of the toolkit and into Flash, you need to export the byte code. To do this, first make sure that 'Turn on Flash Warnings and Errors' is enabled under the 'Build' menu. Next, under the 'File' menu select 'Export Pixel Bender Byte Code Filter for Flash' and save the file as something like './assets/filters/ColorFilter.pbj'. You are now ready to use the filter in ActionScript.

You can load or embed the file to get it into ActionScript. Note that the 'mimeType' property is mandatory when embedding as seen below.

ActionScript:
  1. [Embed(source="/../assets/filters/ColorFilter.pbj", mimeType="application/octet-stream")]
  2. protected var ColorFilter:Class;

Since my example is designed to be used as a procedural shader, use of the 'Shader' class and drawing API to create a fill will work best. The workflow is as follows:

ActionScript:
  1. // Create a new shader for representing the embedded filter.
  2.            
  3. var shader:Shader = new Shader(new ColorFilter());
  4.            
  5. // The parameters that were defined in the Pixel Bender
  6. // script can be dynamically accessed by name and index.
  7. // For instance, to change the R channel to 100% (255) and
  8. // G and B to 0% (0), you would do the following:
  9.            
  10. shader.data.color.value[0] = 1;
  11. shader.data.color.value[1] = 0;
  12. shader.data.color.value[2] = 0;
  13.  
  14. // The alpha channel is configured to be 1.0 by default in
  15. // the script, however I am showing it here for the sake
  16. // of example:
  17.            
  18. shader.data.color.value[3] = 1;
  19.            
  20. // Now create a display object for drawing the shader
  21. // as a fill.
  22.            
  23. var texture:Sprite = new Sprite();
  24. texture.graphics.beginShaderFill(shader);
  25. texture.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
  26. texture.graphics.endFill();
  27.            
  28. // Lastly, add the display object to the display list.
  29.            
  30. addChild(texture);

And here is a basic demonstration of the shader being animated. This example simply cycles through the color spectrum:

ActionScript:
  1. package
  2. {
  3.     import flash.display.Bitmap;
  4.     import flash.display.BitmapData;
  5.     import flash.display.Shader;
  6.     import flash.display.Sprite;
  7.     import flash.events.Event;
  8.  
  9.     public class Main extends Sprite
  10.     {
  11.         private const DELTA_OFFSET:Number = Math.PI * 0.5;
  12.        
  13.         protected var _bitmapData:BitmapData;
  14.        
  15.         protected var _shader:Shader;
  16.        
  17.         protected var _texture:Sprite;
  18.        
  19.         protected var _delta:Number = 0;
  20.        
  21.         [Embed(source="/../assets/filters/ColorFilter.pbj", mimeType="application/octet-stream")]
  22.         protected var ColorFilter:Class;
  23.        
  24.         public function Main()
  25.         {
  26.             init();
  27.         }
  28.        
  29.         protected function init():void
  30.         {
  31.             _shader  = new Shader(new ColorFilter());
  32.             _texture = new Sprite();
  33.            
  34.             addChild(_texture);
  35.            
  36.             addEventListener(Event.ENTER_FRAME, onEnterFrame);
  37.         }
  38.        
  39.         protected function renderShader():void
  40.         {
  41.             _texture:graphics.clear();
  42.             _texture.graphics.beginShaderFill(_shader);
  43.             _texture.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
  44.             _texture.graphics.endFill();
  45.         }
  46.        
  47.         protected function onEnterFrame(event:Event):void
  48.         {
  49.             _shader.data.color.value[0] = 0.5 + Math.cos(_delta - DELTA_OFFSET) * 0.5;
  50.             _shader.data.color.value[1] = 0.5 + Math.cos(_delta) * 0.5;
  51.             _shader.data.color.value[2] = 0.5 + Math.cos(_delta + DELTA_OFFSET) * 0.5;
  52.            
  53.             _delta += 0.1;
  54.  
  55.             renderShader();
  56.         }
  57.     }
  58. }

This is only scratching the surface of Pixel Bender and it's usage. There are four ways total that you can use a Pixel Bender script.

a.) As a filter (using 'ShaderFilter' with 'BitmapData.applyFilter' or 'DisplayObject.filters')
b.) As a blend mode
c.) As a fill (as demonstrated)
d.) As a number cruncher (using 'ShaderJob')

Most of those use cases are obvious, however the last one is shaping up to be the most powerful as Tinic notes in his specifications and implementation post. Using the 'ShaderJob' class, you can execute a Pixel Bender script and listen for an event to be dispatched when it has completed.

In the weeks to come, I will post some more advanced examples of Pixel Bender and it's various uses, as well as demonstrate the psuedo 3D support and invaluable 'drawTriangles' method that has been added to the drawing API.

No comments yet. Be the first.

Leave a reply

*
To prove you are human (not an imperial spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word