In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

はじめてのPixel BenderとShader 「墨」

...
@author @kndys
Get Adobe Flash player
by knd 01 Apr 2010
/**
 * Copyright knd ( http://wonderfl.net/user/knd )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/eJWb
 */

package 
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Shader;
    import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
    import flash.geom.Point;
    import flash.net.URLLoader;
    import flash.net.URLLoaderDataFormat;
    import flash.net.URLRequest;
	
	/**
	 * ...
	 * @author @kndys
	 */
    [SWF(width="465",height="465",backgroundColor="0x808080",frameRate="30")]
	public class Main extends Sprite 
	{
        private var loader:URLLoader;
        private var _overdrive:OverdriveBitmapData;
        private var _drop:BitmapData;
		
		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);
			// entry point
            
            var bmd:BitmapData = new BitmapData(465, 465, true, 0xff808080);
            _overdrive = new OverdriveBitmapData(bmd,
						            			    1 / stage.frameRate, //更新間隔
						           	 		   [2.5, 2.5, 2.5, 0.0], //減衰
						          	  		   [20, 20, 20, 0.0], //伝達速度
						         	   		   [-0.5, -0.5, -0.5, 0.0]); //反射係数
            var bmp:Bitmap = new Bitmap(_overdrive);
            addChild(bmp);
            addEventListener(Event.ENTER_FRAME, loop);
            
            //雨粒画像
            var shape:Shape = new Shape();
            shape.graphics.beginFill(0x333333, 1);
            shape.graphics.drawCircle(5, 5, 5);
            _drop = new BitmapData(shape.width, shape.height, true, 0x0);
            _drop.draw(shape);
            
		}
        
        private function loop(e:Event):void 
        {
            _overdrive.update(); //前回の状態と今回の状態から次回の状態を計算して更新する
            //BitmapDataサブクラスなので今回の状態を簡単に加工できます
            _overdrive.copyPixels(_drop, _drop.rect, new Point(465 * Math.random(), 465 * Math.random()), null, null, true);
        }
	}	
}

