2D Particle Random Motion for Stage3D
5000 particle random motion.
/**
* Copyright flashisobar ( http://wonderfl.net/user/flashisobar )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/ea5D
*/
package
{
import flash.display.Sprite;
[SWF(width = "465", height = "465", frameRate = "60")]
public class Main extends Sprite
{
private var particle2D:Particle2D;
public function Main():void
{
particle2D = new Particle2D();
addChild(particle2D);
}
}
}
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.display3D.Context3D;
import flash.display3D.Context3DTextureFormat;
import flash.display3D.Context3DTriangleFace;
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.utils.ByteArray;
///import flash.display.Bitmap;
///import flash.display.BitmapData;
/**
* base 3D
*
* @author flashisobar
*/
class Base3D extends Sprite
{
private var _context3D:Context3D;
private var _program:Program3D;
///private var sc:BitmapData = new BitmapData(465, 465, false);
public function Base3D()
{
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();
//addChild(new Bitmap(sc));
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, true);
_context3D.setCulling(Context3DTriangleFace.BACK);
_context3D.enableErrorChecking = true;
_program = _context3D.createProgram();
main();
start();
}
protected function main():void
{
}
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 draw():void
{
}
protected function present():void
{
_context3D.present();
}
public function pause():void
{
removeEventListener(Event.ENTER_FRAME, render);
}
public function start():void
{
addEventListener(Event.ENTER_FRAME, render);
}
/*
* 建立頂點"緩衝區"/定義頂點資料/上傳頂點資料
* x,y,u,v : __data32=4
* x,y,z,u,v : __data32=5
* x,y,z,r,g,b : __data32=6
*/
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;
}
}
import com.adobe.utils.AGALMiniAssembler;
import flash.display3D.Context3DBlendFactor;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.VertexBuffer3D;
import flash.events.MouseEvent;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import flash.utils.ByteArray;
import flash.utils.getTimer;
import net.hires.debug.Stats;
/**
* stage3D: 5000 particles random motion
* @author flashisobar
*/
class Particle2D extends Base3D
{
static public const NUM_PARTICLES:uint = 5000;
private var vertexParticle:VertexBuffer3D;
private var indexParticle:IndexBuffer3D;
private var isStart:Boolean = true;
private var particles:Vector.<Number> = new Vector.<Number>(NUM_PARTICLES*4);
private var vertexShader:ByteArray;
private var fragmentShader:ByteArray;
private var matrix3d:Matrix3D;
private var w:int = 400;
private var h:int = 400;
private var size:Number = 4;
private var transformConstants:Vector.<Number>;
public function Particle2D()
{
}
override protected function main():void
{
this.addChild(new Stats);
var vertices:Vector.<Number> = new Vector.<Number>();
var index:Vector.<uint> = new Vector.<uint>();
var r:Number, g:Number, b:Number, color:Number;
var s:uint;
var xPos:Number, yPos:Number;
var idx:uint = 0;
var stime:int = getTimer();
for (var i:int = 0; i < NUM_PARTICLES; i++) {
xPos = (Math.random() - 0.5) * w * 2;
yPos = (Math.random() - 0.5) * h * 2;
color = Math.random() * 0xFFFFFF;
r = (color >> 16) / 255;
g = (color >> 8 & 0xFF) / 255;
b = (color & 0xFF) / 255;
vertices.push(xPos - size, yPos + size, r, g, b);
vertices.push(xPos + size, yPos + size, r, g, b);
vertices.push(xPos + size, yPos - size, r, g, b);
vertices.push(xPos - size, yPos - size, r, g, b);
s = 4 * i;
index.push(s, s + 1, s + 2, s + 2, s + 3, s);
}
vertexParticle = setVertexData(vertices, 5);
indexParticle = setIndexData(index);
trace("Time:" + (getTimer() - stime));
// set register
setVertexBuffer(0, vertexParticle, 0, Context3DVertexBufferFormat.FLOAT_2); // register0: va0(xy)
setVertexBuffer(1, vertexParticle, 2, Context3DVertexBufferFormat.FLOAT_3); // register1: va1(color)
// set constants for setProgramConstantsFromMatrix
transformConstants = new <Number>[1, 1, 1, 1];
var len:int = NUM_PARTICLES * 4;
for (i = 0; i < len; i) {
particles[i++] = -300 + 600 * Math.random();
particles[i++] = -300 + 600 * Math.random();
particles[i++] = 1000 + 3000 * Math.random();
particles[i++] = 1;
}
// AGAL code
var assembler:AGALMiniAssembler = new AGALMiniAssembler();
var code:String = '';
code += "mov vt0, va0\n"; // get vertex position
code += "mov vt1.x vc4.z\n"; // vt1.x = getTimer()/1000;
code += "frc vt1.x vt1.x\n"; // vt1.x = get value from 0 to 1
code += "mul vt1.xy vc5.xy vt1.xx\n"; // vt1.xy = vc5.xy * vt1.xx;
code += "add vt0.xy vt0.xy vt1.xy\n"; // move: vt0.xy = vt0.xy + vt1.xy
code += "m44 op, vt0, vc0\n"; // m44: vt0 * vc0
code += "mov v0, va1\n";
vertexShader = assembler.assemble(Context3DProgramType.VERTEX, code);
code = "mov oc, v0"; // output color: v0
fragmentShader = assembler.assemble(Context3DProgramType.FRAGMENT, code);
setShaders(vertexShader, fragmentShader);
// set projection view or scale
matrix3d = new Matrix3D();
//matrix3d.appendRotation(45, Vector3D.Z_AXIS);
matrix3d.appendScale(1 / w, 1 / h, 1);
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix3d, true); // vc0,vc1,vc2,vc3
stage.addEventListener(MouseEvent.CLICK, createParticles);
}
private function createParticles(e:MouseEvent = null):void
{
isStart = !isStart;
}
private function createParticle(xPos:Number, yPos:Number, color:uint):Vector.<Number>
{
var r:Number = (color >> 16) / 255;
var g:Number = (color >> 8 & 0xFF) / 255;
var b:Number = (color & 0xFF) / 255;
return Vector.<Number>([xPos - size, yPos + size, r, g, b, xPos + size, yPos + size, r, g, b, xPos + size, yPos - size, r, g, b, xPos - size, yPos - size, r, g, b]);
}
override protected function draw():void
{
if (!isStart)
{
return;
}
context3D.clear(.4);
var g:Number = getTimer();
for (var i:int = 0; i < NUM_PARTICLES * 4; i = i + 4) {
transformConstants[2] = g / particles[i + 2]; // z
context3D.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 4, transformConstants); // vc4
context3D.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 5, new <Number>[particles[i], particles[i+1], particles[i+2], particles[i+3]]); // vc5
context3D.drawTriangles(indexParticle, 6 * i/4, 2); // 從 0 開始,畫兩個三角形
}
}
}