Stage3D Waves
/**
* Copyright bongiovi015 ( http://wonderfl.net/user/bongiovi015 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/r2R0
*/
package {
import com.adobe.utils.AGALMiniAssembler;
import com.bit101.components.PushButton;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display3D.Context3D;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.display3D.VertexBuffer3D;
import flash.events.Event;
import flash.geom.Matrix3D;
import flash.geom.Point;
import flash.geom.Vector3D;
import flash.text.TextField;
import flash.utils.ByteArray;
public class Stage3DWave extends Sprite {
public const ROW : int = 80;
public const COL : int = 40;
public const SEED : int = Math.random() * 0xFFFF;
public const SPEED : Number = .5;
public const SPACE : int = 8;
public const DEPTH : int = 200;
public var W : int;
public var H : int;
public var context : Context3D;
public var bmpd : BitmapData;
public var offset : Array = [new Point, new Point];
public var count : int = 0;
private var program:Program3D;
private var vBuffer:VertexBuffer3D;
private var iBuffer:IndexBuffer3D;
private var debug:TextField;
public function Stage3DWave() {
W = stage.stageWidth;
H = stage.stageHeight;
stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, _onContext);
stage.stage3Ds[0].requestContext3D();
}
private function _onContext(e:Event) : void {
context = stage.stage3Ds[0].context3D;
context.configureBackBuffer(W, H, 2, false);
bmpd = new BitmapData(ROW, COL, false, 0);
new PushButton(this, 10, 10, "START", startAnim);
new PushButton(this, 10, 40, "STOP", stopAnim);
_initShader();
_initBuffer();
addEventListener(Event.ENTER_FRAME, render);
}
public function startAnim(e:Event=null) : void {
stopAnim();
addEventListener(Event.ENTER_FRAME, render);
}
public function stopAnim(e:Event=null) : void {
removeEventListener(Event.ENTER_FRAME, render);
}
private function _initBuffer() : void {
vBuffer = context.createVertexBuffer(ROW*COL, 6);
var indices : Vector.<uint> = new Vector.<uint>();
var tmp0:int, tmp1:int, tmp2:int, tmp3:int, tmp4:int, tmp5:int;
var i:int, j:int;
for(j=0; j<COL-1; j++) {
for(i=0; i<ROW-1; i++) {
tmp0 = i + j * ROW;
tmp1 = tmp0 + 1;
tmp2 = i + 1 + (j + 1) * ROW;
tmp3 = tmp0;
tmp4 = tmp2;
tmp5 = tmp2-1;
indices.push(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
}
}
iBuffer = context.createIndexBuffer(indices.length);
iBuffer.uploadFromVector(indices, 0, indices.length);
}
private function _initShader() : void {
var agal : AGALMiniAssembler = new AGALMiniAssembler;
var code : String = "";
code += "mov vt1, va0\n";
code += "div vt2, va1, vc9\n";
code += "mul vt3, vt2, vt2\n";
code += "add vt3.x, vt3.x, vt3.y\n";
code += "add vt3.x, vt3.x, vt3.z\n";
code += "div vt3.x, vt3.x, vc13.y\n";
code += "mul vt3.x, vt3.x, vc13.z\n";
code += "mov vt1.y, vt3.x\n";
code += "m44 op, vt1, vc0\n";
code += "mov v0, vt2\n";
var vertexShader:ByteArray = agal.assemble(Context3DProgramType.VERTEX, code);
code = "mov oc, v0\n";
var fragmentShader:ByteArray = agal.assemble(Context3DProgramType.FRAGMENT, code);
program = context.createProgram();
program.upload(vertexShader, fragmentShader);
context.setProgram(program);
var data:Vector.<Number> = Vector.<Number>([255, 3, DEPTH, 1]);
context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 13, data, 1);
context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 9, Vector.<Number>([255, 255, 255, 1]))
}
public function render(e:Event=null):void {
if( count % 3 == 0) bmpd.perlinNoise(ROW, COL, 3, SEED, false, false, 7, true, offset);
var vBuf:Vector.<Number> = new Vector.<Number>(4*6);
var i:int, j:int, color:uint, index:int;
var oColor:Object;
for ( j=0; j<COL; j++) {
for ( i=0; i<ROW; i++) {
color = bmpd.getPixel(i, j);
oColor = getRGB(color);
vBuf[index++] = i * SPACE;
vBuf[index++] = 0;
vBuf[index++] = j / COL;
vBuf[index++] = oColor.r;
vBuf[index++] = oColor.g;
vBuf[index++] = oColor.b;
}
}
vBuffer.uploadFromVector(vBuf, 0, ROW*COL);
context.setVertexBufferAt(0, vBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
context.setVertexBufferAt(1, vBuffer, 3, Context3DVertexBufferFormat.FLOAT_3);
var model:Matrix3D = new Matrix3D;
model.appendTranslation(-ROW*SPACE*.5, -DEPTH*.2, 1);
model.appendScale(2/W, 2/H, 1);
var view:Matrix3D = new Matrix3D;
view.appendRotation(-(stage.mouseY/H)*60, Vector3D.X_AXIS, new Vector3D(0, 0, 1.5));
view.appendRotation(-(stage.mouseX/W - .5)*60, Vector3D.Y_AXIS, new Vector3D(0, 0, 1.5));
var project : Matrix3D = new Matrix3D;
var fov:Number = 45;
var aspect:Number = 4/3;
var zNear:Number = 0.1;
var zFar:Number = 3;
var yScale:Number = 1.0/Math.tan(fov/2.0);
var xScale:Number = yScale / aspect;
project.copyRawDataFrom(Vector.<Number>([ xScale, 0.0, 0.0, 0.0,
0.0, yScale, 0.0, 0.0,
0.0, 0.0, zFar/(zFar-zNear), 1.0,
0.0, 0.0, (zNear*zFar)/(zNear-zFar), 0.0 ]));
model.append(view);
model.append(project);
context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, model, true);
context.clear(0, 0, 0, 1);
context.drawTriangles(iBuffer);
context.present();
offset[0].x += SPEED;
offset[1].y += SPEED;
count ++;
}
public static function getRGB(pixelValue:uint) : Object {
var red:uint = pixelValue >> 16 & 0xFF;
var green:uint = pixelValue >> 8 & 0xFF;
var blue:uint = pixelValue & 0xFF;
return {r:red, g:green, b:blue};
}
}
}