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 zoom blur filter, polar coordinates

Get Adobe Flash player
by makc3d 14 May 2012
/**
 * Copyright makc3d ( http://wonderfl.net/user/makc3d )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/6SVH
 */

// forked from makc3d's AGAL zoom blur filter
package {
  
  import flash.display.*;
  import com.bit101.components.*;
  import flash.display3D.textures.Texture;
  import flash.display3D.*;
  import flash.events.Event;
  import com.adobe.utils.AGALMiniAssembler;
  import flash.geom.Matrix3D;
  import flash.net.URLRequest;
  import flash.system.LoaderContext;
  
  /**
   * Yet another attempt using polar coordinates.
   */
  public class Filter extends Sprite {
    private var image : BitmapData ;
    private var strength : HSlider ;
    private var stage3d : Stage3D ;
    private var texture : Texture ;
    private var quadIndices : IndexBuffer3D ;
    private var quadVertices : VertexBuffer3D ;
    public function Filter(  ){
      var loader : Loader = new Loader();
      loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImage);
      loader.load(new URLRequest("http://farm3.static.flickr.com/2784/4272833528_33ab1e208c.jpg"), new LoaderContext(true));
    }
    private function onImage ( e : Event ) : void {
      var info : LoaderInfo = e.target as LoaderInfo;
      info.removeEventListener(Event.COMPLETE, onImage);
      image = (info.content as Bitmap).bitmapData;
      
      stage.scaleMode = StageScaleMode.NO_SCALE;
      stage.align = StageAlign.TOP_LEFT;
      
      stage3d = stage.stage3Ds[0];
      stage3d.addEventListener(Event.CONTEXT3D_CREATE, onContext);
      stage3d.requestContext3D();
    }
    private function onContext ( e : Event ) : void {
      stage3d.removeEventListener(Event.CONTEXT3D_CREATE, onContext);
      
      quadIndices = stage3d.context3D.createIndexBuffer(6);
      quadIndices.uploadFromVector(Vector.<uint>([0, 2, 1, 1, 2, 3]), 0, 6);
      
      quadVertices = stage3d.context3D.createVertexBuffer(4, 4);
      quadVertices.uploadFromVector(Vector.<Number>([-1, -1, 0, 1, -1, 1, 0, 0, 1, -1, 1, 1, 1, 1, 1, 0]), 0, 4);
      stage3d.context3D.setVertexBufferAt(0, quadVertices, 0, Context3DVertexBufferFormat.FLOAT_2);
      stage3d.context3D.setVertexBufferAt(1, quadVertices, 2, Context3DVertexBufferFormat.FLOAT_2);
      
      texture = stage3d.context3D.createTexture(512, 512, Context3DTextureFormat.BGRA, false);
      texture.uploadFromBitmapData(image);
      stage3d.context3D.setTextureAt(0, texture);
      
      strength = new HSlider(this, 10, 150);
	  strength.minimum = 1;
	  strength.maximum = 23;
	  strength.tick = 0.1;
	  strength.value = 10;
	  
      new PushButton(this, 10, 180, "apply", applyFilter);
	  new Label(this, int(0.4 * 512) - 2, int(0.6 * 512) - 10, "x Center");
    }
    private function applyFilter ( e : * = null ) : void {
      while ( numChildren > 0 ) {
        removeChildAt(0);
      }
      
      var vshader : AGALMiniAssembler = new AGALMiniAssembler();
      vshader.assemble(Context3DProgramType.VERTEX, "m44 op, va0, vc0\nmov v0, va1\n");
      
      
      var fconstants : Vector.<Number> = new <Number> [
		0.4 /* center x (u) */,
		0.6 /* center y (v) */,
		strength.value /* p > 1, to compress image radially */,
		0,
		2.220446049250313e-16, 0.7853981634, 0.1821, 0.9675 /* atan2 magic numbers */,
		Math.PI, 2*Math.PI, 0, 0
	  ];
      
      var fshader : AGALMiniAssembler = new AGALMiniAssembler();
      fshader.assemble(Context3DProgramType.FRAGMENT,
		/* inverse polar coords calculation: r(u), phi(v) */
		"mov ft0, v0\n" +
		"mul ft0.y, ft0.y, fc2.y\n" +
		"sub ft0.y, ft0.y, fc2.x\n" /* ft0.y = phi in -pi..pi */ +
		"cos ft1.x, ft0.y\n" +
		"sin ft1.y, ft0.y\n" +
		"mul ft0.x, ft0.x, fc0.z\n" /* ft0.x = normalized radius */ +
		"mul ft1.xy, ft1.xy, ft0.xx\n" +
		"add ft1.xy, ft1.xy, fc0.xy\n" +
		"mov ft1.zw, fc2.xy\n" +
		"tex oc, ft1, fs0<2d,clamp,linear>\n"
	  );
      
      var program : Program3D = stage3d.context3D.createProgram();
      program.upload(vshader.agalcode, fshader.agalcode);
      stage3d.context3D.setProgram(program);
	  
      fshader.assemble(Context3DProgramType.FRAGMENT,
		"sub ft0, v0, fc0\n" +
		"sub ft0.zw, ft0.zw, ft0.zw\n" /* ft0 = radius vector */  +
		
		"dp3 ft1, ft0, ft0\n" +
		"sqt ft1, ft1\n" +
		"div ft1.x, ft1.x, fc0.z\n" /* ft1.x = normalized radius */ +
		
		/* atan2, see http://wonderfl.net/c/mS2W/read */
		"abs ft2, ft0\n" +
		"sge ft2, ft0, ft2\n" +
		"add ft2.xyw, ft2.xyw, ft2.xyw\n" +
		"sub ft2.xy, ft2.xy, ft2.zz\n" +
		"sub ft2.w, ft2.w, ft2.x\n" +
		"mul ft2.w, ft2.w, fc1.y\n" +
		"mul ft2.z, ft2.y, ft0.y\n" +
		"add ft2.z, ft2.z, fc1.x\n" +
		"mul ft3.x, ft2.x, ft2.z\n" +
		"sub ft3.x, ft0.x, ft3.x\n" +
		"mul ft3.y, ft2.x, ft0.x\n" +
		"add ft3.y, ft3.y, ft2.z\n" +
		"div ft2.z, ft3.x, ft3.y\n" +
		"mul ft3.x, ft2.z, ft2.z\n" +
		"mul ft3.x, ft3.x, fc1.z\n" +
		"sub ft3.x, ft3.x, fc1.w\n" +
		"mul ft3.x, ft3.x, ft2.z\n" +
		"add ft3.x, ft3.x, ft2.w\n" +
		"mul ft3.x, ft3.x, ft2.y\n" +
		
		/* ft3.x = -pi..pi -> 0..1 */
		"add ft3.x, ft3.x, fc2.x\n" +
		"div ft1.y, ft3.x, fc2.y\n" +
		
		"sub ft1.zw, ft1.zw, ft1.zw\n" +
		"tex oc, ft1, fs0<2d,clamp,linear>\n"
	  );
      
      var program2 : Program3D = stage3d.context3D.createProgram();
      program2.upload(vshader.agalcode, fshader.agalcode);
      
      stage3d.context3D.configureBackBuffer(512, 512, 0);
	  var tmp:Texture = stage3d.context3D.createTexture (512, 512, Context3DTextureFormat.BGRA, true);
	  stage3d.context3D.setRenderToTexture (tmp);
      stage3d.context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, new Matrix3D());
      stage3d.context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, fconstants, fconstants.length / 4);
      stage3d.context3D.clear(0, 0, 0, 1);
      stage3d.context3D.drawTriangles(quadIndices);
	  
	  // now apply inverse transform
      stage3d.context3D.setRenderToBackBuffer();
      stage3d.context3D.setProgram(program2);
	  stage3d.context3D.setTextureAt (0, tmp);
      stage3d.context3D.clear(0, 0, 0, 1);
      stage3d.context3D.drawTriangles(quadIndices);
      stage3d.context3D.present();
    }
  }
}