開発環境 Apache Flex SDK 4.12.1
FlashDevelop 4.6.1
実行環境 Microsoft Windows 8.1 (64bit)
プロジェクトの種類 ActionScript 3/AS3 Project
プロジェクト名 Context3DExample

Main.asをContext3DExample.asにリネームする。
You are renaming a file. Do you also want to update the references?
と聞かれたら「はい」ボタンを押す。

Context3DExample.asをDocument Classにする。

メニューから「Project」→「Properties」を選択する。
OutputタブのPlatformからFlash Playerを選択し、12.0を選択する。
※flash.display3Dなどが使えるのは11.0以降

http://www.bytearray.org/wp-content/projects/agalassembler/com.zip
をダウンロードし、srcディレクトリに展開する。
Context3DExample\src\com\adobe\utils\
 AGALMiniAssembler.as
 FractalGeometryGenerator.as
 PerspectiveMatrix3D.as

動作確認はContext3DExample\bin\index.htmlを開く。
http://www.maroon.dti.ne.jp/lance/flash/c3de/
http://www.maroon.dti.ne.jp/lance/flash/c3de2/

参考

Context3DExample.as
package
{
    import com.adobe.utils.AGALMiniAssembler;
    import com.adobe.utils.PerspectiveMatrix3D;
    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.ErrorEvent;
    import flash.events.Event;
    import flash.geom.Matrix3D;
    import flash.geom.Vector3D;
 
    public class Context3DExample extends Sprite
    {
        public const viewWidth:Number = 640;
        public const viewHeight:Number = 400;
        public const zNear:Number = 1;
        public const zFar:Number = 500;
 
        public const fov:Number = 45;
 
        private var stage3D:Stage3D;
        private var renderContext:Context3D;
        private var indexList:IndexBuffer3D;
        private var vertexes:VertexBuffer3D;
 
        private var projection:PerspectiveMatrix3D = new PerspectiveMatrix3D();
        private var model:Matrix3D = new Matrix3D();
        private var view:Matrix3D = new Matrix3D();
        private var finalTransform:Matrix3D = new Matrix3D();
 
        //For rotation the cube
        private const pivot:Vector3D = new Vector3D();
 
        private const VERTEX_SHADER:String = "m44 op, va0, vc0\n" + "mov v0, va1";
 
        private const FRAGMENT_SHADER:String = "mov oc, v0";
 
        private var vertexAssembly:AGALMiniAssembler = new AGALMiniAssembler();
        private var fragmentAssembly:AGALMiniAssembler = new AGALMiniAssembler();
        private var programPair:Program3D;
 
        public function Context3DExample():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
 
            this.stage.scaleMode = StageScaleMode.NO_SCALE;
            this.stage.align = StageAlign.TOP_LEFT;
            //this.stage.nativeWindow.activate(); //AIR only
 
            stage3D = this.stage.stage3Ds[0];
            stage3D.x = 10;
            stage3D.y = 10;
 
            //Add event listener before requesting the context
            stage3D.addEventListener(Event.CONTEXT3D_CREATE, contextCreated);
            stage3D.addEventListener(ErrorEvent.ERROR, contextCreationError);
            stage3D.requestContext3D(Context3DRenderMode.AUTO);
 
            //Compile shaders
            vertexAssembly.assemble(Context3DProgramType.VERTEX, VERTEX_SHADER, false);
            fragmentAssembly.assemble(Context3DProgramType.FRAGMENT, FRAGMENT_SHADER, false);
        }
 
        private function contextCreated(e:Event):void
        {
            renderContext = Stage3D(e.target).context3D;
            trace("3D driver: " + renderContext.driverInfo);
            setupScene();
        }
 
        private function setupScene():void
        {
            renderContext.enableErrorChecking = true;
            renderContext.configureBackBuffer(viewWidth, viewHeight, 2, false);
            renderContext.setCulling(Context3DTriangleFace.BACK);
 
            //Create vertex index list for the triangles forming a cube
            var triangles:Vector.<uint> = Vector.<uint>([
                2, 1, 0, //front face
                3, 2, 0,
                4, 7, 5, //bottom face
                7, 6, 5,
                8, 11, 9, //back face
                9, 11, 10,
                12, 15, 13, //top face
                13, 15, 14,
                16, 19, 17, //left face
                17, 19, 18,
                20, 23, 21, //right face
                21, 23, 22,
            ]);
            indexList = renderContext.createIndexBuffer(triangles.length);
            indexList.uploadFromVector(triangles, 0, triangles.length);
 
            //Create vertexes - cube faces do not share vertexes
            const dataPerVertex:int = 6;
            var vertexData:Vector.<Number> = Vector.<Number>([
            //	x, y, z, r, g, b,
                0, 0, 0, 1, 0, 0, //front face
                0, 1, 0, 1, 0, 0,
                1, 1, 0, 1, 0, 0,
                1, 0, 0, 1, 0, 0,
 
                0, 0, 0, 0, 1, 0, //bottom face
                1, 0, 0, 0, 1, 0,
                1, 0, 1, 0, 1, 0,
                0, 0, 1, 0, 1, 0,
 
                0, 0, 1, 1, 0, 0, //back face
                1, 0, 1, 1, 0, 0,
                1, 1, 1, 1, 0, 0,
                0, 1, 1, 1, 0, 0,
 
                0, 1, 1, 0, 1, 0, //top face
                1, 1, 1, 0, 1, 0,
                1, 1, 0, 0, 1, 0,
                0, 1, 0, 0, 1, 0,
 
                0, 1, 1, 0, 0, 1, //left face
                0, 1, 0, 0, 0, 1,
                0, 0, 0, 0, 0, 1,
                0, 0, 1, 0, 0, 1,
 
                1, 1, 0, 0, 0, 1, //right face
                1, 1, 1, 0, 0, 1,
                1, 0, 1, 0, 0, 1,
                1, 0, 0, 0, 0, 1,
            ]);
            vertexes = renderContext.createVertexBuffer(vertexData.length / dataPerVertex, dataPerVertex);
            vertexes.uploadFromVector(vertexData, 0, vertexData.length / dataPerVertex);
 
            //Identify vertex data inputs for vertex program
            renderContext.setVertexBufferAt(
                0, vertexes, 0, Context3DVertexBufferFormat.FLOAT_3); //va0 is position
            renderContext.setVertexBufferAt(
                1, vertexes, 3, Context3DVertexBufferFormat.FLOAT_3); //va1 is color
 
            //Upload programs to render context
            programPair = renderContext.createProgram();
            programPair.upload(vertexAssembly.agalcode, fragmentAssembly.agalcode);
            renderContext.setProgram(programPair);
 
            //Set up 3D transforms
            projection.perspectiveFieldOfViewRH(fov, viewWidth / viewHeight, zNear, zFar);
            view.appendTranslation(0, 0, -2); //Move view back
            model.appendTranslation(-.5, -.5, -.5); //center cube on origin
            this.stage.addEventListener(Event.ENTER_FRAME, render);
        }
 
        private function render(e:Event):void
        {
            //Rotate model on each frame
            model.appendRotation(.5, Vector3D.Z_AXIS, pivot);
            model.appendRotation(.5, Vector3D.Y_AXIS, pivot);
            model.appendRotation(.5, Vector3D.X_AXIS, pivot);
 
            //Combine transforms
            finalTransform.identity();
            finalTransform.append(model);
            finalTransform.append(view);
            finalTransform.append(projection);
 
            //Pass the final transform to the vertex shader as program constant, vc0
            renderContext.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, finalTransform, true);
 
            //Clear is required before drawTriangles on each frame
            renderContext.clear(.3, .3, .3);
 
            //Draw the 12 triangles that make up the cube
            renderContext.drawTriangles(indexList, 0, 12);
 
            //Show the frame
            renderContext.present();
        }
 
        private function contextCreationError(e:ErrorEvent):void
        {
            trace(e.errorID + ": " + e.text);
        }
 
    }
 
}
 

