fire effect for stage3d
/**
* Copyright flashisobar ( http://wonderfl.net/user/flashisobar )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/9yxv
*/
package
{
import com.adobe.utils.AGALMiniAssembler;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.GradientType;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.display3D.Context3D;
import flash.display3D.Context3DBlendFactor;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DTextureFormat;
import flash.display3D.Context3DTriangleFace;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.display3D.textures.Texture;
import flash.display3D.textures.TextureBase;
import flash.display3D.VertexBuffer3D;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.utils.ByteArray;
import net.hires.debug.Stats;
/**
* fire effect for stage3d
* @author flashisobar
*/
[SWF(width = "465", height = "465", frameRate = "60")]
public class Main extends Sprite
{
private static const FRAME_CREATE_PARTICLE_NUM:int = 3;
private var vertexParticle:VertexBuffer3D;
private var indexParticle:IndexBuffer3D;
private var textureParticle:Texture;
private var vertexShader:ByteArray;
private var fragmentShader:ByteArray;
private var transformConstants:Vector.<Number>;
private var colorConstants:Vector.<Number>;
private var matrix3d:Matrix3D;
private var isStart:Boolean = true;
private var particles:Vector.<Particle> = new Vector.<Particle>();
private var _context3D:Context3D;
private var _program:Program3D;
///private var sc:BitmapData = new BitmapData(465, 465, false);
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);
Wonderfl.disable_capture();
//Wonderfl.capture_delay(5);
///addChild(new Bitmap(sc));
//Security.loadPolicyFile('http://assets.wonderfl.net/crossdomain.xml');
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
prepareStage3D();
}
private function prepareStage3D():void
{
stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, handleContextCreate);
stage.stage3Ds[0].requestContext3D();
}
/*
* configureBackBuffer: enableDepthAndStencil default is true
* enableErrorChecking: slow rendering - only turn on when developing/testing
*/
private function handleContextCreate(e:Event):void
{
_context3D = stage.stage3Ds[0].context3D;
if (!_context3D) {
return;
}
_context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 2, false);
_context3D.setCulling(Context3DTriangleFace.BACK);
_context3D.enableErrorChecking = true;
_program = _context3D.createProgram();
main();
start();
}
private function main():void
{
this.addChild(new Stats);
// set vertex/index data
var vertices:Vector.<Number>=Vector.<Number>([
-0.5, 0.5, 0, 0,
0.5, 0.5, 0, 1,
0.5, -0.5, 1, 1,
-0.5, -0.5, 0, 1
]);
vertexParticle = setVertexData(vertices, 4);
indexParticle = setIndexData(Vector.<uint>([0, 1, 2, 2, 3, 0]));
// set texture
var sp:Sprite = new Sprite();
var m:Matrix = new Matrix();
m.createGradientBox(64, 64, 0, -32, -32);
sp.graphics.beginGradientFill(GradientType.RADIAL, [0xFF8888, 0xFF8888], [0.5, 0], [0, 255], m);
//sp.graphics.beginFill(0xFF8888, 1);
sp.graphics.drawCircle(0, 0, 64);
sp.graphics.endFill();
var bmpd:BitmapData = new BitmapData(64, 64, true, 0);
bmpd.draw(sp, new Matrix(1, 0, 0, 1, 32, 32));
textureParticle = setTextureData(bmpd);
// set register
setVertexBuffer(0, vertexParticle, 0, Context3DVertexBufferFormat.FLOAT_2); // register0: va0
setVertexBuffer(1, vertexParticle, 2, Context3DVertexBufferFormat.FLOAT_2); // register1: va1
setTexture(0, textureParticle); // fragment sampler0: fs0
// set constants for setProgramConstantsFromMatrix
transformConstants = new <Number>[0, 0, 0, 1];
colorConstants = new <Number>[1, 1, 1, 1];
// AGAL code
// Register components can be accessed both through the coordinate accessors (xyzw), and through the color accessors (rgba).
var assembler:AGALMiniAssembler = new AGALMiniAssembler();
var code:String = '';
code += "mov vt0, va0\n"; // pos: vt0 = va0;
code += "mul vt0.xy, vt0, vc4.ww\n"; // size: vt0.xy = vt0 * vc4.ww
code += "add vt0.xy, vt0, vc4.xy\n"; // move: vt0.xy = vt0 + vc4.xy
code += "m44 op, vt0, vc0\n"; // m44: vt0 * vc0
code += "mov v0, va1"; // uv: v0 = va1;
vertexShader = assembler.assemble(Context3DProgramType.VERTEX, code);
code = "tex ft0, v0, fs0<2d,linear, nomip, repeat>\n"; // 參照 v0 從材質 fs0 取樣放入 ft0
code += "mul oc, ft0, fc0"; // add color: ft0 * fc0
fragmentShader = assembler.assemble(Context3DProgramType.FRAGMENT, code);
// set shader
setShaders(vertexShader, fragmentShader);
// set projection view or scale
matrix3d = new Matrix3D();
matrix3d.appendScale(1 / (500 / 4), 1 / (500 / 4), 1);
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix3d, true); // vc0
/*
* set depthAndStencil = false
* if enable BlendFactors(Additive)
* see: http://goo.gl/yFmmk
* https://github.com/PrimaryFeather/Starling-Framework/issues/150
* http://forum.starling-framework.org/topic/flashdevelop-starling-air-32-stage3d-android-love
* http://forum.starling-framework.org/topic/enabling-depth-buffer
*/
context3D.setBlendFactors(Context3DBlendFactor.ONE, Context3DBlendFactor.ONE);
// set click
//stage.addEventListener(MouseEvent.CLICK, createParticles);
}
private function createParticles(e:MouseEvent = null):void
{
isStart = true;
for (var i:int = 0; i < FRAME_CREATE_PARTICLE_NUM; i++) {
particles.push(new Particle());
}
}
private function draw():void
{
if (!isStart)
return;
createParticles();
var p:Particle;
var len:int = particles.length;
var i:int = len;
while (i--)
{
p = particles[i];
p.x += Math.random() * 2 - 1; // -1~1
p.y += 1.5;
p.size -= Math.random() * 1.2;
if (p.size <= 0)
{
particles.splice(i, 1);
}
}
len = particles.length;
for (i = 0; i < len; i++)
{
p = particles[i];
transformConstants[0] = p.x;
transformConstants[1] = p.y;
transformConstants[3] = p.size;
colorConstants[0] = p.r;
colorConstants[1] = p.g;
colorConstants[2] = p.b;
context3D.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 4, transformConstants);// vc4
context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, colorConstants); // fc0
context3D.drawTriangles(indexParticle);
}
}
protected function render(e:Event = null):void
{
clear();
draw();
///_context3D.drawToBitmapData(sc);
present();
}
protected function clear(__red:Number=0, __green:Number=0, __blue:Number=0, __alpha:Number=1):void {
_context3D.clear(__red, __green, __blue, __alpha);
}
protected function present():void
{
_context3D.present();
}
public function pause():void
{
removeEventListener(Event.ENTER_FRAME, render);
}
public function start():void
{
addEventListener(Event.ENTER_FRAME, render);
}
public function setVertexData(__vertexData:Vector.<Number>, __data32Per:int):VertexBuffer3D
{
var numVertices:int = __vertexData.length/__data32Per;
// create buffer
var vertexBuffer3D:VertexBuffer3D = _context3D.createVertexBuffer(numVertices, __data32Per);
vertexBuffer3D.uploadFromVector(__vertexData, 0, numVertices);
return vertexBuffer3D;
}
/*
* 建立索引"緩衝區"/定義索引資料/上傳索引資料
*/
public function setIndexData(__indexData:Vector.<uint>):IndexBuffer3D
{
// create buffer
var indexBuffer:IndexBuffer3D = _context3D.createIndexBuffer(__indexData.length);
indexBuffer.uploadFromVector(__indexData, 0, __indexData.length);
return indexBuffer;
}
/*
* 建立貼圖材質
*/
public function setTextureData(__bmd:BitmapData):Texture
{
var texture:Texture = _context3D.createTexture(__bmd.width, __bmd.height, Context3DTextureFormat.BGRA, false);
texture.uploadFromBitmapData(__bmd);
return texture;
}
/*
* 設定暫存器
*/
public function setVertexBuffer(__index:int, __buffer:VertexBuffer3D, __bufferOffset:int=0, __format:String="float4"):void
{
_context3D.setVertexBufferAt(__index, __buffer, __bufferOffset, __format);
}
/*
* 設定貼圖材質取樣暫存器
*/
public function setTexture(__sampler:int, __texture:TextureBase):void
{
_context3D.setTextureAt(__sampler, __texture);
}
/*
* 設定頂點及片段著色器
*/
public function setShaders(__vertexProgram:ByteArray, __fragmentProgram:ByteArray):void
{
_program.upload(__vertexProgram, __fragmentProgram);
_context3D.setProgram(_program);
}
public function get context3D():Context3D
{
return _context3D;
}
public function set context3D(value:Context3D):void
{
_context3D = value;
}
}
}
class Particle
{
public var x:Number;
public var y:Number;
public var size:Number;
public var r:Number;
public var g:Number;
public var b:Number;
public function Particle()
{
//this.x = Math.sin(getTimer()/1000)*10;
this.x = 0;
this.y = -50;
size = 50 * Math.random() + 20;
r = Math.random();
g = Math.random() * 0.5;
b = Math.random() * 0.5;
}
}