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

2D Particle Random Motion for Stage3D

5000 particle random motion.
/**
 * Copyright flashisobar ( http://wonderfl.net/user/flashisobar )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/ea5D
 */

package
{
    import flash.display.Sprite;
    
    [SWF(width = "465", height = "465", frameRate = "60")]
    public class Main extends Sprite
    {
        private var particle2D:Particle2D;
        
        public function Main():void
        {
            particle2D = new Particle2D();
            addChild(particle2D);
        }
        
    }

}

    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DTextureFormat;
    import flash.display3D.Context3DTriangleFace;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.textures.Texture;
    import flash.display3D.textures.TextureBase;
    import flash.display3D.VertexBuffer3D;
    import flash.events.Event;
    import flash.utils.ByteArray;
    ///import flash.display.Bitmap;
    ///import flash.display.BitmapData;
    
    /**
     * base 3D
     * 
     * @author flashisobar
     */
    class Base3D extends Sprite 
    {
        private var _context3D:Context3D;
        private var _program:Program3D;
        ///private var sc:BitmapData = new BitmapData(465, 465, false);
        
        public function Base3D() 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            Wonderfl.disable_capture();
            //addChild(new Bitmap(sc));

            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            prepareStage3D();
        }
        
        private function prepareStage3D():void 
        {
            stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, handleContextCreate);
            stage.stage3Ds[0].requestContext3D();
        }
        
        /*
         * configureBackBuffer: enableDepthAndStencil default is true
         * enableErrorChecking: slow rendering - only turn on when developing/testing
         */
        private function handleContextCreate(e:Event):void 
        {
            _context3D = stage.stage3Ds[0].context3D;
            if (!_context3D) {
                return;
            }
            _context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 2, true);
            _context3D.setCulling(Context3DTriangleFace.BACK);
            _context3D.enableErrorChecking = true;
            _program = _context3D.createProgram();
            
            main();
            start();
        }
        
        protected function main():void 
        {
        }
        
        protected function render(e:Event = null):void 
        {
            clear();
            draw();
            ///_context3D.drawToBitmapData(sc);
            present();
        }
        
        protected function clear(__red:Number=0, __green:Number=0, __blue:Number=0, __alpha:Number=1):void {
            _context3D.clear(__red, __green, __blue, __alpha);
        }
        
        protected function draw():void 
        {
            
        }
        
        protected function present():void 
        {
            _context3D.present();
        }
        
        public function pause():void 
        {
            removeEventListener(Event.ENTER_FRAME, render);
        }
        
        public function start():void 
        {
            addEventListener(Event.ENTER_FRAME, render);
        }
        
        /*
         * 建立頂點"緩衝區"/定義頂點資料/上傳頂點資料
         * x,y,u,v        : __data32=4
         * x,y,z,u,v    : __data32=5
         * x,y,z,r,g,b    : __data32=6
         */
        public function setVertexData(__vertexData:Vector.<Number>, __data32Per:int):VertexBuffer3D
        {
            var numVertices:int = __vertexData.length/__data32Per;
            // create buffer
            var vertexBuffer3D:VertexBuffer3D = _context3D.createVertexBuffer(numVertices, __data32Per);
            vertexBuffer3D.uploadFromVector(__vertexData, 0, numVertices);
            return vertexBuffer3D;
        }
        
        /*
         * 建立索引"緩衝區"/定義索引資料/上傳索引資料
         */
        public function setIndexData(__indexData:Vector.<uint>):IndexBuffer3D
        {
            // create buffer
            var indexBuffer:IndexBuffer3D = _context3D.createIndexBuffer(__indexData.length);
            indexBuffer.uploadFromVector(__indexData, 0, __indexData.length);
            return indexBuffer;
        }
        
        /*
         * 建立貼圖材質
         */
        public function setTextureData(__bmd:BitmapData):Texture
        {
            var texture:Texture = _context3D.createTexture(__bmd.width, __bmd.height, Context3DTextureFormat.BGRA, false);
            texture.uploadFromBitmapData(__bmd);
            return texture;
        }
        
        /*
         * 設定暫存器
         */
        public function setVertexBuffer(__index:int, __buffer:VertexBuffer3D, __bufferOffset:int=0, __format:String="float4"):void
        {
            _context3D.setVertexBufferAt(__index, __buffer, __bufferOffset, __format);
        }
        
        /*
         * 設定貼圖材質取樣暫存器
         */
        public function setTexture(__sampler:int, __texture:TextureBase):void
        {
            _context3D.setTextureAt(__sampler, __texture);
        }
        
        /*
         * 設定頂點及片段著色器
         */
        public function setShaders(__vertexProgram:ByteArray, __fragmentProgram:ByteArray):void
        {
            _program.upload(__vertexProgram, __fragmentProgram);
            _context3D.setProgram(_program);
        }
        
        public function get context3D():Context3D 
        {
            return _context3D;
        }
        
        public function set context3D(value:Context3D):void 
        {
            _context3D = value;
        }
        
    }
    import com.adobe.utils.AGALMiniAssembler;
    import flash.display3D.Context3DBlendFactor;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.VertexBuffer3D;
    import flash.events.MouseEvent;
    import flash.geom.Matrix3D;
    import flash.geom.Vector3D;
    import flash.utils.ByteArray;
    import flash.utils.getTimer;
    import net.hires.debug.Stats;

    /**
     * stage3D: 5000 particles random motion
     * @author flashisobar
     */
    class Particle2D extends Base3D 
    {
        static public const NUM_PARTICLES:uint = 5000;
        private var vertexParticle:VertexBuffer3D;
        private var indexParticle:IndexBuffer3D;
        private var isStart:Boolean = true;
        private var particles:Vector.<Number> = new Vector.<Number>(NUM_PARTICLES*4);
        private var vertexShader:ByteArray;
        private var fragmentShader:ByteArray;
        private var matrix3d:Matrix3D;
        private var w:int = 400;
        private var h:int = 400;
        private var size:Number = 4;
        private var transformConstants:Vector.<Number>;
        
        public function Particle2D() 
        {
            
        }
        
        override protected function main():void
        {
            this.addChild(new Stats);
            
            var vertices:Vector.<Number> = new Vector.<Number>();
            var index:Vector.<uint> = new Vector.<uint>();
            var r:Number, g:Number, b:Number, color:Number;
            var s:uint;
            var xPos:Number, yPos:Number;
            var idx:uint = 0;
            var stime:int = getTimer();
            for (var i:int = 0; i < NUM_PARTICLES; i++) {
                xPos = (Math.random() - 0.5) * w * 2;
                yPos = (Math.random() - 0.5) * h * 2;
                color = Math.random() * 0xFFFFFF;
                r = (color >> 16) / 255;
                g = (color >> 8 & 0xFF) / 255;
                b = (color & 0xFF) / 255;
                vertices.push(xPos - size, yPos + size, r, g, b);
                vertices.push(xPos + size, yPos + size, r, g, b);
                vertices.push(xPos + size, yPos - size, r, g, b);
                vertices.push(xPos - size, yPos - size, r, g, b);

                s = 4 * i;
                index.push(s, s + 1, s + 2, s + 2, s + 3, s);
            }
            vertexParticle = setVertexData(vertices, 5);
            indexParticle = setIndexData(index);
            trace("Time:" + (getTimer() - stime));
            
            // set register
            setVertexBuffer(0, vertexParticle, 0, Context3DVertexBufferFormat.FLOAT_2); // register0: va0(xy)
            setVertexBuffer(1, vertexParticle, 2, Context3DVertexBufferFormat.FLOAT_3); // register1: va1(color)
            
            // set constants for setProgramConstantsFromMatrix
            transformConstants = new <Number>[1, 1, 1, 1];
            var len:int = NUM_PARTICLES * 4;
            for (i = 0; i < len; i) {
                particles[i++] = -300 + 600 * Math.random();
                particles[i++] = -300 + 600 * Math.random();
                particles[i++] = 1000 + 3000 * Math.random();
                particles[i++] = 1;
            }
            
            // AGAL code
            var assembler:AGALMiniAssembler = new AGALMiniAssembler();
            var code:String = '';
            code += "mov vt0, va0\n";                // get vertex position
            code += "mov vt1.x vc4.z\n";            // vt1.x = getTimer()/1000;
            code += "frc vt1.x vt1.x\n";            // vt1.x = get value from 0 to 1
            code += "mul vt1.xy vc5.xy vt1.xx\n";    // vt1.xy = vc5.xy * vt1.xx;
            code += "add vt0.xy vt0.xy vt1.xy\n";    // move: vt0.xy = vt0.xy + vt1.xy
            code += "m44 op, vt0, vc0\n";            // m44: vt0 * vc0
            code += "mov v0, va1\n";
            vertexShader = assembler.assemble(Context3DProgramType.VERTEX, code);
            
            code = "mov oc, v0";                    // output color: v0
            fragmentShader = assembler.assemble(Context3DProgramType.FRAGMENT, code);
            setShaders(vertexShader, fragmentShader);
            
            // set projection view or scale
            matrix3d = new Matrix3D();
            //matrix3d.appendRotation(45, Vector3D.Z_AXIS);
            matrix3d.appendScale(1 / w, 1 / h, 1);

            context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix3d, true); // vc0,vc1,vc2,vc3

            stage.addEventListener(MouseEvent.CLICK, createParticles);
        }
        
        private function createParticles(e:MouseEvent = null):void 
        {
            isStart = !isStart;
        }
        
        private function createParticle(xPos:Number, yPos:Number, color:uint):Vector.<Number>
        {
            var r:Number = (color >> 16) / 255;
            var g:Number = (color >> 8 & 0xFF) / 255;
            var b:Number = (color & 0xFF) / 255;
            return Vector.<Number>([xPos - size, yPos + size, r, g, b, xPos + size, yPos + size, r, g, b, xPos + size, yPos - size, r, g, b, xPos - size, yPos - size, r, g, b]);
        }
        
        override protected function draw():void
        {
            if (!isStart)
            {
                return;
            }
            context3D.clear(.4);
            
            var g:Number = getTimer();
            for (var i:int = 0; i < NUM_PARTICLES * 4; i = i + 4) {
                transformConstants[2] =  g / particles[i + 2];    // z
                context3D.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 4, transformConstants); // vc4
                context3D.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 5, new <Number>[particles[i], particles[i+1], particles[i+2], particles[i+3]]); // vc5
                context3D.drawTriangles(indexParticle, 6 * i/4, 2); // 從 0 開始,畫兩個三角形
            }
        }
    }