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

ff: Dispersion

alpha blending:add
optimized a little.
Get Adobe Flash player
by imo_ 03 Mar 2015
/**
 * Copyright imo_ ( http://wonderfl.net/user/imo_ )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/mqh2
 */

// forked from phi16's Dispersion
// forked from phi16's ff: ff: Reflection
// forked from imo_'s ff: Reflection
// forked from phi16's Reflection
package {
    import flash.display.BlendMode;
    import flash.display.Sprite;
    import flash.events.Event;
    public class Fresnel extends Sprite {
        public var bg:Sprite=new Sprite();
        public var div:uint = 8; // must be grater than 1
        public var sprs:Vector.<Sprite>=new Vector.<Sprite>(div, true);
        public var time:Number=0;
        public var IoR:Number=0;
        public var col:uint=0;
        public function Fresnel() {
            addChild(bg);
            for (var i:int = 0; i < div; i++) {
                addChild(sprs[i] = new Sprite());
                sprs[i].x = 465/2.0;
                sprs[i].y = 465/2.0;
                sprs[i].blendMode = BlendMode.ADD;
            }
            bg.graphics.beginFill(0);
            bg.graphics.drawRect(0,0,465,465);
            bg.graphics.endFill();
            bg.graphics.lineStyle(2,0xffffff);
            bg.graphics.drawCircle(465/2.0,465/2.0,100);
            addEventListener(Event.ENTER_FRAME,step);
        }
        public function step(e:Event):void{
            for (var i:int = 0; i < div; i++) {
                sprs[i].graphics.clear();
                var wl:Number=420+240*i/(div-1);
                IoR=getIoR(wl);
                col=spectreRGB(wl);
                rayTrace(sprs[i],mouseX-465/2.0,mouseY-465/2.0,0,-1,1);
            }
            time++;
        }
        public function pow2(a:Number):Number {
            return a*a;
        }
        public function rayTrace(spr:Sprite,a:Number,b:Number,c:Number,d:Number,alpha:Number):void{
            if(alpha<0.01)return;
            var lei:Number=Math.sqrt(c*c+d*d);
            c/=lei,d/=lei;
            a+=0.1*c;
            b+=0.1*d;
            spr.graphics.lineStyle(4,col,alpha);
            spr.graphics.moveTo(a,b);
            var f:Boolean=false;
            var D:Number,t:Number,p:Number,q:Number,le:Number,nx:Number,ny:Number,dp:Number,rx:Number,ry:Number,k:Number,sn:Number,fth:Number;
            D=-a*a*d*d+2*a*b*c*d-b*b*c*c+10000;
            if(a*a+b*b<10000){
                if(D>0){
                    t=Math.sqrt(D)-a*c-b*d;
                    if(t>0){
                        p=a+c*t,q=b+d*t;
                        spr.graphics.lineTo(p,q);
                        le=Math.sqrt(p*p+q*q);
                        nx=-p/le,ny=-q/le;
                        dp=c*nx+d*ny;
                        rx=c-2*dp*nx,ry=d-2*dp*ny;                        
                        sn=Math.abs(c*ny-d*nx);                       
                        fth=1/(IoR*IoR)-sn*sn;
                        if(fth<0)fth=1;
                        else fth=pow2((-dp-(fth=Math.sqrt(fth)))/(-dp+fth))+pow2((IoR*IoR*fth+dp)/(IoR*IoR*fth-dp));
                        if(fth<0)fth=0;
                        if(fth>0.9)fth=0.9;
                        
                        rayTrace(spr,p,q,rx,ry,alpha*fth);
                        k=1.0-IoR*IoR*(1.0-dp*dp);
                        if(k>0){  
                            rx=IoR*c-(IoR*dp+Math.sqrt(k))*nx;    
                            ry=IoR*d-(IoR*dp+Math.sqrt(k))*ny;
                            rayTrace(spr,p,q,rx,ry,alpha*(1-fth));
                        }
                        f=true;
                    }
                }
            }else{
                if(D>0){
                    t=-Math.sqrt(D)-a*c-b*d;
                    if(t>0){
                        p=a+c*t,q=b+d*t;
                        spr.graphics.lineTo(p,q);
                        le=Math.sqrt(p*p+q*q);
                        nx=p/le,ny=q/le;
                        dp=c*nx+d*ny;
                        rx=c-2*dp*nx,ry=d-2*dp*ny;
                        sn=Math.abs(c*ny-d*nx);    
                                            
                        fth=IoR*IoR-sn*sn;
                        if(fth<0)fth=1;
                        else fth=pow2((-dp-(fth=Math.sqrt(fth)))/(-dp+fth))+pow2((1/(IoR*IoR)*fth+dp)/(1/(IoR*IoR)*fth-dp));
                        if(fth<0)fth=0;
                        if(fth>0.9)fth=0.9;
                                          
                        rayTrace(spr,p,q,rx,ry,alpha*fth);
                        k=1.0-1/(IoR*IoR)*(1.0-dp*dp);
                        if(k>0){
                            rx=1/IoR*c-(1/IoR*dp+Math.sqrt(k))*nx;
                            ry=1/IoR*d-(1/IoR*dp+Math.sqrt(k))*ny;
                            rayTrace(spr,p,q,rx,ry,alpha*(1-fth));
                        }
                        f=true;
                    }
                }
                if(!f){
                    spr.graphics.lineTo(a+c*1000,b+d*1000);
                }
            }
        }
    }
}

function getIoR(x:Number):Number{ //Glass, BK7(SHOTT)
    var data:Array=[1.73759695,0.013188707,0.313747346,0.0623068142,1.89878101,155.23629];
    x/=1000;
    x*=x;
    var s:Number=0;
    for(var i:int=0;i<3;i++){
        s+=data[2*i]*x/(x-data[2*i+1]);
    }
    return Math.sqrt(s+1);
}

function spectreRGB(x:Number):int{
    if(x<370)return 0;
    else if(x>780)return 0;
    var data:Array=[
      [4.010353218,-80.63249483,631.7030634,-2340.443417,3649.476495,0,-4177.888781],
      [0.277385381,-11.15063994,185.6265588,-1637.093036,8062.307429,-21008.39274,22614.05094],
      [-0.105722006,2.746241678,-27.82592878,133.2858701,-268.2029047,0,505.990267],
      [-8.591709666,229.2801983,-2539.539977,14942.14013,-49253.65203,86238.82071,-62662.66903],
      [-2.50432e-05,0.000231452,0,0,0,0,-1.042682898],
      [0,0,0,0,0,0,0]];
    var ri:uint=x<470?0:x<550?5:1;
    var gi:uint=x<460?5:x<610?2:5;
    var bi:uint=x<520?3:x<760?5:4;
    x/=100;
    var r:Number=0,g:Number=0,b:Number=0;
    for(var i:int=0;i<7;i++){
        r=r*x+data[ri][i];
        g=g*x+data[gi][i];
        b=b*x+data[bi][i];
    }
    var rs:int=Math.max(0,Math.min(1,r))*255;
    var gs:int=Math.max(0,Math.min(1,g))*255;
    var bs:int=Math.max(0,Math.min(1,b))*255;
    return (rs<<16)+(gs<<8)+bs;
}