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

Stage3D Smoke

Bigger version and Javascript/webgl version on my blog : 
http://blog.bongiovi.tw/?p=418
Get Adobe Flash player
by bongiovi015 31 Jul 2012
    Embed
/**
 * Copyright bongiovi015 ( http://wonderfl.net/user/bongiovi015 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/5Cfp
 */

package {
    import com.bit101.components.HSlider;
    import com.bit101.components.Label;
    import com.bit101.components.Window;
    
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DBlendFactor;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DTextureFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.VertexBuffer3D;
    import flash.display3D.textures.Texture;
    import flash.events.Event;
    import flash.geom.Matrix;
    import flash.geom.Matrix3D;
    import flash.geom.Point;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    
    import net.hires.debug.Stats;
    
    [SWF(width=465, height=465, frameRate=60, backgroundColor=0)]
    public class Smoke extends Sprite {
        public static const URL_LIGHT : String = "http://www.bongiovi.tw/experiments/smokes/bridgeLight512.png";
        public static const URL_BG : String = "http://www.bongiovi.tw/experiments/smokes/bridgeBG512.jpg";
        
        private var context:Context3D;
        //    PERLIN NOISE
        private var _bmpdPerlin:BitmapData;
        private var _seed:int = Math.random() * 0xFFFF;
        private var _offset:Array = [new Point, new Point];
        
        //    BITMAPDATAS AND TEXTURES
        private var _bmpdLight:BitmapData;
        private var _bmpdBg:BitmapData;
        private var _textureOrg:Texture;
        private var _textureBg:Texture;
        
        //    SHADER PROGRAMS
        private var _passCopy:Pass;
        private var _passCopyToTexture:Pass;
        private var _passAdd:Pass;
        private var _passDecrease:Pass;
        private var _passDisplace:Pass;
        
        //    BUFFERS
        private var vbuffer:VertexBuffer3D;
        private var ibuffer:IndexBuffer3D;
        
        //    OTHERS AND CONTROLS
        private var _isFirstTime:Boolean = true;
        private var _preTexture:Texture;
        private var _sliderRange:HSlider;
        private var _sliderDescrease:HSlider;
        private var _sliderSpeed:HSlider;
        
        
        
        public function Smoke() {
            stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, _onContext);
            stage.stage3Ds[0].requestContext3D();
            
            addChild(new Stats).y = 465 - 100;
        }
        
        protected function _onContext(event:Event):void {
            context = stage.stage3Ds[0].context3D;
            context.configureBackBuffer(465, 465, 1, false);
            context.enableErrorChecking = true;
            context.setBlendFactors( Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA);
            
            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, _onBgLoaded);
            loader.load(new URLRequest(URL_BG), new LoaderContext(true));

        }
        
        private function _onBgLoaded(event:Event):void {
            _bmpdBg = event.currentTarget.content.bitmapData;
            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, _onLightLoaded);
            loader.load(new URLRequest(URL_LIGHT), new LoaderContext(true));
        }
        
        private function _onLightLoaded(event:Event):void {
            _bmpdLight = event.currentTarget.content.bitmapData;
            
            _initTexture();
            _initPerlin();
            _initBuffer();
            _initShader();
            _initControl();

            addEventListener(Event.ENTER_FRAME, _loop);
        }
        
        private function _initControl():void {
            var window:Window = new Window(this, 255, 5, "Controls");
            window.width = 200;
            window.height = 80;
            _sliderRange = new HSlider(window.content, 5, 5);
            _sliderRange.value = 4;
            new Label(window.content, 110, 0, "Smoke Range");
            _sliderDescrease = new HSlider(window.content, 5, 25);
            _sliderDescrease.value = 5;
            new Label(window.content, 110, 20, "Alpha Decrease");
            _sliderSpeed = new HSlider(window.content, 5, 45);
            _sliderSpeed.value = 50;
            new Label(window.content, 110, 40, "Movement Speed");
        }
        
        private function _initPerlin():void {
            _bmpdPerlin = new BitmapData(128, 128, false, 0);
        }
        
        private function _initShader():void {
            _passCopy = new PassCopy(context, true, false).assemble();
            _passCopyToTexture = new PassCopy(context, false, true, 512, 512).assemble();
            _passAdd = new PassAdd(context, false, true, 512, 512).assemble();
            _passDecrease = new PassColorAdd(context, false, true, 512, 512).assemble();
            _passDisplace = new PassDisplacement(context, false, true, 512, 512).assemble();
        }
        
        private function _initBuffer():void {
            ibuffer = context.createIndexBuffer(6);
            ibuffer.uploadFromVector(Vector.<uint>([0, 1, 2, 0, 2, 3]), 0, 6);
            
            vbuffer = context.createVertexBuffer(4, 5);
            var imageSize:Number = 1;
            var vbuf:Vector.<Number> = Vector.<Number>([
                -imageSize,   imageSize, 0,        0, 0,
                imageSize,   imageSize, 0,        1, 0,
                imageSize,  -imageSize, 0,        1, 1,
                -imageSize,  -imageSize, 0,        0, 1
            ]);
            vbuffer.uploadFromVector(vbuf, 0, 4);
        }
        
        private function _initTexture():void {
            _textureOrg = createTexture(context, _bmpdLight);
            _textureBg = createTexture(context, _bmpdBg);
        }
        
        private function _loop(event:Event):void {
            _bmpdPerlin.perlinNoise(_bmpdPerlin.width, _bmpdPerlin.height, 8, _seed, false, false, 3, false, _offset);
            var texturePerlin:Texture = createTexture(context, _bmpdPerlin);
            var texture:Texture;
            var mtx:Matrix3D = new Matrix3D();
            
            context.setVertexBufferAt(0, vbuffer, 0, "float3");
            context.setVertexBufferAt(1, vbuffer, 3, "float2");
            
            
            if(!_isFirstTime) {
                context.setTextureAt(0, _preTexture);
                context.setTextureAt(1, _textureOrg);
                _passAdd.render(ibuffer);
                texture = _passAdd.getTexture(); 
            }
            
            var numIter:int = 10;
            var range:Number = _sliderRange.value / 4000 + 0.002;
            var alphaDecrease:Number = _sliderDescrease.value / 4000 + .004;
            for(var i:int=0; i<numIter; i++)  {
                context.setTextureAt(0, texture == null ? _textureOrg : texture);
                context.setTextureAt(1, texturePerlin);
                context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([-.5, -.5, range, 1-i/numIter*alphaDecrease]) );
                _passDisplace.render(ibuffer);
                
                context.setTextureAt(1, null);
                context.setTextureAt(0, _passDisplace.getTexture());
                context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mtx, true);
                _passCopyToTexture.render(ibuffer);
                texture = _passCopyToTexture.getTexture();
            }
            
            context.setTextureAt(0, texture);
            context.setTextureAt(1, null);
            
            context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([0, 0, 0, -0.02]));
            _passDecrease.render(ibuffer);
            
            _preTexture = _passDecrease.getTexture();
            context.setTextureAt(0, _preTexture);
            context.setTextureAt(1, _textureBg);
            _passAdd.render(ibuffer);
            
            context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mtx, true);
            context.setVertexBufferAt(0, vbuffer, 0, "float3");
            context.setVertexBufferAt(1, vbuffer, 3, "float2");
            context.setTextureAt(0, _passAdd.getTexture());
            context.setTextureAt(1, null);
            _passCopy.render(ibuffer);
            context.present();
            
            var speed:Number = _sliderSpeed.value/100 + .1;
            _offset[0].x += speed;
            _offset[1].y += speed;
            _isFirstTime = false;
        }
        
        
        public static function createTexture(context:Context3D, source:BitmapData) : Texture {
            var w:Number, h:Number, level:int=0;
            w = source.width, h = source.height;
            var texture:Texture = context.createTexture(w, h, Context3DTextureFormat.BGRA, true);
            var bmpd:BitmapData;
            var mtx:Matrix = new Matrix;
            while(w&&h) {
                bmpd = new BitmapData(w, h, true, 0);
                bmpd.draw(source, mtx, null, null, null, true);
                texture.uploadFromBitmapData(bmpd, level);
                w >>= 1;
                h >>= 1;
                mtx.scale(.5, .5);
                level++;
            }
            bmpd.dispose();
            return texture;
        }
    }
}


