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

CRT Display Shader

Get Adobe Flash player
by devon_o 01 Nov 2014
/**
 * 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/ix4l
 */

package 
{
    
import com.adobe.utils.AGALMiniAssembler;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.LoaderInfo;
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.net.URLRequest;
import flash.system.LoaderContext;

/**
 * CRT display.
 * largely ported from http://blog.mrlxhg.com/2014/10/old-crt-display-shader-fallout-pipoy-screen/
 * @author Devon O.
 */

[SWF(width='465', height='465', backgroundColor='#000000', frameRate='60')]
public class Main extends Sprite 
{
 
    private static var VERTEX_SHADER:String =
    <![CDATA[
    
    m44 op, va0, vc0
    mov v0, va1 
    
    ]]>;
    
    
    private static var FRAGMENT_SHADER:String =
    <![CDATA[
    
    mov ft0.xy, v0.xy
    sub ft0.xy, v0.xy, fc0.zz
    
    mov ft0.z, fc0.x
    dp3 ft0.w, ft0.xyz, ft0.xyz
    mul ft0.z, ft0.w, fc4.y
    
    add ft0.w, fc0.w, ft0.z
    mul ft0.w, ft0.w, ft0.z
    mul ft0.xy, ft0.ww, ft0.xy
    add ft0.xy, ft0.xy, v0.xy

    tex ft2, ft0.xy, fs0<2d, clamp, nearest, mipnone>

    sge ft3.x, ft0.x, fc0.x
    sge ft3.y, ft0.y, fc0.x
    slt ft3.z, ft0.x, fc0.w
    slt ft3.w, ft0.y, fc0.w
    mul ft3.x, ft3.x, ft3.y
    mul ft3.x, ft3.x, ft3.z
    mul ft3.x, ft3.x, ft3.w

    max ft4.x, ft2.x, ft2.y
    max ft4.x, ft4.x, ft2.z
    min ft4.y, ft2.x, ft2.y
    min ft4.y, ft4.y, ft2.z
    div ft4.y, ft4.y, fc2.z
    add ft4.x, ft4.x, ft4.y
    mov ft4.xyzw, ft4.xxxx
    mul ft4.xyzw, ft4.xyzw, ft3.xxxx

    mov ft2.x, ft0.y
    mul ft2.x, ft2.x, fc1.w
    mul ft2.x, ft2.x, fc4.z
    sin ft2.x, ft2.x
    mul ft2.x, ft2.x, fc0.y
    sat ft2.x, ft2.x
    mul ft2.x, ft2.x, fc0.y
    mul ft2.x, ft2.x, fc4.w
    add ft2.x, ft2.x, fc0.w

    mov ft2.y, fc0.w

    mov ft2.z, fc5.x
    mul ft2.z, ft2.z, fc0.z
    add ft2.z, ft2.z, ft0.y
    mul ft2.z, ft2.z, fc1.w
    mul ft2.z, ft2.z, fc3.x
    sin ft2.z, ft2.z
    mul ft2.z, ft2.z, fc2.w
    add ft2.y, ft2.y, ft2.z

    add ft2.z, ft0.y, fc5.x
    mul ft2.z, ft2.z, fc1.w
    mul ft2.z, ft2.z, fc2.z
    sin ft2.z, ft2.z
    mul ft2.z, ft2.z, fc2.w
    add ft2.y, ft2.y, ft2.z

    mul ft2.y, ft2.y, fc4.x

    mul ft0.xyz, ft4.xyz, ft3.xxx
    mul ft0.xyz, ft0.xyz, fc3.yzw
    mul ft0.xyz, ft0.xyz, ft2.xxx
    mul ft0.xyz, ft0.xyz, ft2.yyy
    mov ft0.w, fc0.w
    mov oc, ft0
    
    ]]>;
    
    private var context:Context3D;
    private var isReady:Boolean;
    private var program:Program3D;
    private var renderMatrix:Matrix3D;
    private var vertexBuffer:VertexBuffer3D;
    private var indexBuffer:IndexBuffer3D;
    private var textureData:BitmapData;
    private var texture:Texture;
    private var textureWidth:int;
    private var textureHeight:int;
    
    public function Main():void 
    {
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
    }
    
    private function init(e:Event = null):void 
    {
        removeEventListener(Event.ADDED_TO_STAGE, init);
        
        stage.scaleMode = StageScaleMode.NO_SCALE;
        stage.align = StageAlign.TOP_LEFT;
        this.isReady = false;
        this.renderMatrix = new Matrix3D();
        
        loadImage();
        startRender();
    }
    
    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/1/12/1247/124761a085cc7a1704c9fb601fe9d35e2e5a8b2e"), new LoaderContext(true));
    }
    
    private function onImageLoad(event:Event=null):void
    {
        event.currentTarget.removeEventListener(Event.COMPLETE, onImageLoad);
        var l:Loader = (event.currentTarget as LoaderInfo).loader;
        this.textureData = (l.content as Bitmap).bitmapData;    
        
        requestContext();
    }
    
    private function startRender():void
    {
        addEventListener(Event.ENTER_FRAME, onFrame);
    }
    
    private function requestContext():void
    {
        stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onStage3dContext);
        stage.stage3Ds[0].requestContext3D(Context3DRenderMode.AUTO, Context3DProfile.BASELINE);
    }
    
    private function onStage3dContext(e:Event):void
    {
        this.context = stage.stage3Ds[0].context3D;
        this.context.configureBackBuffer(stage.stageWidth, stage.stageHeight, 2, false, false);
        
        createVertexBuffer();
        createIndexBuffer();
        createTextures();
        createPrograms();
        
        this.isReady = true;
    }
    
    private function createVertexBuffer():void
    {
        var vertices:Vector.<Number> = new <Number>[
        //    x            y        u  v
            -1.0,         1.0,      0, 0, 
             1.0,         1.0,      1, 0,
            -1.0,        -1.0,      0, 1,
             1.0,        -1.0,      1, 1  ];
            
        this.vertexBuffer = this.context.createVertexBuffer(4, 4);
        this.vertexBuffer.uploadFromVector(vertices, 0, 4);
    }
    
    private function createIndexBuffer():void
    {
        this.indexBuffer = this.context.createIndexBuffer(6);
        
       // 2 triangles (0, 1, 2) & (1, 3, 2)
       //   0 - 1
       //   | / |
       //   2 - 3
        this.indexBuffer.uploadFromVector(new <uint>[0, 1, 2,   1, 3, 2], 0, 6);
    }
    
    private function createTextures():void
    {
        this.textureWidth = this.textureData.width;
        this.textureHeight = this.textureData.height;
        this.texture = this.context.createTexture(this.textureWidth, this.textureHeight, Context3DTextureFormat.BGRA, false);
        this.texture.uploadFromBitmapData(this.textureData);
        this.textureData.dispose();
    }

    private function createPrograms():void
    {
        var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
        vertexShaderAssembler.assemble(Context3DProgramType.VERTEX, VERTEX_SHADER);
        
        var fragmentShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
        fragmentShaderAssembler.assemble(Context3DProgramType.FRAGMENT, FRAGMENT_SHADER);
        
        this.program = this.context.createProgram();
        this.program.upload(vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);
    }
    

    private var fc0:Vector.<Number> = new <Number>[0.0, .25, .50, 1.0];
    private var fc1:Vector.<Number> = new <Number>[Math.sqrt(.50), 2.5, 1.55, Math.PI];
    private var fc2:Vector.<Number> = new <Number>[2.2, 1.4, 2.0, .2];
    private var fc3:Vector.<Number> = new <Number>[3.5, 1, 1, 1];
    private var fc4:Vector.<Number> = new <Number>[1, 1, 1, 1];
    private var fc5:Vector.<Number> = new <Number>[1, 1, 1, 1];
    private var time:Number = 0.0;
    private function onFrame(e:Event):void
    {
        if (!this.isReady)
            return;
            
        this.context.clear(0, 0, 0, 1);
        
        this.renderMatrix.identity();
        this.renderMatrix.appendScale(this.textureWidth / stage.stageWidth, this.textureHeight / stage.stageHeight, 1.0);
        this.context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, this.renderMatrix, true);
        
        this.context.setVertexBufferAt(0, this.vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);
        this.context.setVertexBufferAt(1, this.vertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2);
        
        // screen tint
        fc3[1] = 0.7;       // red
        fc3[2] = 1.0;       // green
        fc3[3] = 0.7;       // blue
        
        fc4[0] = 1.1;       // screen intensity/brightness
        fc4[1] = 0.75;      // bulging distortion (0 = none)
        fc4[2] = 256;       // scanline frequency
        fc4[3] = 4.0;       // scanline intensity
        
        this.time += 10/512;
        fc5[0] = time;

        this.context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, this.fc0, 1);
        this.context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, this.fc1, 1);
        this.context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 2, this.fc2, 1);
        this.context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 3, this.fc3, 1);
        this.context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 4, this.fc4, 1);
        this.context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 5, this.fc5, 1);
        
        this.context.setTextureAt(0, this.texture);
        
        this.context.setProgram(this.program);
        
        this.context.drawTriangles(this.indexBuffer);
        
        this.context.present();
    }
    
}
    
}