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

AGAL Post Processing FX

Get Adobe Flash player
by devon_o 18 Aug 2012
/**
 * Copyright devon_o ( http://wonderfl.net/user/devon_o )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/cyHn
 */

package
{
    import com.adobe.utils.AGALMiniAssembler;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DTextureFormat;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.textures.Texture;
    import flash.display3D.VertexBuffer3D;
    import flash.events.Event;
    import flash.geom.Matrix3D;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;

    /**
     * AGAL Postprocessing effect
     * Based on: http://www.iquilezles.org/apps/shadertoy/?p=postpro
     */
    
    [SWF(width="465", height="465", frameRate="60", backgroundColor="#000000")]
    public class PostPro extends Sprite
    {
        private var mContext3d:Context3D;
        private var mVertBuffer:VertexBuffer3D;
        private var mIndexBuffer:IndexBuffer3D; 
        private var mProgram:Program3D;
        private var mTexture:Texture;
        private var mTextureData:BitmapData;
        
        private var mMatrix:Matrix3D = new Matrix3D();
        
        public function PostPro()
        {    
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);    
        }
        
        private function init(event:Event = null):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            initStage();
            loadImage();
            
            addEventListener(Event.ENTER_FRAME, onTick);
        }
        
        private function loadImage():void {
            var l:Loader = new Loader();
            l.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoad);
            l.load(new URLRequest("http://assets.wonderfl.net/images/related_images/6/68/68ef/68efcb70438fb102c11265efe3fd1a737160999c"), new LoaderContext(true));
        }
        
        private function onImageLoad(event:Event = null):void
        {
            event.currentTarget.removeEventListener(Event.COMPLETE, onImageLoad);
            var l:Loader = event.currentTarget.loader;
            mTextureData = (l.content as Bitmap).bitmapData;
            
            stage.stage3Ds[0].addEventListener( Event.CONTEXT3D_CREATE, initStage3d );
            stage.stage3Ds[0].requestContext3D();
        }
        
        private function initStage():void
        {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
        }
        
        private function initStage3d(event:Event):void
        {
            mContext3d = stage.stage3Ds[0].context3D;        
            mContext3d.enableErrorChecking = false;
            
            mContext3d.configureBackBuffer(stage.stageWidth, stage.stageHeight, 4, true);
            
            var vertices:Vector.<Number> = Vector.<Number>([
                -1.0, -1.0,  0,   0, 0, 
                -1.0,  1.0,  0,   0, 1,
                 1.0,  1.0,  0,   1, 1,
                 1.0, -1.0,  0,   1, 0  ]);
            
            mVertBuffer = mContext3d.createVertexBuffer(4, 5);
            mVertBuffer.uploadFromVector(vertices, 0, 4);
            mIndexBuffer = mContext3d.createIndexBuffer(6);            
            mIndexBuffer.uploadFromVector (Vector.<uint>([0, 1, 2, 2, 3, 0]), 0, 6);
            
            mTexture = mContext3d.createTexture(mTextureData.width, mTextureData.height, Context3DTextureFormat.BGRA, true);
            mTexture.uploadFromBitmapData(mTextureData);

            mContext3d.setVertexBufferAt(0, mVertBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
            mContext3d.setVertexBufferAt(1, mVertBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
            
            generateMicroProg();
            
            mContext3d.setTextureAt(0, mTexture);
            mContext3d.setProgram(mProgram);
        }
        
        private function generateMicroProg():void
        {
            var vertexShaderAssembler : AGALMiniAssembler = new AGALMiniAssembler();
            vertexShaderAssembler.assemble( Context3DProgramType.VERTEX,
                "m44 op, va0, vc0\n" + // pos to clipspace
                "mov v0, va1" // copy uv
            );
            var fragmentShaderAssembler : AGALMiniAssembler= new AGALMiniAssembler();
            fragmentShaderAssembler.assemble( Context3DProgramType.FRAGMENT,
                "div ft0, v0, fc0   \n" +
                "sub ft1, ft0, fc3.x   \n" +
                "mul ft1, ft1, fc2.x   \n" +
                "add ft1, ft1, fc3.x   \n" +
                "mov ft2, fc1   \n" +
                "mov ft2.x, ft0.x   \n" +
                "sub ft2.y, fc1.x, ft0.y   \n" +
                "tex ft3, ft2, fs0<2d, repeat, linear, nomip>   \n" +
                "mov ft4, fc1   \n" +
                "mov ft2, fc1   \n" +
                "add ft2.x, ft1.x, fc3.y   \n" +
                "mul ft2.y, uv.y, fc2.w   \n" +
                "tex ft6, ft2, fs0<2d, repeat, linear, nomip>   \n" +
                "mov ft4.x, ft6.x   \n" +
                "mov ft2, fc1   \n" +
                "add ft2.x, ft1.x, fc3.z   \n" +
                "mul ft2.y, uv.y, fc2.w   \n" +
                "tex ft6, ft2, fs0<2d, repeat, linear, nomip>   \n" +
                "mov ft4.y, ft6.y   \n" +
                "mov ft2, fc1   \n" +
                "sub ft2.x, ft1.x, fc3.y   \n" +
                "mul ft2.y, uv.y, fc2.w   \n" +
                "tex ft6, ft2, fs0<2d, repeat, linear, nomip>   \n" +
                "mov ft4.z, ft6.z   \n" +
                "mov ft4.w, fc1.w   \n" +
                "mov ft5, fc1   \n" +
                "mul ft5, ft4, fc3.x   \n" +
                "mov ft6, fc1   \n" +
                "mul ft6, ft4, fc3.w   \n" +
                "mul ft6, ft6, ft5   \n" +
                "add ft6, ft6, ft5   \n" +
                "sat ft4, ft6   \n" +
                "mov ft6, fc1   \n" +
                "sub ft6, fc1.x, ft1.x   \n" +
                "mov ft5, fc1   \n" +
                "sub ft5, fc1.x, ft1.y   \n" +
                "mul ft5, ft5, ft6   \n" +
                "mul ft5, ft5, ft1.y   \n" +
                "mul ft5, ft5, ft1.x   \n" +
                "mul ft5, ft5, fc4.x   \n" +
                "mul ft5, ft5, fc3.x   \n" +
                "add ft5, ft5, fc3.x   \n" +
                "mul ft4, ft4, ft5   \n" +
                "mov ft5, fc1   \n" +
                "mov ft5.x, fc4.y   \n" +
                "mov ft5.y, fc1.y   \n" +
                "mov ft5.z, fc4.z   \n" +
                "mul ft4, ft4, ft5   \n" +
                "mov ft5, fc1   \n" +
                "mul ft5, ft1.y, fc4.w   \n" +
                "mul ft5, ft5, fc2.y   \n" +
                "sin ft5, ft5   \n" +
                "mul ft5, ft5, fc5.y   \n" +
                "add ft5, ft5, fc5.x   \n" +
                "mul ft4, ft4, ft5   \n" +
                "mul ft4, ft4, fc2.z   \n" +
                "mov oc, ft4" 
            );
            
            mProgram = mContext3d.createProgram();
            mProgram.upload( vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);
        }
        
        
        private var mTime:Number = 0.0;
        private var resx:Number = 0;
        private var resy:Number = 0;
        private function onTick(event:Event):void
        {
            if ( !mContext3d ) 
                return;
            
            mContext3d.clear ( 0, 0, 0, 1 );
            mContext3d.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mMatrix, true);
            
            // resolution        = FC0 = [1, 1, 1, 1];
            mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>( [ 1, 1, 1, 1 ]) );
            
            // ONE                = FC1 = [1, 1, 1, 1];
            mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, Vector.<Number>( [ 1, 1, 1, 1 ]) );
            
            // TIME             = FC2
            mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 2, Vector.<Number>( [
                .9 + .1 * Math.sin(.2 * mTime), 
                10 * mTime, 
                .97 + 0.03 * Math.sin(110 * mTime),
                -1 ]) );

            // CONSTANTS 1        = FC3
            mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 3, Vector.<Number>( [ .5, .003, 0.0, 1.2 ]) );
            
            // CONSTANTS 2        = FC4
            mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 4, Vector.<Number>( [ 16, .8, 0.7, 1000 ]) );
            
            // CONSTANTS 3        = FC5
            mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 5, Vector.<Number>( [ .9, .1, 3, 2 ]) );
            
            // SMOOTHSTEP        = FC6
            var ss:Number = smoothStep(0.2, 0.7, Math.sin(mTime));
            mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 6, Vector.<Number>( [ ss, ss * 3, 1, 1 ]) );
            
            mContext3d.drawTriangles(mIndexBuffer);
            mContext3d.present();
            
            mTime += .05;
        }
        
        private function smoothStep(edge0:Number, edge1:Number, x:Number):Number
        {
            var t:Number = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
            return t * t * (3.0 - 2.0 * t);
        }
        
        private function clamp(target:Number, min:Number, max:Number):Number
        {
            if (target < min) target = min;
            if (target > max) target = max;
            return target;
        }
    }
}