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 Flash Engineer PopCap Games, International Ltd.

Portfolio

UV Scrolling in Starling


Obviously this could come in pretty darned handy for space games, side scrollers, etc, etc[...]

Drawing on Stuff in Away3D 4.0

So, Easter Day, I thought I’d sit down and make a little ‘Paint on an Egg and Send it to Your Friend’ app.

Santabot: A Unity3D Flash Game


All right, so a Christmas game like “Santabot vs. The Flying Saucers from Mars” may be a day late[...]

Magnify – a jQuery Plugin


Let me begin by saying right up front, I have not given up on Flash[...]

It’s a Starling Halloween


Getting some practice for the upcoming Zombie Apocalypse[...]

Getting Started with Proscenium

So I had a chance this weekend to sit down and play around with Adobe’s new 3D framework for Stage3D, Proscenium, and thought I’d share a few of the results (a word of caution, there are no preloaders for any of the examples and may load a bit slowly). The first shows some reflections and [...]

Particle Editor for Starling Framework

An in-browser particle editor for the Starling 2D Framework for Flash Player 11.

So Long and Thanks for all the Flash on the Beach

So, another Flash on the Beach has just has just drawn to a close[...]

Game Development Tips from the Trenches of PopCap

Well, this is a post that’s a bit overdue, but, thanks to a well timed bank holiday, I finally had the opportunity to sit down and type up what I’ve been meaning to for some time now…

Old Skool Demoscene FX as 3D Textures

Many moons ago, I got the idea to create some demoscene plane deformation effects in Flash based on the formulas found here: http://www.iquilezles.org/www/articles/deform/deform.htm. I posted my less than desired results up on wonderfl. Thankfully, fellow wonderfl user, Hasufel, forked my attempt and optimized the hell out of it coming up with this. Well, today, for no [...]

Making The Gaming Scene (A Change in Careers)

And for my second blog post of the day, a much more personal note. After about three years of working with, what I would consider as objectively as possible, the best digital agency in Ireland, vStream Digital Media, I have made the immense career decision to leave the agency world and enter the arena of [...]

Feeling Lucky?

Images to dice, kick ascii style [...]

Adventures in Playbook Land

Adventures in Playbook Land


Now that the ordeal is over, I thought I’d take the time to sit down and share my account of what it was like to develop a Blackberry Playbook application using the Adobe Flex SDK[...]

Flash

Draw it for Me

So many ideas – so little time….

Kinect Application Running in Dublin

So, on Friday I just wrapped up our latest project at vStream Digital Media, a Kinect powered flipbook that lets users flip through the hand written notebooks of Philip Lynott of Thin Lizzy. The app uses OpenNI, runs in Adobe AIR and is currently on display at a pretty bitchin’ Phil Lynott exhibition running in [...]

Beach Ball Kinect Party

So we finally got a Kinect camera hooked up to a pc at work and, while it doesn’t seem to be legal to use it for commercial projects (but, hey, I’m no lawyer), the boss asked me to get it figured out and come up with some ideas just in case it would be feasible [...]