AGAL Pulse FX
/**
* 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/sZILY
*/
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 Pulse effect
* based on: http://www.iquilezles.org/apps/shadertoy/?p=pulse
*/
[SWF(width="465", height="465", frameRate="60", backgroundColor="#000000")]
public class Pul 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 Pul()
{
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();
mxposSpeed = randRange(4, 1);
myposSpeed = randRange(4, 1);
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> ([
// X, Y, Z, r, g, b, u, v, cx, cy, flag
-1.0, -1.0, 0.0, 1, 1, 0, 0, 0, 0.2, 0.4, 1.0,
1.0, -1.0, 0.0, 1, 0, 1, 1, 0, 0.2, 0.4, 1.0,
1.0, 1.0, 0.0, 0, 1, 1, 1, 1, 0.2, 0.4, 1.0,
-1.0, 1.0, 0.0, 1, 1, 1, 0, 1, 0.2, 0.4, 1.0
]);
mVertBuffer = mContext3d.createVertexBuffer(vertices.length / 11, 11);
mVertBuffer.uploadFromVector(vertices, 0, vertices.length / 11);
mContext3d.setVertexBufferAt( 0, mVertBuffer, 0, Context3DVertexBufferFormat.FLOAT_3 );
mContext3d.setVertexBufferAt( 1, mVertBuffer, 6, Context3DVertexBufferFormat.FLOAT_2 );
mContext3d.setVertexBufferAt( 2, mVertBuffer, 3, Context3DVertexBufferFormat.FLOAT_3 );
mContext3d.setVertexBufferAt( 3, mVertBuffer, 8, Context3DVertexBufferFormat.FLOAT_3 );
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);
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" +
"mov v0, va1 \n" +
"mov v1, va2 \n" +
"mov v2, va3"
);
var fragmentShaderAssembler : AGALMiniAssembler= new AGALMiniAssembler();
fragmentShaderAssembler.assemble( Context3DProgramType.FRAGMENT,
"mul ft5, v0, fc3.w \n" +
"mul ft5, ft5, fc6.z \n" +
"mov ft0, v0.xy \n" +
"mul ft4, fc3.x, ft5.x \n" +
"mul ft4, ft4, fc2.x \n" +
"mul ft6, fc3.y, ft5.x \n" +
"mul ft6, ft6, fc2.z \n" +
"add ft6, ft4, ft6 \n" +
"add ft6, ft6, ft5.x \n" +
"sub ft0.x, ft0.x, ft6.x \n" +
"add ft0.x, ft0.x, fc4.x \n" +
"mul ft4, fc3.z, ft5.y \n" +
"mul ft4, ft4, fc2.y \n" +
"mul ft6, fc3.y, ft5.y \n" +
"mul ft6, ft6, fc2.z \n" +
"add ft6, ft4, ft6 \n" +
"add ft6, ft6, ft5.y \n" +
"sub ft0.y, ft0.y, ft6.y \n" +
"sub ft0.y, ft0.y, fc4.y \n" +
"dp3 ft1, ft0, ft0 \n" +
"sqt ft1, ft1 \n" +
"div ft4, v0.xy, fc8.xy \n" +
"div ft5, ft0, ft1 \n" +
"div ft6, ft1, fc6.y \n" +
"sub ft6, ft6, fc6.w \n" +
"sin ft6, ft6 \n" +
"mul ft6, ft6, ft5 \n" +
"div ft6, ft6, fc6.x \n" +
"add ft2, ft4, ft6 \n" +
"tex ft4, ft2, fs0<2d, repeat, linear, nomip> \n" +
"mul ft4, ft4.xyz, fc6.z \n" +
"div ft4, ft4, ft1 \n" +
"mov oc, ft4"
);
mProgram = mContext3d.createProgram();
mProgram.upload( vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);
}
private var mTime:Number = 0.0;
private var mxpos:Number = Math.random() * 800;
private var mypos:Number = Math.random() * 600;
private var mxposSpeed:Number;
private var myposSpeed:Number ;
private function onTick(event:Event):void
{
if ( !mContext3d )
return;
mContext3d.clear ( 0, 0, 0, 1 );
mContext3d.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mMatrix, true);
// ONE = FC1 = [1, 1, 1, 1];
mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, Vector.<Number>( [ 1, 1, 1, 1 ]) );
//time = FC2 = [sin(time / 2), sin(time / 5), cos(time), time]
mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 2, Vector.<Number>( [
Math.sin(mTime / 2.0),
Math.sin(mTime / 5.0),
Math.cos(mTime),
mTime]) );
// position
var xpos:Number = (mxpos / stage.stageWidth) * 128;
var ypos:Number = ((mypos / stage.stageHeight) * 128) - 128;
mxpos += mxposSpeed;
mypos += myposSpeed;
if (mxpos > stage.stageWidth)
{
mxposSpeed *= -1;
mxpos = stage.stageWidth;
}
if ( mxpos < 0)
{
mxposSpeed *= -1;
mxpos = 0;
}
if (mypos > stage.stageHeight)
{
myposSpeed *= -1;
mypos = stage.stageHeight;
}
if (mypos < 0)
{
myposSpeed *= -1;
mypos = 0;
}
mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 4, Vector.<Number>([ xpos, ypos, 1, 1 ]) );
// constants1 = FC 3 = [.5, .3, .4, 2]
mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 3, Vector.<Number>([ .50, .3, .4, 2.0 ]) );
// constants = FC6 = [25.0, 30.0, 50.0, time * 10]
mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 6, Vector.<Number>([ 25, 10, 50, mTime * 10 ]) );
// resolution = FC8 = [1, 1, 1, 1];
mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 8, Vector.<Number>( [ .5, .5, 1, 1 ]) );
mTime += .025;
mContext3d.drawTriangles(mIndexBuffer);
mContext3d.present();
}
private function randRange(max:Number, min:Number = 0, decimals:int = 0):Number {
if (min > max) return NaN;
var rand:Number = Math.random() * (max - min) + min;
var d:Number = Math.pow(10, decimals);
return ~~((d * rand) + 0.5) / d;
}
}
}