import com.adobe.utils.AGALMiniAssembler;

import flash.display3D.Context3D;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DTextureFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.display3D.textures.Texture;
import flash.utils.ByteArray;

class Pass {
    protected static const agal:AGALMiniAssembler = new AGALMiniAssembler();
    protected var _shaderVertex:String;
    protected var _shaderFragment:String;
    protected var _program:Program3D;
    protected var _context:Context3D;
    protected var _isRenderBackToBuffer:Boolean;
    protected var _isRenderToTexture:Boolean;
    protected var _texture:Texture;
    
    
    public function Pass(context:Context3D, isRenderBackToBuffer:Boolean, isRenderToTexture:Boolean, width:Number=1, height:Number=1) {
        _context = context;
        _isRenderBackToBuffer = isRenderBackToBuffer;
        _isRenderToTexture = isRenderToTexture;
        if(_isRenderToTexture) _texture = _context.createTexture(width, height, Context3DTextureFormat.BGRA, true);
    }
    
    
    public function assemble() : Pass {
        var vertexShader:ByteArray = agal.assemble(Context3DProgramType.VERTEX, _shaderVertex);
        var fragmentShader:ByteArray = agal.assemble(Context3DProgramType.FRAGMENT, _shaderFragment);
        _program = _context.createProgram();
        _program.upload(vertexShader, fragmentShader);
        return this;
    }
    
    
    public function render(iBuffer:IndexBuffer3D) : void {
        if(_isRenderBackToBuffer)     _context.setRenderToBackBuffer();
        else    _context.setRenderToTexture(_texture, false, 1);
        
        _context.clear(0, 0, 0, 0);
        _context.setProgram(_program);
        _context.drawTriangles(iBuffer);
    }
    
