LogoLogo
  • Home
  • Projects
  • About
  • Contact

DirectionalBlurFilter && .swc Library and Stuff

Devon O. · November 02, 2008 · Actionscript, Flash · 9 comments
2

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.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//  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).

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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?

  Facebook   Pinterest   Twitter   Google+
  • Yahtzee! Too Late for a Contest, but Never too Late to Play
    July 27, 2008 · 4 comments
    2129
    3
    Read more
  • OBO fPlayer (desktop AIR flv player) updated
    January 01, 2009 · 9 comments
    3351
    2
    Read more
  • Laws of Nature and of Nature’s God
    July 04, 2008 · 0 comments
    1638
    3
    Read more
9 Comments:
  1. Very cool.

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

    John · November 02, 2008
  2. 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..

    Devon O. · November 02, 2008
  3. 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.

    yanli · November 02, 2008
  4. 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.

    dVyper · November 02, 2008
  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

    Matt Przybylski · November 02, 2008
  6. 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.. :)

    Devon O. · November 03, 2008
  7. 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?

    Jack · November 03, 2008
  8. 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?

    Devon O. · November 04, 2008
  9. 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.

    Jack · November 04, 2008

Leave a Comment! Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Devon O. Wolfgang

AIR | Unity3D | AR/VR

Unity Certified Developer

Technical Reviewer of “The Essential Guide to Flash CS4 AIR Development” and “Starling Game Development Essentials”

Reviewer of “The Starling Handbook”

Unity Engineer at Touch Press.

Categories
  • Actionscript (95)
  • AIR (16)
  • Flash (99)
  • Games (7)
  • Liberty (13)
  • Life (53)
  • Shaders (20)
  • Unity3D (21)
Recent Comments
  • MainDepth on Unity Ripple or Shock Wave Effect
  • Devon O. on Unity Ripple or Shock Wave Effect
  • Feral_Pug on Unity Ripple or Shock Wave Effect
  • bavvireal on Unity3D Endless Runner Part I – Curved Worlds
  • Danielius Vargonas on Custom Post Processing with the LWRP
Archives
  • December 2020 (1)
  • December 2019 (1)
  • September 2019 (1)
  • February 2019 (2)
  • December 2018 (1)
  • July 2018 (1)
  • June 2018 (1)
  • May 2018 (2)
  • January 2018 (1)
  • December 2017 (2)
  • October 2017 (1)
  • September 2017 (2)
  • January 2017 (1)
  • July 2016 (1)
  • December 2015 (2)
  • March 2015 (1)
  • September 2014 (1)
  • January 2014 (1)
  • August 2013 (1)
  • July 2013 (1)
  • May 2013 (1)
  • March 2013 (2)
  • December 2012 (1)
  • November 2012 (1)
  • September 2012 (3)
  • June 2012 (2)
  • May 2012 (1)
  • April 2012 (1)
  • December 2011 (2)
  • October 2011 (3)
  • September 2011 (1)
  • August 2011 (1)
  • July 2011 (1)
  • May 2011 (2)
  • April 2011 (2)
  • March 2011 (1)
  • February 2011 (1)
  • January 2011 (2)
  • December 2010 (3)
  • October 2010 (5)
  • September 2010 (1)
  • July 2010 (2)
  • May 2010 (5)
  • April 2010 (2)
  • March 2010 (7)
  • February 2010 (5)
  • January 2010 (5)
  • December 2009 (3)
  • November 2009 (1)
  • October 2009 (5)
  • September 2009 (5)
  • August 2009 (1)
  • July 2009 (1)
  • June 2009 (2)
  • May 2009 (6)
  • April 2009 (4)
  • March 2009 (2)
  • February 2009 (4)
  • January 2009 (1)
  • December 2008 (5)
  • November 2008 (2)
  • September 2008 (1)
  • August 2008 (6)
  • July 2008 (6)
  • June 2008 (9)
  • May 2008 (4)
  • April 2008 (3)
  • March 2008 (4)
  • February 2008 (9)
  • January 2008 (7)
  • December 2007 (6)
Copyright © 2021 Devon O. Wolfgang