Stage3D RayLights
/**
* Copyright bongiovi015 ( http://wonderfl.net/user/bongiovi015 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/1XYp
*/
package {
import com.bit101.components.HSlider;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display3D.Context3D;
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 net.hires.debug.Stats;
[SWF(width=465, height=465, frameRate=60, backgroundColor=0x000000)]
public class Test04_Rays extends Sprite {
//--------------------------------------
// CLASS CONSTANTS
//--------------------------------------
private var _player:VideoPlayer;
public var W : int = 465;
public var H : int = 465;
private var context:Context3D;
private var _bmpd:BitmapData;
private var _slider:HSlider;
private var vbuffer:VertexBuffer3D;
private var ibuffer:IndexBuffer3D;
private var imageSize:Number;
private var _pass:PassRays;
private var _texture:Texture;
public function Test04_Rays() {
_player = new VideoPlayer(512, 512);
_player.setVideoURL("http://www.bongiovi.tw/experiments/particleVideo/SigurRos.flv");
_player.play();
_player.setVolume(0);
stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, _onContext);
stage.stage3Ds[0].requestContext3D();
addChild(new Stats).y = 365;
}
private function _onContext(e:Event) : void {
context = stage.stage3Ds[0].context3D;
context.configureBackBuffer(W, H, 1, false);
_bmpd = new BitmapData(512, 512);
_player.play();
_initShader();
_initBuffer();
_slider = new HSlider(this, 5, 5);
_slider.value = 25;
addEventListener(Event.ENTER_FRAME, _loop);
}
private function _loop(e:Event) : void {
_bmpd.draw(_player);
_texture = createTexture(context, _bmpd);
context.setTextureAt(0, _texture);
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([1- stage.mouseX/stage.stageWidth, 1-stage.mouseY/stage.stageHeight, 0, 0]));
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, Vector.<Number>([_slider.value/100 + .05, 1, Math.PI, .5]));
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 2, Vector.<Number>([3, 0, 0, 0]));
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 4, Vector.<Number>([1, 0, Math.PI, 2 * Math.PI]));
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 5, Vector.<Number>([1e-10, Math.PI / 2, 0, 0,]));
_pass.render(ibuffer);
context.present();
}
private function _initShader() : void {
_pass = new PassRays(context, true, false);
_pass.assemble();
}
private function _initBuffer() : void {
vbuffer = context.createVertexBuffer(4, 5);
ibuffer = context.createIndexBuffer(6);
imageSize = 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);
ibuffer.uploadFromVector(Vector.<uint>([0, 1, 2, 0, 2, 3]), 0, 6);
context.setVertexBufferAt(0, vbuffer, 0, "float3");
context.setVertexBufferAt(1, vbuffer, 3, "float2");
}
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 flash.display.Sprite;
import flash.events.AsyncErrorEvent;
import flash.events.ErrorEvent;
import flash.events.NetStatusEvent;
import flash.events.SecurityErrorEvent;
import flash.media.SoundTransform;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
class VideoPlayer extends Sprite {
private var _nc:NetConnection;
private var _ns:NetStream;
private var _video:Video;
private var _url:String;
public function VideoPlayer(width:int, height:int) {
_nc = new NetConnection();
_nc.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
_nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
_nc.connect(null);
_ns = new NetStream(_nc);
_ns.client = this;
_ns.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
_ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onError);
_ns.checkPolicyFile = true;
_video = new Video(width, height);
_video.smoothing = true;
_video.attachNetStream(_ns);
addChild(_video);
}
public function setVideoURL(videoURL:String):void {
_url = videoURL;
stop();
}
public function play():void {
if (!_url) {
stop();
trace("No URL set. Please use the 'setVideoURL' method.");
} else {
_ns.play(_url);
}
}
public function stop():void {
_ns.close();
_video.clear();
}
public function setVolume(volume:Number):void {
var st:SoundTransform = _ns.soundTransform;
st.volume = volume;
_ns.soundTransform = st;
}
private function onError(e:ErrorEvent) : void { trace(e.text); }
private function onStatus(e:NetStatusEvent) : void { trace(e.info.code); }
public function onMetaData(o:Object):void { }
public function onXMPData(info:Object):void { }
}
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 {
//--------------------------------------
// CLASS CONSTANTS
//--------------------------------------
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() : void {
var vertexShader:ByteArray = agal.assemble(Context3DProgramType.VERTEX, _shaderVertex);
var fragmentShader:ByteArray = agal.assemble(Context3DProgramType.FRAGMENT, _shaderFragment);
_program = _context.createProgram();
_program.upload(vertexShader, fragmentShader);
}
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 PassRays extends Pass {
//--------------------------------------
// CLASS CONSTANTS
//--------------------------------------
public function PassRays(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 : center : [.5, .5, 0, 0]
// fc1 : range : [0.15, 1, PI/2, .5];
// fc2 : constants : [3, 0, 0, 0];
_shaderFragment = "" +
"mov ft0, v0\n" + // pos = outcoord();
"sub ft1, ft0, fc0\n" + // newPos = pos - center;
"add ft1.x, ft1.x, fc5.x \n"+ // fudge to prevent div zero
"div ft2.x, ft1.y, ft1.x \n"+ // ft1.x = ydiff / xdiff
"neg ft2.y, ft2.x \n"+ // ft1.y = -ydiff / xdiff
"mul ft3.y, fc5.y, ft2.x \n"+ // ft3.x = atan(ft1.x)
"add ft3.z, fc4.x, ft2.x \n"+ // atan(x) = Pi / 2 * x / (1 + x)
"div ft4.x, ft3.y, ft3.z \n"+
"mul ft3.y, fc5.7, ft2.y \n"+ // ft3.y = atan(ft1.y)
"add ft3.z, fc4.x, ft2.y \n"+ // atan(x) = Pi / 2 * x / (1 + x)
"div ft4.y, ft3.y, ft3.z \n"+
"slt ft3.x, ft1.x, fc4.y \n"+ // x < 0 ft3.x
"slt ft3.y, ft1.y, fc4.y \n"+ // y < 0 ft3.y
"sub ft3.z, fc4.x, ft3.x \n"+ // x >= 0 ft3.z
"sub ft3.w, fc4.x, ft3.y \n"+ // y >= 0 ft3.w
"mul ft2.x, ft3.z, ft3.w \n"+ // x > 0 && y > 0 ft2.x
"mul ft2.y, ft3.x, ft3.w \n"+ // x < 0 && y > 0 ft2.y
"mul ft2.z, ft3.x, ft3.y \n"+ // x < 0 && y < 0 ft2.z
"mul ft2.w, ft3.z, ft3.y \n"+ // x > 0 && y < 0 ft2.w
"sub ft3.x, ft4.x, fc4.z \n"+ // a - Pi ft3.x
"neg ft3.y, ft4.y \n"+ // -a ft3.y
"mov ft3.z, ft4.x \n"+ // a ft3.z
"sub ft3.w, fc4.z, ft4.y \n"+ // Pi - a ft3.w
"mul ft3, ft3, ft2 \n"+ // multiply grid of possibilities
"add ft3.xy, ft3.xz, ft3.yw \n"+ // add possibilities
"add ft3.x, ft3.x, ft3.y \n"+
"mul ft4, ft1, ft1\n" + // r = length(newPos);
"add ft4.x, ft4.x, ft4.y\n" +
"add ft4.x, ft4.x, ft4.z\n" +
"sqt ft4.x, ft4.x\n" +
"div ft5.x, ft3.x, fc1.x\n" + // thetaCenter = floor(theta/range)
"frc ft5.y, ft5.x\n" +
"sub ft5.x, ft5.x, ft5.y\n" +
"mul ft5.x, ft5.x, fc1.x\n" + // * range
"mov ft5.z, fc1.x\n" +
"mul ft5.y, ft5.z, fc1.w\n" + // + range *.5
"add ft5.x, ft5.x, ft5.y\n" +
"cos ft6.x, ft5.x\n" + // pos0.x = cos(thetaCenter)*r + center.x;
"mul ft6.x, ft6.x, ft4.x\n" +
"add ft6.x, ft6.x, fc0.x\n" +
"sin ft6.y, ft5.x\n" + // pos0.y = sin(thetaCenter)*r + center.y
"mul ft6.y, ft6.y, ft4.x\n" +
"add ft6.y, ft6.y, fc0.y\n" +
"mov ft6.zw, fc1.yy\n" +
"tex ft7, ft6, fs0, <2d,clamp,linear>\n" +
"sub ft0.x, ft3.x, ft5.x\n" + // abs(theta - thetaCenter) ;
"abs ft0.x, ft0.x\n" +
"mov ft0.y, fc1.x\n" + // range * .5 * bright
"mul ft0.y, ft0.y, fc1.w\n" +
"mul ft1, ft7, ft7\n" +
"add ft1.x, ft1.x, ft1.y\n" +
"add ft1.x, ft1.x, ft1.z\n" +
"div ft1.x, ft1.x, fc2.x\n" +
"mul ft0.y, ft0.y, ft1.x\n" +
"slt ft0.z, ft0.x, ft0.y\n" +
"mul ft7.a, ft7.a, ft0.z\n" +
"mov oc, ft7\n";
}
}