/**
* Copyright okoi ( http://wonderfl.net/user/okoi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/h5Dq
*/
/**
* [test]stage3d, AGAL(3)
* Stage3Dテスト
* テクスチャの作成
* アルファブレンド
*/
package
{
import com.adobe.utils.AGALMiniAssembler;
import com.adobe.utils.PerspectiveMatrix3D;
import flash.display.Stage3D;
import flash.display3D.Program3D;
import flash.display3D.Context3D;
import flash.display3D.Context3DRenderMode;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DTriangleFace;
import flash.display3D.Context3DBlendFactor;
import flash.display3D.Context3DCompareMode;
import flash.display.Sprite;
import flash.events.Event;
import flash.utils.ByteArray;
import flash.geom.Vector3D;
import flash.geom.Matrix3D;
[SWF(width = "465", height = "465", frameRate="60")]
/**
* ...
* @author okoi
*/
public class Main extends Sprite
{
private static const WIDTH:int = 465;
private static const HEIGHT:int = 465;
private var _stage3D:Stage3D;
private var _context3D:Context3D;
private var _renderProgram:Program3D; // レンダリングプログラム
private var _matProjection:PerspectiveMatrix3D;
private var _camera:Camera;
private var _particleData:ParticleData;
private var _particleList:Vector.<Particle>;
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);
// entry point
_stage3D = stage.stage3Ds[0];
_stage3D.addEventListener( Event.CONTEXT3D_CREATE, Context3DCreateHandler );
_stage3D.requestContext3D( Context3DRenderMode.AUTO );
}
private function Context3DCreateHandler( e:Event ) : void
{
_context3D = _stage3D.context3D;
_context3D.enableErrorChecking = true;
_context3D.configureBackBuffer( WIDTH, HEIGHT, 0, true );
_context3D.setCulling(Context3DTriangleFace.BACK);
_context3D.setBlendFactors( Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA );
_context3D.setDepthTest(false, Context3DCompareMode.ALWAYS);
_renderProgram = _context3D.createProgram();
InitCamera();
InitProjection();
InitShader();
_particleData = new ParticleData( _context3D );
_particleList = new Vector.<Particle>();
_context3D.clear();
AddParticle();
addEventListener( Event.ENTER_FRAME, EnterFrameHandler );
}
private function InitProjection() : void {
_matProjection = new PerspectiveMatrix3D();
_matProjection.perspectiveFieldOfViewLH( 45 * Math.PI / 180, WIDTH / HEIGHT, 0.1, 3000 );
}
private function InitCamera() : void {
_camera = new Camera();
}
private function InitShader() : void {
var agalAssembler:AGALMiniAssembler = new AGALMiniAssembler();
var code:String = "";
var vShader:ByteArray;
var fShader:ByteArray;
code = "m44 op, va0, vc0\n";
code += "mov v0, va1\n";
vShader = agalAssembler.assemble( Context3DProgramType.VERTEX, code );
code = "tex ft0, v0, fs0 <2d,clamp,linear>\n";
code += "mul oc, ft0, fc0\n";
//code = "mov oc, v0\n";
fShader = agalAssembler.assemble( Context3DProgramType.FRAGMENT, code );
_renderProgram.upload( vShader, fShader );
_context3D.setProgram(_renderProgram);
}
private function EnterFrameHandler( e:Event ) : void {
var i:int;
for ( i = _particleList.length - 1; i >= 0; i-- ) {
if ( _particleList[i].life > 0 ) _particleList[i].life--;
else _particleList.splice( i, 1 );
}
_camera.InitView( new Vector3D(0, 0, -2), new Vector3D(0, 0, 0), new Vector3D(0, 1, 0) );
_context3D.clear();
for ( i = _particleList.length - 1; i >= 0; i-- ){
var mat:Matrix3D = new Matrix3D();
var particle:Particle = _particleList[i];
_context3D.setVertexBufferAt( 0, _particleData.vBuf, 0, Context3DVertexBufferFormat.FLOAT_3 ); // va0
_context3D.setVertexBufferAt( 1, _particleData.uvBuf, 0, Context3DVertexBufferFormat.FLOAT_2 ); // va1
_context3D.setTextureAt( 0, _particleData.texture );
mat.append( particle.matrix ); // ワールド座標変換
mat.append( _camera.matrix ); // ビュー変換変換
mat.append( _matProjection ); // プロジェクション座標変換
var alpha:Number = ( particle.life / particle.maxlife > 0.5 ) ? (1 - (particle.life / particle.maxlife)) * 2: (particle.life / particle.maxlife) * 2;
_context3D.setProgramConstantsFromMatrix( Context3DProgramType.VERTEX, 0, mat, true ); // vc0
_context3D.setProgramConstantsFromVector( Context3DProgramType.FRAGMENT, 0, Vector.<Number>([ particle.r, particle.g, particle.b, alpha ]) );
_context3D.drawTriangles( _particleData.iBuf );
}
_context3D.present();
if ( int(Math.random() * 10) == 0 ) {
AddParticle();
}
}
private function AddParticle() : void {
var p:Particle = new Particle();
_particleList.push( p );
}
}
}
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display3D.Context3D;
import flash.display3D.textures.Texture;
import flash.display3D.IndexBuffer3D;
import flash.display3D.VertexBuffer3D;
import flash.display3D.Context3DTextureFormat;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
class Camera {
private var _view:Matrix3D;
public function Camera() {
_view = new Matrix3D();
}
/**
* ビュー行列の設定を行う
* PerspectiveMatrix3DのlookAtLH,RHはバグがあるっぽいので自力計算
* @param from
* @param at
* @param up
*/
public function InitView( from:Vector3D, at:Vector3D, up:Vector3D ) : void {
var vz:Vector3D = at.subtract( from );
vz.normalize();
var vx:Vector3D = up.crossProduct( vz );
vx.normalize();
var vy:Vector3D = vz.crossProduct( vx );
vy.normalize();
var vtx:Number = vx.dotProduct( from ) * -1;
var vty:Number = vy.dotProduct( from ) * -1;
var vtz:Number = vz.dotProduct( from ) * -1;
_view.identity();
_view.rawData = Vector.<Number>([
vx.x, vy.x, vz.x, 0,
vx.y, vy.y, vz.y, 0,
vx.z, vy.z, vz.z, 0,
vtx, vty, vtz, 1,
]);
}
public function get matrix():Matrix3D {
return _view;
}
}
class ParticleData {
private var _vBuf:VertexBuffer3D;
private var _uvBuf:VertexBuffer3D;
private var _iBuf:IndexBuffer3D;
private var _texture:Texture = null;
public function ParticleData( context3d:Context3D ) {
_vBuf = context3d.createVertexBuffer( 4, 3 );
_vBuf.uploadFromVector(
Vector.<Number>([
-0.1, 0.1, 0,
0.1, 0.1, 0,
0.1, -0.1, 0,
-0.1, -0.1, 0,
]),
0,
4
);
_uvBuf = context3d.createVertexBuffer( 4, 2 );
_uvBuf.uploadFromVector(
Vector.<Number>([
0, 0,
1, 0,
1, 1,
0, 1,
]),
0,
4
);
_iBuf = context3d.createIndexBuffer( 3 * 2 );
_iBuf.uploadFromVector(
Vector.<uint>([
0, 1, 2,
2, 3, 0,
]),
0,
3 * 2
);
InitTexture( context3d );
}
private function InitTexture( context3d:Context3D ) : void {
var w:int = 16;
var h:int = 16;
var shape:Shape = new Shape();
shape.graphics.beginFill( 0xFFFFFF );
shape.graphics.drawCircle( 0, 0, 5 );
shape.graphics.endFill();
var bmd:BitmapData = new BitmapData(w, h, true, 0 );
bmd.draw( shape, new Matrix(1, 0, 0, 1, w/2, h/2), null, null, null, true );
_texture = context3d.createTexture( w, h, Context3DTextureFormat.BGRA, false );
_texture.uploadFromBitmapData( bmd );
bmd.dispose();
bmd = null;
}
public function get vBuf():VertexBuffer3D { return _vBuf; }
public function get uvBuf():VertexBuffer3D { return _uvBuf; }
public function get iBuf():IndexBuffer3D { return _iBuf; }
public function get texture():Texture { return _texture; }
}
class Particle {
public var x:Number = 0;
public var y:Number = 0;
public var z:Number = 0;
public var r:Number = 1;
public var g:Number = 1;
public var b:Number = 1;
public var life:Number;
public var maxlife:Number;
public function Particle() {
life = Math.random() * 200 + 100;
maxlife = life;
r = Math.random();
g = Math.random();
b = Math.random();
x = Math.random() - 0.5;
y = Math.random() - 0.5;
z = Math.random();
}
public function get matrix() : Matrix3D {
var mat:Matrix3D = new Matrix3D();
mat.appendTranslation( x, y, z );
return mat;
}
}