Tom Krcha's FlashRealtime

Hey amigo! These are my notes. I'm Platform Evangelist with Adobe.


Pixel Bender 2. - filter ve Flashi

November 26th, 2008

V minulém díle (http://tom.krcha.com/pixel-bender-1-uvod/) jsme si představili v kostce jazyk Pixel Bender. Vzhledem k tomu, že je již konečně ke stažení CS4 Trial a všichni si jej můžou vyzkoušet, přešel bych rovnou k věci, a sice aplikaci Pixel Bender filtrů ve Flashi 10.

Aplikace, kterou si dnes vytvoříme je zde.
pixel bender in flash

(Musíte mít nainstalovaný Flash Player 10)

1) Stáhněte si a nainstalujte Flash CS4 z www.adobe.com/cz/downloads/

2) Nachystejte si nějaký Pixel Bender filter (viz. inspirace v minulém díle)

Ideální však bude použít nějaký pokročilejší filtr. Já jsem zvolil twirl.pbk - příklad, který se nainstaluje s Pixel Benderem. 

- Otevřete twirl.pbk v Pixel Bender Toolkit

- File -> Export Kernel Filter For Flash Player … uložte soubor *.pbj - pokud nastane problém při exportu*, odstraňte některé nepodporované části nebo použijte můj vyexportovaný twirl.pbj. 

* Flash Player Pixel Bender Runtime nepodporuje všechny možnosti jazyka Pixel Bender (např. blok needed) - o těchto možnostech si řekneme v dalším dílech. 

3) Spusťte Flash CS4

- Vytvoříme si třídu PixelBenderLoader, která bude načítat filtry za běhu a aplikovat je na jakýkoliv DisplayObject = snad jakákoliv vizuální komponenta, MovieClip, Video, Fotka, Vektor apod.

- PixelBenderLoader je moje třída, kterou můžete používat, nicméně inovaci se meze nekladou a určitě si najdete vlastní cestu pro vaše konkrétní využití.

package
{
	import flash.display.*;
	import flash.events.*;
	import flash.filters.*;
	import flash.net.*;
	import flash.events.EventDispatcher;
 
	public class PixelBenderLoader extends EventDispatcher
	{		
		private var loader:URLLoader;
		private var shader:Shader;
		// ShaderFilter muzeme aplikovat pomoci parametru filters DisplayObjectu
		private var filter:ShaderFilter;
 
		public function PixelBenderLoader():void
		{
 
		}
	        // nacteni filtru
		public function loadFilter(filterURL:String):void{
			loader = new URLLoader();
			loader.dataFormat = URLLoaderDataFormat.BINARY;
 
			// odchytime jen udalost nacteni, doporucuju vsak odchytit pripadne errory
			loader.addEventListener(Event.COMPLETE, onComplete);
			loader.load(new URLRequest(filterURL));
		}
 
		// aplikuje filter pomoci transformacni objektu
		public function applyFilter(displayObject:DisplayObject,transformObject:Object){
			applyShaderWithTransformObject(shader,transformObject);
			filter = new ShaderFilter(shader);
			displayObject.filters = [filter];
		}
 
                // vrati filter pro pripadnou aplikaci volnejsim zpusobem
		public function getFilter(transformObject:Object):ShaderFilter{
			applyShaderWithTransformObject(shader,transformObject);
			filter = new ShaderFilter(shader);
			return filter;
		}
 
                // aplikuje transformacni objekt na shader pomoci cyklu
		protected function applyShaderWithTransformObject(shader:Shader,transformObject:Object):void{
			for(var i:String in transformObject){
				shader.data[i].value = [transformObject[i]];
			}
		}
 
		// po načtení filteru
		protected function onComplete(e:Event):void
		{
			shader = new Shader(loader.data);
			dispatchEvent(e);
		}
	}
}

transformObject:Object - hodnoty parametrů, které filter umožňuje měnit
např. tranformObject = {radius:150};

- Ve Flashi pak použijeme filter tímto způsobem

Načtení filtru:

var pbl:PixelBenderLoader = new PixelBenderLoader();
pbl.addEventListener(Event.COMPLETE,onComplete);
pbl.loadFilter("twirl.pbj");

Aplikace filtru - v tomto případě budeme měnit radius:
(deformClip je klasický MovieClip v library, obsahuje fotku a dynamický text)

function applyRadius(radius:Number){
	// transformacni objekt, zmenime jen radius
	var transformObject:Object = new Object();
	transformObject.radius = radius;
 
	// zmen dynamicky text
	deformClip.txt.text = radius.toString();
 
	// aplikuj filtr
	pbl.applyFilter(deformClip,transformObject);
}

Změna parametru při pohybu myši:

// zmen radius pri pohybu mysi
function mouseMoveChange(event:MouseEvent):void{
	applyRadius(Math.abs(event.localX));
}

Odchycení události načtení filtru - v tuto chvíli lze začít filter používat:

function onComplete(e:Event):void{
	trace("filter load complete - aplikace");	
	applyRadius(100);
	stage.addEventListener(MouseEvent.MOUSE_MOVE,mouseMoveChange);
}

Demo soubory ke stažení zde.

Facebook comments:

9 Comments »

  1. Zdravim.

    super clanok od ktoreho sa odrazilo vela ludi.

    Napada ma ci by sa do triedy nedal importovat uz nacitany filter. a nie ho vzdy nacitat. pricom by bola trieda univerzalna

    nieco taketo :
    pbl.loadEmbedFilter(”pixelate.pbj”);
    ostatne metody zachovali.

    alebo to napvno anstavit do tej triedy.

    sukusal som to dlho ale bez uspesne :(

    [Embed(source='Test_filter.pbj',mimeType='application/octet-stream')]
    private static const WaterKernel: Class;

    Comment by TS — March 7, 2009 @ 2:09 am

  2. Diky.

    Tu druhou variantu bych musel vyzkouset. V tuto chvili si nejsem jisty zdali to tak jde. Nicmene cilem je udelat z *.pbj instanci ShaderFilter

    Comment by tom — March 8, 2009 @ 11:23 pm

  3. Cavko, paradny clanok, ale neviem ako docielti pomocou tvojej tredy aby som nastavil dva a viac parametrov, danemu filtru napriklad

    function applyRadius(radius:Number){

    var transformObject2:Object = new Object();
    transformObject2.outerRadius = 20

    // PROSTE TOTO TO NEVIE SPRACOVAT A NEVIEM AKO TO ZAPISAT
    transformObject2.center = [0,0];

    pbl2.applyFilter(obrazok,transformObject2);

    }

    Comment by MISO — March 19, 2009 @ 10:19 am

  4. //dalsi parametry posles velmi jednoduse:

    var transformObject:Object = new Object();
    transformObject.parametr1 = hodnota1;
    transformObject.parametr2 = hodnota2;

    // samotna aplikace:
    pbl.applyFilter(deformClip,transformObject);

    Comment by tom — March 24, 2009 @ 1:25 am

  5. to ano ale ono mi to pride ze to neni osterene ked ma filtren na pariklad parameter center ktory sa sklada z dvoch suradnic napr

    transformObject.center = [0,5]
    alebo

    transformObject.center[0] = 0

    transformObject.center[1] = 5

    tento zapis to uz nezobere

    Comment by MISO — March 24, 2009 @ 10:13 pm

  6. musis to zapsat takhle:
    transformObject.center = new Array();
    transformObject.center[0] = 0;
    transformObject.center[1] = 5;

    Comment by tom — March 27, 2009 @ 3:30 pm

  7. dakujem moc

    Comment by miso — March 29, 2009 @ 3:33 am

  8. cavko po dlhom case som sa ktomu dostal a popisany postup mi nefunguje importujem triedu napisem :

    var pbl:PixelBenderLoader = new PixelBenderLoader();
    pbl.addEventListener(Event.COMPLETE,onComplete);
    pbl.loadFilter(”pinch.pbj”);

    function applyRadius(radius:Number){
    // transformacni objekt, zmenime jen radius

    var transformObject:Object = new Object();
    transformObject.center = new Array();

    //transformObject.magnification = radius;

    transformObject.center[0] = 5;
    transformObject.center[1] = 5;

    // aplikuj filtr
    pbl.applyFilter(deformClip,transformObject);
    }

    // zmen radius pri pohybu mysi
    function mouseMoveChange(event:MouseEvent):void{
    applyRadius(mouseX/500);
    }

    function onComplete(e:Event):void{
    stage.addEventListener(MouseEvent.MOUSE_MOVE,mouseMoveChange);
    }

    a po spusteni hlasi chybu

    ArgumentError: Error #2004: One of the parameters is invalid.
    at flash.display::DisplayObject/set filters()
    at PixelBenderLoader/applyFilter()
    at omnio_fla::MainTimeline/applyRadius()
    at omnio_fla::MainTimeline/mouseMoveChange()

    Comment by Miso — April 10, 2009 @ 5:07 pm

  9. fuu nejako zle to sformatovalo

    Comment by Miso — April 10, 2009 @ 5:07 pm

RSS feed for comments on this post. / TrackBack URL

Leave a comment