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

Crosshatch Shader on Webcam Vid

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

package  {
    
    import com.adobe.utils.AGALMiniAssembler;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DProfile;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DRenderMode;
    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.media.Camera;
    import flash.media.Video;
    import flash.text.AntiAliasType;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
    import flash.utils.ByteArray;
    
    /**
     * Crosshatch shader applied to webcam video
     */
    
    [SWF(width='465', height='465', backgroundColor='#FFFFFF', frameRate='60')]
    public class Cam extends Sprite {
        
        private static const FRAGMENT_SHADER:String =
        <![CDATA[
        tex ft0, v0.xy, fs0<2d, clamp, linear, mipnone>
        
        dp3 ft0.x, ft0.xyz, ft0.xyz
        sqt ft0.x, ft0.x
        
        add ft1.x, v0.x, v0.y
        div ft4.z, ft1.x, fc1.x
        frc ft4.w, ft4.z
        sub ft4.w, ft4.z, ft4.w
        mul ft4.z, fc1.x, ft4.w
        sub ft1.x, ft1.x, ft4.z
        
        sub ft1.y, v0.x, v0.y
        div ft4.z, ft1.y, fc1.x
        frc ft4.w, ft4.z
        sub ft4.w, ft4.z, ft4.w
        mul ft4.z, fc1.x, ft4.w
        sub ft1.y, ft1.y, ft4.z

        add ft1.z, v0.x, v0.y
        sub ft1.z, ft1.z, fc1.y
        div ft4.z, ft1.z, fc1.x
        frc ft4.w, ft4.z
        sub ft4.w, ft4.z, ft4.w
        mul ft4.z, fc1.x, ft4.w
        sub ft1.z, ft1.z, ft4.z
        
        sub ft1.w, v0.x, v0.y
        sub ft1.w, ft1.w, fc1.y
        div ft4.z, ft1.w, fc1.x
        frc ft4.w, ft4.z
        sub ft4.w, ft4.z, ft4.w
        mul ft4.z, fc1.x, ft4.w
        sub ft1.w, ft1.w, ft4.z
        
        mov ft2, fc2
        
        slt ft4.x, ft0.x, fc0.x
        seq ft4.y, ft1.x, fc1.z
        mul ft4.z, ft4.x, ft4.y
        sub ft2.xyz, ft2.xyz, ft4.zzz
        
        slt ft4.x, ft0.x, fc0.y
        seq ft4.y, ft1.y, fc1.z
        mul ft4.z, ft4.x, ft4.y
        sub ft2.xyz, ft2.xyz, ft4.zzz
        
        slt ft4.x, ft0.x, fc0.z
        seq ft4.y, ft1.z, fc1.z
        mul ft4.z, ft4.x, ft4.y
        sub ft2.xyz, ft2.xyz, ft4.zzz
        
        slt ft4.x, ft0.x, fc0.w
        seq ft4.y, ft1.w, fc1.z
        mul ft4.z, ft4.x, ft4.y
        sub ft2.xyz, ft2.xyz, ft4.zzz
        
        mov ft2.w, ft0.w
        mov oc, ft2
    ]]>
        
        private static const VERT_SHADER:String =
        <![CDATA[
        m44 op, va0, vc0
        mov v0, va1
        ]]>
        
        private var mVideoData:BitmapData;
        private var mVBuffer:VertexBuffer3D;
        private var mIBuffer:IndexBuffer3D;
        private var mProgram:Program3D;
        private var mNumVerts:int;
        private var mContext:Context3D;
        
        private var mTexture:Texture;
        
        private var mAppWidth:int;
        private var mAppHeight:int;
        
        private var mWebCam:Camera;
        private var mVideo:Video;
        private var mVidSize:int = 256;
        
        public function Cam() 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(event:Event = null):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            initStage();
        }
        
        private function initStage():void
        {
            mAppWidth = stage.stageWidth;
            mAppHeight = stage.stageHeight;
            
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            
            stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext);
            stage.stage3Ds[0].requestContext3D(Context3DRenderMode.AUTO, Context3DProfile.BASELINE);
            
            stage.addEventListener(Event.RESIZE, onStageResize);
        }
        
        private function onStageResize(event:Event):void
        {
            if (!mContext) return;
                
            mAppWidth = stage.stageWidth;
            mAppHeight = stage.stageHeight;
            mContext.configureBackBuffer(mAppWidth, mAppHeight, 4, true);
        }
        
        protected function onContext(event:Event):void{
            stage.stage3Ds[0].removeEventListener(Event.CONTEXT3D_CREATE, onContext);
            
            mContext = stage.stage3Ds[0].context3D;
            mContext.configureBackBuffer(mAppWidth, mAppHeight, 4, true);
            
            initApp();
        }
        
        private function initApp():void {
            if (!initCam())
            {
                exit();
                return;
            }
            
            initBuffers();
            initTexture();
            initShader();
            
            start();
        }
        
        
        private function exit():void
        {
            var tf:TextField = new TextField();
            tf.selectable = false;
            tf.mouseEnabled = false;
            tf.mouseWheelEnabled = false;
            tf.autoSize = TextFieldAutoSize.LEFT;
            tf.defaultTextFormat = new TextFormat("_sans", 12, 0xFFFFFF);
            tf.antiAliasType = AntiAliasType.ADVANCED;
            tf.text = "No Web Cam detected.";
            tf.x = (mAppWidth - tf.width) >> 1;
            tf.y = (mAppHeight - tf.height) >> 1;
            addChild(tf);
        }
        
        private function initCam():Boolean
        {
            var camIndex:int = 0;
            for ( var i:int = 0 ; i < Camera.names.length ; i++ ) {
                if ( Camera.names[ i ] == "USB Video Class Video" ) {
                    camIndex = i;
                    break;
                }
            }
            mWebCam = Camera.getCamera(String(camIndex));
            
            if (!mWebCam) return false;
            
            mWebCam.setMode(mVidSize, mVidSize, 24);
            
            mVideo = new Video(mVidSize, mVidSize);
            mVideo.attachCamera(mWebCam);

            mVideoData = new BitmapData(mVideo.width, mVideo.height, false, 0x000000);
            return true;
        }
        
        public function start():void
        {
            mWebCam.addEventListener(Event.VIDEO_FRAME, onFrame);
        }
        
        private function initBuffers():void 
        {
            var vertices:Vector.<Number> = Vector.<Number>([
                -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  ]);
            
            mVBuffer = mContext.createVertexBuffer(4, 5);
            mVBuffer.uploadFromVector(vertices, 0, 4);
            
            mIBuffer = mContext.createIndexBuffer(6);            
            mIBuffer.uploadFromVector (Vector.<uint>([0, 1, 2, 2, 3, 0]), 0, 6);
        }
        
        private function initTexture():void
        {
            mTexture = mContext.createTexture(mVidSize, mVidSize, Context3DTextureFormat.BGRA, true);
        }
        
        private function initShader():void
        {
            var assembler:AGALMiniAssembler = new AGALMiniAssembler();
            
            var vs:ByteArray = assembler.assemble(Context3DProgramType.VERTEX, VERT_SHADER);
            var fs:ByteArray = assembler.assemble(Context3DProgramType.FRAGMENT, FRAGMENT_SHADER);
            
            mProgram = mContext.createProgram();
            mProgram.upload(vs, fs);
        }
        
        private var mVideoMat:Matrix3D = new Matrix3D();
        public function onFrame(event:Event = null):void
        { 
            if ( !mContext ) 
                return;
                
            mContext.clear(1.0, 1.0, 1.0, 1.0);
            
            mVideoMat.identity();
            mVideoMat.prependScale(1, -1, 1);
            mVideoMat.appendScale(mVidSize / mAppWidth, mVidSize / mAppHeight, 1);
            
            mVideoData.draw(mVideo);
            mTexture.uploadFromBitmapData(mVideoData);
            
            mContext.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mVideoMat, true);
            mContext.setVertexBufferAt(0, mVBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
            mContext.setVertexBufferAt(1, mVBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
            
            mContext.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, new <Number>[1, .75, .50, .3465], 1);
            mContext.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, new <Number>[10/mVidSize, 5/mVidSize, 0, 1], 1);
            mContext.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 2, new <Number>[1, 1, 1, 1], 1);
            
            mContext.setTextureAt(0, mTexture);
            
            mContext.setProgram(mProgram);

            mContext.drawTriangles(mIBuffer);
            mContext.present();
        }

    }
}