Caustics

by devon_o
♥3 | Line 184 | Modified 2013-08-30 21:46:36 | MIT License
play

ActionScript3 source code

/**
 * 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/hzeT
 */

package
{
    import com.adobe.utils.AGALMiniAssembler;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.VertexBuffer3D;
    import flash.events.Event;
    import flash.geom.Matrix3D;
    
    /**
     * Ported from: http://glsl.heroku.com/e#10585.0
     * @author Devon O.
     */

    [SWF(width="465", height="465", frameRate="60", backgroundColor="#000000")]
    public class Caustics extends Sprite
    {
        
        private static const FRAGMENT_SHADER:String =
    <![CDATA[
        //vec2 p = surfacePosition*8.0- vec2(20.0);
        mul ft0.xy, v0.xy, fc0.xx
        sub ft0.xy, ft0.xy, fc0.yy
        
        //vec2 i = p;
        mov ft1.xy, ft0.xy
        
        //float c = 1.0;
        mov ft1.z, fc0.w
        
        // ft0.w = n
        mov ft0.w, fc0.w
        //for (int n = 0; n < MAX_ITER; n++) 
            //--------LOOP 1----------
            //float t = time * (1.0 - (3.0 / n));
            div ft2.x, fc1.y, ft0.w
            sub ft2.x, fc0.w, ft2.x
            mul ft2.x, ft2.x, fc1.x
            
            //i = p + vec2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x));
            mov ft6.xy, ft1.xy
            sub ft3.x, ft2.x, ft6.x
            cos ft3.x, ft3.x
            add ft3.y, ft2.x, ft6.y
            sin ft3.y, ft3.y
            add ft1.x, ft3.x, ft3.y
            
            sub ft3.z, ft2.x, ft6.y
            sin ft3.z, ft3.z
            add ft3.w, ft2.x, ft6.x
            cos ft3.w, ft3.w
            add ft1.y, ft3.z, ft3.w
            
            //c += 1.0/length(vec2(p.x / (sin(i.x+t)/inten),   p.y / (cos(i.y+t)/inten)));
            add ft3.x, ft1.x, ft2.x
            sin ft3.x, ft3.x
            div ft3.x, ft3.x, fc0.z
            div ft3.x, ft0.x, ft3.x
            
            add ft3.y, ft1.y, ft2.x
            cos ft3.y, ft3.y
            div ft3.y, ft3.y, fc0.z
            div ft3.y, ft0.y, ft3.y
            
            dp3 ft3.x, ft3.xy, ft3.xy
            sqt ft3.x, ft3.x
            rcp ft3.x, ft3.x
            add ft1.z, ft1.z, ft3.x
            
            // increment loop counter
            add ft0.w, ft0.w, fc0.w
            
            //--------LOOP 2-----------
            //float t = time * (1.0 - (3.0 / n));
            div ft2.x, fc1.y, ft0.w
            sub ft2.x, fc0.w, ft2.x
            mul ft2.x, ft2.x, fc1.x
            
            //i = p + vec2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x));
            mov ft6.xy, ft1.xy
            sub ft3.x, ft2.x, ft6.x
            cos ft3.x, ft3.x
            add ft3.y, ft2.x, ft6.y
            sin ft3.y, ft3.y
            add ft1.x, ft3.x, ft3.y
            
            sub ft3.z, ft2.x, ft6.y
            sin ft3.z, ft3.z
            add ft3.w, ft2.x, ft6.x
            cos ft3.w, ft3.w
            add ft1.y, ft3.z, ft3.w
            
            //c += 1.0/length(vec2(p.x / (sin(i.x+t)/inten),   p.y / (cos(i.y+t)/inten)));
            add ft3.x, ft1.x, ft2.x
            sin ft3.x, ft3.x
            div ft3.x, ft3.x, fc0.z
            div ft3.x, ft0.x, ft3.x
            
            add ft3.y, ft1.y, ft2.x
            cos ft3.y, ft3.y
            div ft3.y, ft3.y, fc0.z
            div ft3.y, ft0.y, ft3.y
            
            dp3 ft3.x, ft3.xy, ft3.xy
            sqt ft3.x, ft3.x
            rcp ft3.x, ft3.x
            add ft1.z, ft1.z, ft3.x
            
            // increment loop counter
            add ft0.w, ft0.w, fc0.w
            
            //--------LOOP 3----------
            //float t = time * (1.0 - (3.0 / n));
            div ft2.x, fc1.y, ft0.w
            sub ft2.x, fc0.w, ft2.x
            mul ft2.x, ft2.x, fc1.x
            
            //i = p + vec2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x));
            mov ft6.xy, ft1.xy
            sub ft3.x, ft2.x, ft6.x
            cos ft3.x, ft3.x
            add ft3.y, ft2.x, ft6.y
            sin ft3.y, ft3.y
            add ft1.x, ft3.x, ft3.y
            
            sub ft3.z, ft2.x, ft6.y
            sin ft3.z, ft3.z
            add ft3.w, ft2.x, ft6.x
            cos ft3.w, ft3.w
            add ft1.y, ft3.z, ft3.w
            
            //c += 1.0/length(vec2(p.x / (sin(i.x+t)/inten),   p.y / (cos(i.y+t)/inten)));
            add ft3.x, ft1.x, ft2.x
            sin ft3.x, ft3.x
            div ft3.x, ft3.x, fc0.z
            div ft3.x, ft0.x, ft3.x
            
            add ft3.y, ft1.y, ft2.x
            cos ft3.y, ft3.y
            div ft3.y, ft3.y, fc0.z
            div ft3.y, ft0.y, ft3.y
            
            dp3 ft3.x, ft3.xy, ft3.xy
            sqt ft3.x, ft3.x
            
            rcp ft3.x, ft3.x
            add ft1.z, ft1.z, ft3.x
    //}
    //c /= float(MAX_ITER);
    div ft1.z, ft1.z, fc1.w
    
    //c = 1.5-sqrt(c);
    sqt ft1.z, ft1.z
    sub ft1.z, fc1.z, ft1.z
    
    //gl_FragColor = vec4(vec3(c*c*c*c), 1.0);
    mov ft4.xyz, ft1.zzz
    // crank up the blue
    add ft4.z, ft4.z, fc1.z
    mov ft4.w, fc0.w
    
    mov oc, ft4
    ]]>
        
        
        private var mContext3d:Context3D;
        private var mVertBuffer:VertexBuffer3D;
        private var mIndexBuffer:IndexBuffer3D; 
        private var mProgram:Program3D;
        
        private var mMatrix:Matrix3D = new Matrix3D();
        
        public function Caustics()
        {    
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);    
        }
        
        private function init(event:Event = null):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            initStage();
            setS3d();
    
            addEventListener(Event.ENTER_FRAME, onTick);
        }
        
        
        private function setS3d():void
        {
            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.configureBackBuffer(stage.stageWidth, stage.stageHeight, 1, true);
            
            var vertices:Vector.<Number> = Vector.<Number>([
            //    x        y        z            u     v
                -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);
    
            mContext3d.setVertexBufferAt(0, mVertBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
            mContext3d.setVertexBufferAt(1, mVertBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
            generateProgram();
            
            mContext3d.setProgram(mProgram);
        }
        
        
        private function generateProgram():void
        {
            var vertexShaderAssembler : AGALMiniAssembler = new AGALMiniAssembler();
            vertexShaderAssembler.assemble( Context3DProgramType.VERTEX,
                "m44 op, va0, vc0                                \n" +
                "mov v0, va1                                      "
            );
            
            var fragmentShaderAssembler : AGALMiniAssembler= new AGALMiniAssembler();
            fragmentShaderAssembler.assemble( Context3DProgramType.FRAGMENT, FRAGMENT_SHADER);
            
            mProgram = mContext3d.createProgram();
            mProgram.upload( vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);
        }
        
        
        private var mTime:Number = 0.0;
        private function onTick(event:Event):void
        {
            if ( !mContext3d ) 
                return;
            
            mContext3d.clear ( 0, 0, 0, 1 );
            mContext3d.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mMatrix, true);
            
            mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>( [ 6, 15, .05, 1 ]) );    
            mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, Vector.<Number>( [ mTime, 3, 1.25, 3 ]) );
            
            mContext3d.drawTriangles(mIndexBuffer);
            mContext3d.present();
            
            mTime += .015;
            
        }
        
    }
}