[test]stage3d, AGAL

by okoi
♥0 | Line 172 | Modified 2011-11-08 12:26:37 | MIT License
play

ActionScript3 source code

/**
 * Copyright okoi ( http://wonderfl.net/user/okoi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/eaVe
 */

/**
 * とりあえず色々な人のコードを参考にしつつ
 */
package 
{
   import com.adobe.utils.AGALMiniAssembler;
   import flash.display.Sprite;
   import flash.display.Stage3D;
   import flash.display.StageAlign;
   import flash.display.StageScaleMode;   
   import flash.display3D.Context3D;
   import flash.display3D.Context3DProgramType;
   import flash.display3D.Context3DRenderMode;
   import flash.display3D.Context3DTriangleFace;
   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.utils.ByteArray;

   [SWF(width = "465", height = "465", frameRate = "60")]
   
    /**
     * ...
     * @author
     */
    public class Main extends Sprite {
        private const WIDTH:uint = 465;
        private const HEIGHT:uint = 465;
        //
        private var stage3D:Stage3D;
        private var context3D:Context3D;
        private var programP:Program3D;
        private var vBufferXY:VertexBuffer3D;
        private var vBufferRGB:VertexBuffer3D;
        private var iBuffer:IndexBuffer3D;
        //
        private static const NUM_PARTICLE_MAX:int = 1000;
        private var _particleList:Vector.<Particle>;
        
        public function Main():void {
            //Wonderfl.disable_capture();
            
            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
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            
  
            InitParticle();
            
            stage3D = stage.stage3Ds[0];
            stage3D.addEventListener( Event.CONTEXT3D_CREATE, Context3DCreateHandler );
            //    この Stage3D インスタンスの Context3D オブジェクトの作成を要求します。
            //    Context3DRenderMode.AUTO ハードウェアレンダリングかソフトウェアレンダリングの使用できる方を自動で選択
            stage3D.requestContext3D( Context3DRenderMode.AUTO );
        }
        
        private function InitParticle() : void 
        {
            _particleList = new Vector.<Particle>(NUM_PARTICLE_MAX);
            for ( var i:int = 0; i < NUM_PARTICLE_MAX; i++ ) {
                var p:Particle = new Particle();
                p.x = Math.random() * WIDTH;
                p.y = Math.random() * HEIGHT;
                _particleList[i] = p;
            }
        }
        
        private function Context3DCreateHandler( e:Event ) : void 
        {
            context3D = stage3D.context3D;
            context3D.enableErrorChecking = true;
            
            InitShader();
            InitBuffer();
            
            context3D.configureBackBuffer( WIDTH , HEIGHT, 0, false );
            context3D.setCulling(Context3DTriangleFace.BACK);
            context3D.setVertexBufferAt(0, vBufferXY, 0, Context3DVertexBufferFormat.FLOAT_2);
            context3D.setVertexBufferAt(1, vBufferRGB, 0, Context3DVertexBufferFormat.FLOAT_3);
            context3D.setProgram(programP);
                
            addEventListener( Event.ENTER_FRAME, EnterFrameHandler );
        }        
        
        private function InitShader() : void {
            
            var agalAssembler:AGALMiniAssembler = new AGALMiniAssembler();

            var code:String = "";
            code += "m44 op, va0, vc0\n";    //    頂点レジスタ, 定数レジスタの 4x4行列演算
            code += "mov v0, va1\n";
            var vertexShader:ByteArray = agalAssembler.assemble(Context3DProgramType.VERTEX, code);
            
            code = "mov oc, v0\n";
            var fragmentShader:ByteArray = agalAssembler.assemble(Context3DProgramType.FRAGMENT, code);
            
            var mat:Matrix3D = new Matrix3D();
            mat.appendScale(2/WIDTH, -2/HEIGHT, 1);
            mat.appendTranslation(-1, 1, 0);
            context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mat, true);        //    vcレジスタに登録
                        
               programP = context3D.createProgram();
            programP.upload(vertexShader, fragmentShader);
        }
        
        private function InitBuffer() : void {
            
            //Particle
            var numVertices:uint = NUM_PARTICLE_MAX * 4;
            var numIndices:uint  = NUM_PARTICLE_MAX * 6;
            vBufferXY = context3D.createVertexBuffer(numVertices, 2);
            vBufferRGB = context3D.createVertexBuffer(numVertices, 3);
            iBuffer = context3D.createIndexBuffer(numIndices);
        }
        
        private function EnterFrameHandler( e:Event ) : void {
            
            var i:int;

            context3D.clear(0,0,0,1);
            
            //    頂点バッファ更新
            var p:Particle;
            var index:int = 0;
            var vBuf:Vector.<Number> = new Vector.<Number>(NUM_PARTICLE_MAX * 4 * 2);
            for ( i = 0; i < NUM_PARTICLE_MAX; i++ ) {
                p = _particleList[i];
                for ( var v:int = 0; v < p.vertex.length; v++ ) {
                    vBuf[index++] = p.vertex[v].x;
                    vBuf[index++] = p.vertex[v].y;
                }
            }
            vBufferXY.uploadFromVector(vBuf, 0, NUM_PARTICLE_MAX * 4);
            
            //    インデックスバッファ更新
            index = 0;
            var iBuf:Vector.<uint> = new Vector.<uint>(NUM_PARTICLE_MAX * 6);
            var t:uint = 0;
            for ( i = 0; i < NUM_PARTICLE_MAX; i++ ) {
                t = i << 2;
                p = _particleList[i];
                iBuf[index++] = t + p.index[0];
                iBuf[index++] = t + p.index[1];
                iBuf[index++] = t + p.index[2];
                iBuf[index++] = t + p.index[3];
                iBuf[index++] = t + p.index[4];
                iBuf[index++] = t + p.index[5];
            }
            iBuffer.uploadFromVector( iBuf, 0, NUM_PARTICLE_MAX * 6 );
            
            //    色は白固定
            index = 0;
            var colorBuf:Vector.<Number> = new Vector.<Number>(NUM_PARTICLE_MAX * 4 * 3);
            for ( i = 0; i < NUM_PARTICLE_MAX; i++ ) {
                for ( v = 0; v < 4; v++ ){
                    colorBuf[index++] = 1;
                    colorBuf[index++] = 1;
                    colorBuf[index++] = 1;
                }
            }
            vBufferRGB.uploadFromVector( colorBuf, 0, NUM_PARTICLE_MAX * 4 );
            
            
            //    描画
            context3D.drawTriangles(iBuffer);
            context3D.present();
        }
    }
}

import flash.geom.Point;

class Particle {
    private var _x:Number = 0;
    private var _y:Number = 0;
    
    public var vertex:Vector.<Point> = new Vector.<Point>(4);
    public var index:Vector.<uint> = new Vector.<uint>(6);
    
    public function Particle() {
        var i:int;
        for ( i = 0; i < 4; i++ ) {
            vertex[i] = new Point();
        }
        SetVertex();
        
        index[0] = 0;
        index[1] = 2;
        index[2] = 1;
        index[3] = 1;
        index[4] = 2;
        index[5] = 3;
    }
    
    public function get x():Number { return _x;    }
    public function get y():Number { return _y; }
    
    public function set x( val:Number ) : void {
        _x = val;
        SetVertex();
    }
    public function set y( val:Number ) : void {
        _y = val;
        SetVertex();
    }
    
    private function SetVertex() : void {
        
        vertex[0].x = _x - 0.5;
        vertex[0].y = _y - 0.5;
        vertex[1].x = _x - 0.5;
        vertex[1].y = _y + 0.5;
        vertex[2].x = _x + 0.5;
        vertex[2].y = _y - 0.5;
        vertex[3].x = _x + 0.5;
        vertex[3].y = _y + 0.5;
    }
}