    public function getTexture() : Texture {    return _texture;    }
}



import flash.display3D.Context3D;

class PassCopy extends Pass {
    
    public function PassCopy(context:Context3D, isRenderBackToBuffer:Boolean, isRenderToTexture:Boolean, width:Number=1, height:Number=1) {
        super(context, isRenderBackToBuffer, isRenderToTexture, width, height);
        
        _shaderVertex = "" +
            "m44 op, va0, vc0\n" +
            "mov v0, va1\n";
        
        _shaderFragment = "" +
            "tex oc, v0, fst0, <2s, clamp, linear>\n";
    }
}



import flash.display3D.Context3D;

class PassAdd extends Pass {
    public function PassAdd(context:Context3D, isRenderBackToBuffer:Boolean, isRenderToTexture:Boolean, width:Number=1, height:Number=1) {
        super(context, isRenderBackToBuffer, isRenderToTexture, width, height);
        
        _shaderVertex = "" +
            "mov op, va0\n" +
            "mov v0, va1\n";
        
        //    fs0:texture0;
        //    fst1:texture1;
        _shaderFragment = "" +
            "tex ft0, v0, fs0, <2d, clamp, linear>\n" +
            "tex ft1, v0, fs1, <2d, clamp, linear>\n" +
            "add oc, ft0, ft1\n";
    }
}


import flash.display3D.Context3D;


class PassColorAdd extends Pass {
    public function PassColorAdd(context:Context3D, isRenderBackToBuffer:Boolean, isRenderToTexture:Boolean, width:Number=1, height:Number=1) {
        super(context, isRenderBackToBuffer, isRenderToTexture, width, height);
        _shaderVertex = "" +
            "mov op, va0\n" +
            "mov v0, va1\n";
        
        _shaderFragment = "" +
            "tex ft0, v0, fs0, <2d,clamp,linear>\n" +
            "add oc, ft0, fc0\n";
    }
}


import flash.display3D.Context3D;


class PassDisplacement extends Pass {
    
    public function PassDisplacement(context:Context3D, isRenderBackToBuffer:Boolean, isRenderToTexture:Boolean, width:Number=1, height:Number=1) {
        super(context, isRenderBackToBuffer, isRenderToTexture, width, height);
        
        _shaderVertex = "" +
            "mov op, va0\n" +
            "mov v0, va1\n";
        
        //            fc0 : [-.5, -.5, .5, .8];
        _shaderFragment = "" +
            "tex ft0, v0, fs1, <2d,clamp,linear>\n" +            //     map perlin(fs1) to ft0
            "add ft1, ft0, fc0\n" +                                //     displacement ( x-.5, y-.5)
            "mul ft1, ft1, fc0.z\n" +                            //     multiply by the size
            "add ft2, v0, ft1\n" +                                //     add to coordinate
            "tex ft3, ft2, fs0, <2d,clamp,linear>\n" +            //    map to outpur color
            "mov ft3.w, fc0.w\n" + 
            "mov oc, ft3\n";
    }
}