Saturday, January 17, 2009

Pixel Bender Filter in Flash CS4






My first Pixel Bender filter (RGB RAMP)



Today I spent a few hours with Pixel Bender and it is well worth the effort. As you know CS4 was announced recently and packs a pretty substantial list of features, but Adobe is equally impressing developers on the Adobe Labs. One of the newer additions is Pixel Bender. Pixel Bender is essentially a toolkit that is used to develop filters. These filters can be used in Flash 10 and After Effects and allow everyday people to create some very interesting filters.

The running of the filter in Flash CS4 is pretty much identical to an included filter, like the BlurFilter or DropShadowFilter.


Start by opening the Pixel Bender Toolkit, which can be obtained on the Adobe labs


Then create your kernel script by simply copying and pasting the code provided here into the code window of the Pixel Bender toolkit. Pixel Bender Files have the extension pbk.














<languageversion : 1.0;>

kernel QuadBlur
< namespace : "com.pixelbender.filters";
vendor : "RGB Filter";
version : 1;
description : "Creates a basic RGB Pixel Color Ramp";
>

{

input image4 src;
output pixel4 dst;

parameter float red

<

minValue:1.0;

maxValue:15.0;

defaultValue:1.0;

>;

parameter float green

<

minValue:1.0;

maxValue:15.0;

defaultValue:1.0;

>;

parameter float blue

<

minValue:1.0;

maxValue:15.0;

defaultValue:1.0;

>;


void


evaluatePixel()

{


pixel4 p = sampleNearest(src,outCoord());

p.r *= red;

p.g *= green;

p.b *= blue;

dst = p;

}


}</languageversion>



Then export the filter File > Export Kernel Filter for Flash Player and save the Sample.pbj (binary file) file on you desktop.

Now Open Flash and create a new ActionScript 3 document. For a test sample you need to insert an image on the stage and an image for a button inserted as movie clip. Save the new Flash document to your desktop, where you saved the filter file. Once the file is saved import an image that you will apply the filter to.


Click on the following link to see the filter in action. You must have Flash Player 10 installed to view it.



The ActionScript 3 code that I used to import the new sample shader is
shown below.









import adobe.utils.*;

import fl.controls.*;

import flash.accessibility.*;

import flash.desktop.*;

import flash.display.*;

import flash.errors.*;

import flash.events.*;

import flash.external.*;

import flash.filters.*;

import flash.geom.*;

import flash.media.*;

import flash.net.*;

import flash.printing.*;

import flash.profiler.*;

import flash.sampler.*;

import flash.system.*;

import flash.text.*;

import flash.text.engine.*;

import flash.ui.*;

import flash.utils.*;

import flash.xml.*;



var shader:flash.display.Shader;

var timer:flash.utils.Timer;

var loader:flash.net.URLLoader;

var timerInt:uint;

var startBtn:fl.controls.Button;

var image:flash.display.MovieClip;

var shaderFilter:flash.filters.ShaderFilter;









try

{

startBtn["componentInspectorSetting"] = true;

}

catch (e:Error)

{

};

startBtn.emphasized = false;

startBtn.enabled = true;

startBtn.label = "Start Effect";

startBtn.labelPlacement = "right";

startBtn.selected = false;

startBtn.toggle = false;

startBtn.visible = true;

try

{

startBtn["componentInspectorSetting"] = false;

}

catch (e:Error)

{

};



timerInt = 40;

image = new PixelBenderImage();

image.y = 20;

image.x = 25;

addChild(image);

startBtn.addEventListener(MouseEvent.CLICK, this.startEffect);





function restartEffect(arg1:flash.events.MouseEvent):*

{

image.alpha = 0;

initFilter();

return;

}

function startEffect(arg1:flash.events.MouseEvent):*

{

loader = new URLLoader();

loader.dataFormat = URLLoaderDataFormat.BINARY;

loader.addEventListener(Event.COMPLETE, this.loadComplete);

loader.load(new URLRequest("Sample.pbj"));

return;

}





function initFilter():*

{

shader.data.red.value = [20];

shader.data.green.value = [20];

shader.data.blue.value = [20];

shaderFilter = new ShaderFilter(this.shader);

image.filters = [shaderFilter];

image.alpha = 1;

timer = new Timer(timerInt, 0);

timer.addEventListener(TimerEvent.TIMER, this.timerHit);

timer.start();

return;

}

function timerHit(arg1:flash.events.TimerEvent):void

