ff: Dispersion
alpha blending:add
optimized a little.
/**
* 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;
}