/* overdrive.pbj ソース
 * 非常に単純なコードです。
kernel Overdrive
{
    input image4 currentImage;
    input image4 previousImage;
    output pixel4 nextPixel;
    
    parameter float current;
    parameter float previous;
    parameter float around;
    parameter float reflection;

    void
    evaluatePixel()
    {
        float2 pos = outCoord();
        
        float4 colorN = sampleNearest(currentImage, pos + float2(0.0, -1.0));
        float4 colorS = sampleNearest(currentImage, pos + float2(0.0, 1.0));
        if (colorN.a == 0.0) colorN = reflection * colorS;
        else if (colorS.a == 0.0) colorS = reflection * colorN;
        
        float4 colorW = sampleNearest(currentImage, pos + float2(-1.0, 0.0));
        float4 colorE = sampleNearest(currentImage, pos + float2(1.0, 0.0));
        if (colorW.a == 0.0) colorW = reflection * colorE;
        else if (colorE.a == 0.0) colorE = reflection * colorW;
        
        nextPixel = float4(0.5)
            + current * (sampleNearest(currentImage, pos) - float4(0.5))
            + previous * (sampleNearest(previousImage, pos) - float4(0.5))
            + around * (colorN + colorS + colorW + colorE - float4(2.0));
    }
}
 */

	import flash.display.BitmapData;
    import flash.display.Shader;
    import flash.display.ShaderData;
    import flash.display.ShaderInput;
    import flash.display.ShaderJob;
    import mx.utils.Base64Decoder;
	
	/**
     * ...
     * @author @kndys
     */
    internal class OverdriveBitmapData extends BitmapData
    {
        
        private var _previous:BitmapData;
        private var _next:BitmapData;
        
        private var _shader:Shader;
        private var _job:ShaderJob;
        
        private var _dt:Number;
        private var _decay:Array;
        private var _velocity:Array;
        private var _reflection:Array;
        
        /**
         * 
         * @param	initialImage 初期状態のBitmapData
         * @param	dt update()の間隔 [sec]
         * @param	decay 減衰の大きさ [1/sec] (RGBA各チャネルについてArrayで指定)
         * @param	velocity 伝達の速さ [pixel/sec] (RGBA各チャネルについてArrayで指定)
         * @param	reflection 境界での反射の仕方(RGBA各チャネルについてArrayで指定)
         */
        public function OverdriveBitmapData(initialImage:BitmapData, dt:Number = 0.0, decay:Array = null, velocity:Array = null, reflection:Array = null) 
        {
            super(initialImage.width, initialImage.height, initialImage.transparent);
            super.draw(initialImage);
            _previous = new BitmapData(initialImage.width, initialImage.height, initialImage.transparent);
            _previous.draw(initialImage);
            _next = new BitmapData(initialImage.width, initialImage.height, initialImage.transparent, 0x0);
            
            _shader = new Shader();
            var decoder:Base64Decoder = new Base64Decoder();
            decoder.decode("pQEAAACkCQBPdmVyZHJpdmWgDG5hbWVzcGFjZQBvdmVyZHJpdmUAoAx2ZW5kb3IAQGtuZHlzAKAIdmVyc2lvbgABAKAMZGVzY3JpcHRpb24AAKEBAgAADF9PdXRDb29yZACjAARjdXJyZW50SW1hZ2UAowEEcHJldmlvdXNJbWFnZQChAgQBAA9uZXh0UGl4ZWwAoQEEAgAPY3VycmVudAChAQQDAA9wcmV2aW91cwChAQQEAA9hcm91bmQAoQEEBQAPcmVmbGVjdGlvbgAdAAAxAAAQADIGAIAAAAAAMgYAQL+AAAAdBgAxAACwAAEGADEGABAAMAcA8QYAsAAdBgDzBwAbADIHAIAAAAAAMgcAQD+AAAAdBwAxAACwAAEHADEHABAAMAgA8QcAsAAdBwDzCAAbADIIAIAAAAAAMggAQAAAAAAyCAAgAAAAADIIABAAAAAAKAYA8wgAGwAdAYCAAIAAADQAAAABgAAAHQgA8wUAGwADCADzBwAbAB0GAPMIABsANQAAAAAAAAAyCACAAAAAADIIAEAAAAAAMggAIAAAAAAyCAAQAAAAACgHAPMIABsAHQGAQACAAAA0AAAAAYBAAB0IAPMFABsAAwgA8wYAGwAdBwDzCAAbADYAAAAAAAAANgAAAAAAAAAyCACAv4AAADIIAEAAAAAAHQgAMQAAsAABCAAxCAAQADAJAPEIALAAHQgA8wkAGwAyCQCAP4AAADIJAEAAAAAAHQkAMQAAsAABCQAxCQAQADAKAPEJALAAHQkA8woAGwAyCgCAAAAAADIKAEAAAAAAMgoAIAAAAAAyCgAQAAAAACgIAPMKABsAHQGAgACAAAA0AAAAAYAAAB0KAPMFABsAAwoA8wkAGwAdCADzCgAbADUAAAAAAAAAMgoAgAAAAAAyCgBAAAAAADIKACAAAAAAMgoAEAAAAAAoCQDzCgAbAB0BgEAAgAAANAAAAAGAQAAdCgDzBQAbAAMKAPMIABsAHQkA8woAGwA2AAAAAAAAADYAAAAAAAAAMgoAgD8AAAAyCgBAPwAAADIKACA/AAAAMgoAED8AAAAwCwDxAACwADIMAIA/AAAAMgwAQD8AAAAyDAAgPwAAADIMABA/AAAAHQ0A8wsAGwACDQDzDAAbAB0LAPMCABsAAwsA8w0AGwAdDADzCgAbAAEMAPMLABsAMAoA8QAAsAEyCwCAPwAAADILAEA/AAAAMgsAID8AAAAyCwAQPwAAAB0NAPMKABsAAg0A8wsAGwAdCgDzAwAbAAMKAPMNABsAHQsA8wwAGwABCwDzCgAbAB0KAPMGABsAAQoA8wcAGwAdDADzCgAbAAEMAPMIABsAHQoA8wwAGwABCgDzCQAbADIMAIBAAAAAMgwAQEAAAAAyDAAgQAAAADIMABBAAAAAHQ0A8woAGwACDQDzDAAbAB0KAPMEABsAAwoA8w0AGwAdDADzCwAbAAEMAPMKABsAHQEA8wwAGwA=");
            _shader.byteCode = decoder.drain(); //new OverdriveShader();
            setShaderInput();
            
            _dt = dt;
            _decay = decay;
            _velocity = velocity;
            _reflection = reflection;
            setShaderParam();
        }
        
        private function setShaderParam():void
        {
            if ( dt == 0.0 || _decay == null || _velocity == null || _reflection == null) return;
            var dat:ShaderData = _shader.data;
            var prmCurr:Array = [];
            var prmPrev:Array = [];
            var prmArnd:Array = [];
            var prmRefl:Array = [];
            dat.current.value = prmCurr;
            dat.previous.value = prmPrev;
            dat.around.value = prmArnd;
            dat.reflection.value = prmRefl;
            for (var i:int = 0; i< 4; i++) 
            {
                var a:Number = _velocity[i] * dt;
                a *= a;
                var b:Number = _decay[i] * _dt;
                var c:Number = 1 / (2 + b); 
                prmCurr[i] = (4 - 8 * a) * c;
                prmPrev[i] = - (2 - b) * c;
                prmArnd[i] = 2 * a * c;
                prmRefl[i] = _reflection[i]
            }
        }
        
        public function update():void
        {
            _job = new ShaderJob(_shader, _next);
            _job.start(true);
            
            _previous.draw(super);
            super.draw(_next);
        }
        
        private function setShaderInput():void
        {
            var dat:ShaderData = _shader.data;
            var current:ShaderInput = dat.currentImage;
            var previous:ShaderInput = dat.previousImage;
            current.input = super;
            previous.input = _previous;
        }
        
        public function get dt():Number { return _dt; }
        
        public function set dt(value:Number):void 
        {
            _dt = value;
            setShaderParam();
        }
        
        public function get decay():Array { return _decay; }
        
        public function set decay(value:Array):void 
        {
            _decay = value;
            setShaderParam();
        }
        
        public function get velocity():Array { return _velocity; }
        
        public function set velocity(value:Array):void 
        {
            _velocity = value;
            setShaderParam();
        }
        
        public function get reflection():Array { return _reflection; }
        
        public function set reflection(value:Array):void 
        {
            _reflection = value;
            setShaderParam();
        }
    }