{

var loc2:*;

var loc3:*;

var loc4:*;


if (shader.data.red.value == 1)

{

startBtn.label = "Restart Effect";

startBtn.removeEventListener(MouseEvent.CLICK, this.startEffect);

startBtn.addEventListener(MouseEvent.CLICK, this.restartEffect);

timer.stop();

return;

}

loc2 = shader.data.red.value - 0.1;

loc3 = shader.data.green.value - 0.1;

loc4 = shader.data.blue.value - 0.1;

shader.data.red.value = [loc2];

shader.data.green.value = [loc3];

shader.data.blue.value = [loc4];

shaderFilter = new ShaderFilter(shader);

image.filters = [shaderFilter];

return;

}

function loadComplete(arg1:flash.events.Event):void

{

shader = new Shader(loader.data);

initFilter();

addEventListener(Event.ENTER_FRAME, loop);

return;

}

/*

function onChange(p:Number):void

{

p *= 50;

shader.data.amount.value = [p, p, p];

image.filters = [filter];

}

*/





Pixel Bender filter (ZOOM BLUR)




This filter will create a zoom blur effect













<languageVersion : 1.0;>

kernel ZoomBlur

< namespace : "com.rphelan";

vendor : "Ryan Phelan";

version : 1;

description : "A simple implementation of zoom blur, using 15 levels of blur.";

>

{

parameter float2 center

<

minValue:float2(0.0, 0.0);

maxValue:float2(2048.0, 2048.0);

defaultValue:float2(256.0, 256.0);

>;



parameter float amount

<

minValue:0.0;

maxValue:0.5;

defaultValue:0.05;

>;


input image4 src;

output pixel4 dst;

void

evaluatePixel()

{

// Obtain the output pixel coordinate

float2 coord = outCoord();



// Offset by the center value

coord -= center;



float scale;

dst = float4(0.0);



// This is an expanded for loop.

// Loops are not currently supported in pixel bender.

// For increased definition at the cost of performance,

// simply add more levels.



// Take 15 samples radiating out from the center and

// add them to dst



scale = 1.0;

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (1.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (2.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (3.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (4.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (5.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (6.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (7.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (8.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (9.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (10.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (11.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (12.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (13.0/14.0);

dst += sampleNearest( src, coord*scale + center );



scale = 1.0 + amount * (14.0/14.0);

dst += sampleNearest( src, coord*scale + center );



// Divide by 15 to get the average of the samples

dst /= 15.0;

}

}



Then export the filter File > Export Kernel Filter for Flash Player and save the .pdk file on you desktop.

Now Open Flash and create a new ActionScript 3 document. Save the new Flash document to your desktop, where you saved the filter file. Once the file is saved import an image that you will apply the filter to.


Click on the following link to see the filter in action. You must have Flash Player 10 installed to view it.



The ActionScript 3 code that I used to import the ZoomBlur sample shader is
shown below.









import adobe.utils.*;

import fl.controls.*;

import flash.accessibility.*;

import flash.desktop.*;

import flash.display.*;

import flash.errors.*;

import flash.events.*;

import flash.external.*;

import flash.filters.*;

import flash.geom.*;

import flash.media.*;

import flash.net.*;

import flash.printing.*;

import flash.profiler.*;

import flash.sampler.*;

import flash.system.*;

import flash.text.*;

import flash.text.engine.*;

import flash.ui.*;

import flash.utils.*;

import flash.xml.*;





var shader:flash.display.Shader;

var timer:flash.utils.Timer;

var loader:flash.net.URLLoader;

var timerInt:uint;

var startBtn:fl.controls.Button;

var image:flash.display.MovieClip;

var shaderFilter:flash.filters.ShaderFilter;









try

{

startBtn["componentInspectorSetting"] = true;

}

catch (e:Error)

{

};

startBtn.emphasized = false;

startBtn.enabled = true;

startBtn.label = "Start Effect";

startBtn.labelPlacement = "right";

startBtn.selected = false;

startBtn.toggle = false;

startBtn.visible = true;

try

{

startBtn["componentInspectorSetting"] = false;

}

catch (e:Error)

{

};



timerInt = 40;

image = new PixelBenderImage();

image.y = 20;

image.x = 25;

addChild(image);

startBtn.addEventListener(MouseEvent.CLICK, this.startEffect);





function restartEffect(arg1:flash.events.MouseEvent):*

{

image.alpha = 0;

return;

}

function startEffect(arg1:flash.events.MouseEvent):*

{

loader = new URLLoader();

loader.dataFormat = URLLoaderDataFormat.BINARY;

loader.addEventListener(Event.COMPLETE, this.loadComplete);

loader.load(new URLRequest("ZoomBlur.pbj"));

return;

}





function initFilter():*

{

return;

}

function timerHit(arg1:flash.events.TimerEvent):void

{

return;

}

function loadComplete(arg1:flash.events.Event):void

{

shader = new Shader(loader.data);

filter = new ShaderFilter(shader);

image.filters = [filter];

return;

}

 










No comments: