DirectionalBlurFilter && .swc Library and Stuff

Since the release of Flash 10, I’ve seen a few blog posts about creating .swc libraries that can be used in Flash. Probably the most in depth was Mike Chambers article “Creating Re-distributable Actionscript Libraries of Pixel Bender Filters”. Needless to say, I had to give it a go, myself. So, I fired up Pixel Bender and created the DirectionalBlurFilter seen below.

//  Directional Blur
//  01NOV08
//  
//  TODO:
//  Blur from image center - not image origin
<languageVersion : 1.0;>
kernel DirectionalBlur
<   namespace :     "com.onebyonedesign";
    vendor :        "Devon O. Wolfgang";
    version :       1;
    description :   "Directional Blur";
>
{
    parameter float angle
    <
        minValue:       0.0;
        maxValue:       360.0;
        defaultValue:   0.0;
    >;
 
    parameter float blurAmount
    <
        minValue:       0.0;
        maxValue:       1.0;
        defaultValue:   0.0;
    >;
 
    input image4 src;
    output pixel4 dst;
 
    void
    evaluatePixel()
    {
        float2 offset;
        float rads = radians(angle);
 
        offset.y = sin(rads);
        offset.x = cos(rads);
 
        //  add a little more blur
        float amount = blurAmount * 5.0;
 
        offset *= amount;
 
        //  number of sampled images
        int count = 30;
 
        //  very annoying pseudo loop
        dst += sampleNearest( src, outCoord() + offset * float(0) );
        dst += sampleNearest( src, outCoord() + offset * float(1) );
        dst += sampleNearest( src, outCoord() + offset * float(2) );
        dst += sampleNearest( src, outCoord() + offset * float(3) );
        dst += sampleNearest( src, outCoord() + offset * float(4) );
        dst += sampleNearest( src, outCoord() + offset * float(5) );
        dst += sampleNearest( src, outCoord() + offset * float(6) );
        dst += sampleNearest( src, outCoord() + offset * float(7) );
        dst += sampleNearest( src, outCoord() + offset * float(8) );
        dst += sampleNearest( src, outCoord() + offset * float(9) );
        dst += sampleNearest( src, outCoord() + offset * float(10) );
        dst += sampleNearest( src, outCoord() + offset * float(11) );
        dst += sampleNearest( src, outCoord() + offset * float(12) );
        dst += sampleNearest( src, outCoord() + offset * float(13) );
        dst += sampleNearest( src, outCoord() + offset * float(14) );
        dst += sampleNearest( src, outCoord() + offset * float(15) );
        dst += sampleNearest( src, outCoord() + offset * float(16) );
        dst += sampleNearest( src, outCoord() + offset * float(17) );
        dst += sampleNearest( src, outCoord() + offset * float(18) );
        dst += sampleNearest( src, outCoord() + offset * float(19) );
        dst += sampleNearest( src, outCoord() + offset * float(20) );
        dst += sampleNearest( src, outCoord() + offset * float(21) );
        dst += sampleNearest( src, outCoord() + offset * float(22) );
        dst += sampleNearest( src, outCoord() + offset * float(23) );
        dst += sampleNearest( src, outCoord() + offset * float(24) );
        dst += sampleNearest( src, outCoord() + offset * float(25) );
        dst += sampleNearest( src, outCoord() + offset * float(26) );
        dst += sampleNearest( src, outCoord() + offset * float(27) );
        dst += sampleNearest( src, outCoord() + offset * float(28) );
        dst += sampleNearest( src, outCoord() + offset * float(29) );
 
        //  no loops allowed
        /*
        for (int i = 0; i < count; i++) {
            dst += sampleNearest( src, outCoord() + offset * float(i) );
        }
        */
 
        //  normalize image
        dst /= float(count);
    }
}

What I dislike most about it is that the object blurs from the edge rather than the center, cutting the blur off rather abruptly. If anyone knows how to fix that or knows of a better Directional or Motion Blur filter, don’t hesitate to post. Lord knows when it comes to Pixel Shader coding, I’ll be the first to admit, I’m not exactly your “go to guy”.

In any case, after creating the “peanut butter and jelly file” (that’s a .pbj for those wondering), compiling it into a .swc (according to Mike Chambers’ instructions) and compiling that .swc file within a Flash .swf I got the below example.

The actionscript was simple enough – and I love the ability to treat my own filters just like a native Flash filter (just wish I was better at writing them).

package {
 
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import caurina.transitions.Tweener;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	import src.filters.DirectionalBlurFilter;
 
	/**
	 * ...
	 * @author Devon O.
	 */
	public class Main extends Sprite {
 
		//	Euro is item in .fla library
		private var _euro:Euro;
		private var _dirFilter:DirectionalBlurFilter;
 
		public function Main():void {
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
 
		private function init(e:Event = null):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);
 
			var instructions:TextField = new TextField;
			instructions.mouseEnabled = false;
			instructions.selectable = false;
			instructions.defaultTextFormat = new TextFormat("_sans", 12);
			instructions.autoSize = TextFieldAutoSize.LEFT;
			instructions.text = "Click around the stage.";
			instructions.y = 5;
			instructions.x = int(stage.stageWidth * .5 - instructions.width * .5);
			addChild(instructions);
 
			_dirFilter = new DirectionalBlurFilter();
 
			_euro = new Euro();
			_euro.x = 40;
			_euro.y = 40;
			addChild(_euro);
 
			stage.addEventListener(MouseEvent.CLICK, moveCoin);
		}
 
		private function moveCoin(event:MouseEvent):void {
			var tx:Number = event.stageX;
			var ty:Number = event.stageY;
			var rad:Number = Math.atan2(_euro.y - ty, _euro.x - tx);
			var angle:Number = rad * 180 / Math.PI;
 
			_dirFilter.angle = angle;
			_dirFilter.blurAmount = 1;
 
			var dataObj:Object = { blurAmount:1 };
 
			Tweener.addTween(_euro, { x:tx, y:ty, time:.5, transition:"easeOutQuad" } );
			Tweener.addTween(dataObj, { blurAmount:0, time:.5, transition:"easeOutQuad", onUpdate:applyBlur, onUpdateParams:[dataObj] } );
		}
 
		private function applyBlur(o:Object):void {
			_dirFilter.blurAmount = o.blurAmount;
			_euro.filters = [_dirFilter];
		}
	}
}

In other news, yes it’s been awhile, but I’ve been extremely busy lately with the new job and just settling into a new country in general. The company I’m working for now, just picked up an IIA NetVisionary award the other day and is now shortlisted for two Golden Spider awards. Wish I could say I helped out, but the awards are for projects created before my arrival. Still, it’s a great atmosphere to be coming into.

Ireland is a wonderful country – the people here have been terrific about welcoming this foreigner into their midst. And, of course, finally living together with my wife for the first time in nearly 3 years of marriage is the best thing ever. Who knew life could be so good?

9 Comments »

  1. John says:

    Very cool.

    I noticed when you move at 45 degrees, the front edge gets clipped pretty badly but the trailing edge looks fine.

  2. Devon O. says:

    Hey, John.

    Thanks for the comment. That clipped thing is the whole “blur from the edge” problem I was talking about. I got no idea how to solve it.. short of learning more pixel shader technique, that is..

  3. yanli says:

    To my surprise, I saw a strip of pink lines on the coin, defect produce after a few times of click on stage (near the text), look like FP10 have defective graphics bug? I was shock to think my nVidia graphics card is spolit.

  4. dVyper says:

    Nice job.

    It works well when you click on a position far away from the coin, but when you click on a location right beside the coin the effect looks too weird.

  5. Congrats on the living part of the past. As for the coding, outside of the blur from edge debacle, you should be using TweenLite/Max instead of tweener for your tweening :P

  6. Devon O. says:

    I’ve seen the pink stripe ugliness myself. It too has something to do with filter code. The focus of the post was supposed to be more on the fact that you can now write your own filters and easily use them in Flash just as you would a native filter class – not so much on my filter writing abilities, which leave a lot to be desired.

    Matt, my first tweening choice was actually TweenFilterLite, but when I discovered I couldn’t (at least not easily) tween custom filter properties, I reverted back to Tweener. Brand loyalty, I suspect… Thank you for the congrats.. :)

  7. Jack says:

    Hey Devon. Just wanted to chime in and make sure you (and others) knew that TweenLite/FilterLite/Max can easily do exactly what you’re doing with Tweener. I assume the “custom filter properties” you mentioned had to do with these lines:

    var dataObj:Object = { blurAmount:1 };
    Tweener.addTween(dataObj, { blurAmount:0, time:.5, transition:”easeOutQuad”, onUpdate:applyBlur, onUpdateParams:[dataObj] } );

    Which would look like this with TweenLite:

    var dataObj:Object = { blurAmount:1 };
    TweenLite.to(dataObj, .5, { blurAmount:0, ease:Quad.easeOut, onUpdate:applyBlur, onUpdateParams:[dataObj] } );

    Not that Tweener is a bad choice – I just wanted to correct what seemed like a misunderstanding as far as tweening custom properties with TweenLite/FilterLite/Max. Or did I miss something that you were trying to do with Tweener that TweenLite/FilterLite/Max couldn’t do?

  8. Devon O. says:

    Hey Jack,
    Thank you for the comment and useful info. Actually what I was hoping to do though was something like:
    TweenFilterLite.to(_euro, .5, {blurFilter:{blurX:0}});
    except I wanted to replace the blurFilter with my own custom (DirectionalBlurFilter) filter. To be honest, I didn’t poke around the code too much. Is that possible?

  9. Jack says:

    No, sorry, but blurFilter:{} is specifically for BlurFilters, not any old custom filter. But I believe Tweener (and any popular tweening engine) has that requirement as well. It’s pretty easy to accomplish what you’re after with an onUpdate, though (as your code demonstrated). TweenLite/FilterLite/Max can tween any numeric property of ANY object, and if you need to do something special on every frame with the new value (like apply it to the “filters” property of an object), just use onUpdate to call a function that does that job for you.

RSS feed for comments on this post. / TrackBack URI

Leave a Reply

Devon O. Wolfgang

Technical Reviewer of “The Essential Guide to Flash CS4 AIR Development”

Contributing Author of “Flash AS3 for Interactive Agencies”

Senior Software Developer in Dublin, Ireland

Portfolio

Bayer Pixel Bender Filter

Bayer Mosaic Filter in Pixel Bender


Now, seeing as how I’ve been trying to learn some Pixel Bender coding lately[...]

Liquitext

Liquid Text Effect


Haven’t been too active around here lately due to a major on going project at work lately as well as the fact that my wife and I are in the slow process of moving homes. Really, the only free time it seems I have these days is during the lunch hour. So, over the past two days, I came up with this fun little toy during lunches[...]

Google’s Text To Speech Engine in Flash

I’m not sure how I managed to miss this, but I just happened to run across a ‘new’ (well, newish), albeit still unofficial, offering of Google today: text-to-speech. You can see what few details there are on this Techcrunch post. Basically, it just boils down to this though – you send your phrase to be [...]

Quick Sound Effects Generator


Need some beeps, boops, or bops, to go with your UI or games [...]

Quick QuickBox2D Tip II – Collision Detection

Custom collision detection/handling in QuickBox2D [...]

None of This Runs Eternal


No Flash/Actionscript stuff here. Just me rambling about the upcoming Current 93 concert [...]

Playing Around with the New UndoManager

Included in the Flex 4.0 SDK and the, just released, Flash Professional CS5 lies a new hidden little gem of a class: flashx.undo.UndoManager (although the Flex 4.0 SDK’s been out for awhile, I have to admit I didn’t even notice this until I installed Flash CS5 and started poking around the documentation looking for new [...]

Making Waves

In a previous post, “Digging into the Microphone in Flash Player 10.1″, reader David Law asked in the comments how it would be possible to save .wav files to the server. I wasn’t sure right offhand, but thought I’d spend my lunch hour yesterday looking into it. Well, after reading this quick tutorial on Adobe [...]

Some Drawing Fun and a Bad Movie You’ll Never See

Earlier today, Dave Gillem posted a link on Facebook to an incredible Processing based drawing application. Thought I’d have a go at reproducing something similar in Flash. Well, I failed miserably, but the results were still interesting enough to check out. You can play around with it below. Just mouse down to draw in the [...]

Animating Bezier Curves


The other day I got the notion in my head that I wanted to draw some bezier curves in an animated fashion. I’m sure this has been done a million times before, but sometimes reinventing the wheel can be a good learning experience [...]

My God, It’s Full of Stars…


Just a quick little thing I got an idea for (i.e. pretty much ripped off) while browsing Processing examples.

Another Year, Another Look

As a few folks may have noticed, the blog is looking a little bit different as of today [...]

The Webcam Warholizer


Just a little bit of quick Friday fun with webcam and bitmapata…

More With the JiglibFlash Terrain

Playing around a bit more with the animated JiglibFlash terrain idea from my last post, I wanted to see how it would work in conjunction with a webcam. So, needless to say, you’ll need a webcam to check out the results below.

Rockin and Rollin with the JiglibFlash Terrain


Finally got the chance to play around with the new JiglibFlash height map terrain, today, and have to say I am very impressed [...]