手動ローテーション
+ ...
Context3DExample.as
package
{
    import com.adobe.utils.AGALMiniAssembler;
    import com.adobe.utils.PerspectiveMatrix3D;
    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.ErrorEvent;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.geom.Matrix3D;
    import flash.geom.Point;
    import flash.geom.Vector3D;
    import flash.ui.Keyboard;
 
    public class Context3DExample extends Sprite
    {
        public const viewWidth:Number = 640;
        public const viewHeight:Number = 400;
        public const zNear:Number = 1;
        public const zFar:Number = 500;
 
        public const fov:Number = 45;
 
        private var stage3D:Stage3D;
        private var renderContext:Context3D;
        private var indexList:IndexBuffer3D;
        private var vertexes:VertexBuffer3D;
 
        private var projection:PerspectiveMatrix3D = new PerspectiveMatrix3D();
        private var model:Matrix3D = new Matrix3D();
        private var view:Matrix3D = new Matrix3D();
        private var finalTransform:Matrix3D = new Matrix3D();
 
        //For rotation the cube
        private const pivot:Vector3D = new Vector3D();
 
        private const VERTEX_SHADER:String = "m44 op, va0, vc0\n" + "mov v0, va1";
 
        private const FRAGMENT_SHADER:String = "mov oc, v0";
 
        private var vertexAssembly:AGALMiniAssembler = new AGALMiniAssembler();
        private var fragmentAssembly:AGALMiniAssembler = new AGALMiniAssembler();
        private var programPair:Program3D;
 
        private var lastPosition:Point = new Point();
 
        public function Context3DExample():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
 
            this.stage.scaleMode = StageScaleMode.NO_SCALE;
            this.stage.align = StageAlign.TOP_LEFT;
            //this.stage.nativeWindow.activate(); //AIR only
 
            stage3D = this.stage.stage3Ds[0];
            stage3D.x = 10;
            stage3D.y = 10;
 
            //Add event listener before requesting the context
            stage3D.addEventListener(Event.CONTEXT3D_CREATE, contextCreated);
            stage3D.addEventListener(ErrorEvent.ERROR, contextCreationError);
            stage3D.requestContext3D(Context3DRenderMode.AUTO);
 
            //Compile shaders
            vertexAssembly.assemble(Context3DProgramType.VERTEX, VERTEX_SHADER, false);
            fragmentAssembly.assemble(Context3DProgramType.FRAGMENT, FRAGMENT_SHADER, false);
 
            stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
        }
 
        private function contextCreated(e:Event):void
        {
            renderContext = Stage3D(e.target).context3D;
            trace("3D driver: " + renderContext.driverInfo);
            setupScene();
        }
 
        private function setupScene():void
        {
            renderContext.enableErrorChecking = true;
            renderContext.configureBackBuffer(viewWidth, viewHeight, 2, false);
            renderContext.setCulling(Context3DTriangleFace.BACK);
 
            //Create vertex index list for the triangles forming a cube
            var triangles:Vector.<uint> = Vector.<uint>([
                2, 1, 0, //front face
                3, 2, 0,
                4, 7, 5, //bottom face
                7, 6, 5,
                8, 11, 9, //back face
                9, 11, 10,
                12, 15, 13, //top face
                13, 15, 14,
                16, 19, 17, //left face
                17, 19, 18,
                20, 23, 21, //right face
                21, 23, 22,
            ]);
            indexList = renderContext.createIndexBuffer(triangles.length);
            indexList.uploadFromVector(triangles, 0, triangles.length);
 
            //Create vertexes - cube faces do not share vertexes
            const dataPerVertex:int = 6;
            var vertexData:Vector.<Number> = Vector.<Number>([
            //	x, y, z, r, g, b,
                0, 0, 0, 1, 0, 0, //front face
                0, 1, 0, 1, 0, 0,
                1, 1, 0, 1, 0, 0,
                1, 0, 0, 1, 0, 0,
 
                0, 0, 0, 0, 1, 0, //bottom face
                1, 0, 0, 0, 1, 0,
                1, 0, 1, 0, 1, 0,
                0, 0, 1, 0, 1, 0,
 
                0, 0, 1, 1, 0, 0, //back face
                1, 0, 1, 1, 0, 0,
                1, 1, 1, 1, 0, 0,
                0, 1, 1, 1, 0, 0,
 
                0, 1, 1, 0, 1, 0, //top face
                1, 1, 1, 0, 1, 0,
                1, 1, 0, 0, 1, 0,
                0, 1, 0, 0, 1, 0,
 
                0, 1, 1, 0, 0, 1, //left face
                0, 1, 0, 0, 0, 1,
                0, 0, 0, 0, 0, 1,
                0, 0, 1, 0, 0, 1,
 
                1, 1, 0, 0, 0, 1, //right face
                1, 1, 1, 0, 0, 1,
                1, 0, 1, 0, 0, 1,
                1, 0, 0, 0, 0, 1,
            ]);
            vertexes = renderContext.createVertexBuffer(vertexData.length / dataPerVertex, dataPerVertex);
            vertexes.uploadFromVector(vertexData, 0, vertexData.length / dataPerVertex);
 
            //Identify vertex data inputs for vertex program
            renderContext.setVertexBufferAt(
                0, vertexes, 0, Context3DVertexBufferFormat.FLOAT_3); //va0 is position
            renderContext.setVertexBufferAt(
                1, vertexes, 3, Context3DVertexBufferFormat.FLOAT_3); //va1 is color
 
            //Upload programs to render context
            programPair = renderContext.createProgram();
            programPair.upload(vertexAssembly.agalcode, fragmentAssembly.agalcode);
            renderContext.setProgram(programPair);
 
            //Set up 3D transforms
            projection.perspectiveFieldOfViewRH(fov, viewWidth / viewHeight, zNear, zFar);
            model.appendTranslation(-.5, -.5, -.5); //center cube on origin
            view.appendTranslation(0, 0, -2); //Move view back
            this.stage.addEventListener(Event.ENTER_FRAME, render);
        }
 
        private function render(e:Event):void
        {
            //Rotate model on each frame
            //model.appendRotation(.5, Vector3D.Z_AXIS, pivot);
            //model.appendRotation(.5, Vector3D.Y_AXIS, pivot);
            //model.appendRotation(.5, Vector3D.X_AXIS, pivot);
 
            //Combine transforms
            finalTransform.identity();
            finalTransform.append(model);
            finalTransform.append(view);
            finalTransform.append(projection);
 
            //Pass the final transform to the vertex shader as program constant, vc0
            renderContext.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, finalTransform, true);
 
            //Clear is required before drawTriangles on each frame
            renderContext.clear(.3, .3, .3);
 
            //Draw the 12 triangles that make up the cube
            renderContext.drawTriangles(indexList, 0, 12);
 
            //Show the frame
            renderContext.present();
        }
 
        private function contextCreationError(e:ErrorEvent):void
        {
            trace(e.errorID + ": " + e.text);
        }
 
        private function mouseMove(e:MouseEvent):void 
        {
            if (e.buttonDown)
            {
                model.appendRotation((e.localX - lastPosition.x), Vector3D.Y_AXIS, pivot);
                model.appendRotation((e.localY - lastPosition.y), Vector3D.X_AXIS, pivot);
            }
            lastPosition.x = e.localX;
            lastPosition.y = e.localY;
        }
 
        private function keyDown(e:KeyboardEvent):void 
        {
            var x:Number = 0;
            var z:Number = 0;
            switch (e.keyCode) 
            {
                case Keyboard.W: z = 0.1; break;
                case Keyboard.S: z = -0.1; break;
                case Keyboard.A: x = -0.1; break;
                case Keyboard.D: x = 0.1; break;
                default: return;
            }
            view.appendTranslation(x, 0, z);
        }
 
    }
 
}
 
最終更新:2014年06月14日 12:36