• (转)Stage3D程序的基本步骤


    原文:http://www.flashache.com/2012/10/31/stage3d-program-basic-steps/   作者:flashche

    本月24号《flash开发者大会》,我选择了《AGAL程序设计》这么一个比较难讲的主题。这么一个相对比较小众的主题,在开发者大会这种需要顾虑到所有人的一个场合下讲,如何选择切入点是很重要的。说起来要跑通一个基础的Stage3D的程序,有很多步骤,就就比较难解释了,短短的40分钟要让全场大部分人都理解可以说是基本不可能,所以肯定不可能详细阐述这块的细节。当然,如果真能做到这点的话那就更棒了。所以决定在这整理一下完成一个Stage3D项目的基本开发流程,方便大家参考。附上的参考也是非常好的学习资料哦,:-)

    flash开发者大会:http://www.wefdc.com/info

    参考资料:
    Christer Kaitila, 《Adobe Flash 11 Stage3D(Molehill) Game Programming》, PACKT publishing
    Norbz’s Dev Blog, “Stage3D / AGAL from scratch”, http://blog.norbz.net/tutorials/
    7yue,“深入Stage3D”, http://t.cn/SbMKLo

    因为比较详细,而且为了便于理解,所以这篇文章会比较长,不过主要是重复代码,所以不用担心,不会花费太长时间。

    1、创建基础类

    package
    {
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.events.Event;
      
        [SWF(width="600",height="400",frameRate="60")]
        public class Stage3DBasic extends Sprite
        {
            public function Stage3DBasic()
            {
                if(stage != null) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
            }
      
            private function init(e:Event = null):void
            {
                if(hasEventListener(Event.ADDED_TO_STAGE))
                    removeEventListener(Event.ADDED_TO_STAGE, init);
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
            }
        }
    }

    为Stage3D设置这3个Frame rate,20/30/60

    2、请求Context3D对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    package
    {
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.display3D.Context3D;
        import flash.events.Event;
      
        [SWF(width="600",height="400",frameRate="60")]
        public class Stage3DBasic extends Sprite
        {
            private var _view_Number;
            private var _view_height:Number;
      
            private var _renderContext:Context3D;
      
            public function Stage3DBasic()
            {
                if(stage != null) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
            }
      
            private function init(e:Event = null):void
            {
                if(hasEventListener(Event.ADDED_TO_STAGE))
                    removeEventListener(Event.ADDED_TO_STAGE, init);
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
      
                _view_width = stage.stageWidth;
                _view_height = stage.stageHeight;
      
                stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
                stage.stage3Ds[0].requestContext3D();
            }
      
            private function onContext3DCreate(e:Event):void
            {
                _renderContext = stage.stage3Ds[0].context3D;
            }
        }
    }

    3、设置Context3D Display Buffer

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    package
    {
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.display3D.Context3D;
        import flash.events.Event;
      
        [SWF(width="600",height="400",frameRate="60")]
        public class Stage3DBasic extends Sprite
        {
            private var _view_Number;
            private var _view_height:Number;
      
            private var _renderContext:Context3D;
      
            public function Stage3DBasic()
            {
                if(stage != null) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
            }
      
            private function init(e:Event = null):void
            {
                if(hasEventListener(Event.ADDED_TO_STAGE))
                    removeEventListener(Event.ADDED_TO_STAGE, init);
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
      
                _view_width = stage.stageWidth;
                _view_height = stage.stageHeight;
      
                stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
                stage.stage3Ds[0].requestContext3D();
            }
      
            private function onContext3DCreate(e:Event):void
            {
                _renderContext = stage.stage3Ds[0].context3D;
                _renderContext.configureBackBuffer(_view_width, _view_height, 0, true);
            }
        }
    }

    4、初始化模型数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    package
    {
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.display3D.Context3D;
        import flash.events.Event;
      
        [SWF(width="600",height="400",frameRate="60")]
        public class Stage3DBasic extends Sprite
        {
            private var _view_Number;
            private var _view_height:Number;
      
            private var _renderContext:Context3D;
      
            private var _meshVertexData:Vector.<Number>;
            private var _meshInexData:Vector.<uint>;
      
            public function Stage3DBasic()
            {
                if(stage != null) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
            }
      
            private function init(e:Event = null):void
            {
                if(hasEventListener(Event.ADDED_TO_STAGE))
                    removeEventListener(Event.ADDED_TO_STAGE, init);
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
      
                _view_width = stage.stageWidth;
                _view_height = stage.stageHeight;
      
                stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
                stage.stage3Ds[0].requestContext3D();
            }
      
            private function onContext3DCreate(e:Event):void
            {
                _renderContext = stage.stage3Ds[0].context3D;
                _renderContext.configureBackBuffer(_view_width, _view_height, 0, true);
      
                initData();
            }
      
            private function initData():void
            {
                _meshVertexData = Vector.<Number>([
                        //X,  Y,     Z,  r, g, b
                        -0.3, -0.301, 0, 0,
                        0,    0.3,   00, 1, 0,
                        0.3, -0.3,   00, 0, 1
                    ]);
                _meshInexData = Vector.<uint>([
                        0, 1, 2
                    ]);
            }
        }
    }

    为了简单起见,定义的是一个三角形,可以看到两个数据,一个是meshVertexData,定义了每个定点的位置,和颜色值,一共三个点,每个点包含了6个数据,分别是x, y, z和r, g, b。meshVertexData包含了三个这样的数据。然后是meshIndexData,定义了链接这些定点的顺序,0, 1, 2,即按照顺序链接这三个定点,有点像小时候玩的连线游戏,是不是很简单就能理解了 :D

    5、创建顶点缓冲和索引缓冲,并上传数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    package
    {
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.display3D.Context3D;
        import flash.display3D.IndexBuffer3D;
        import flash.display3D.VertexBuffer3D;
        import flash.events.Event;
      
        [SWF(width="600",height="400",frameRate="60")]
        public class Stage3DBasic extends Sprite
        {
            private var _view_Number;
            private var _view_height:Number;
      
            private var _renderContext:Context3D;
      
            private var _meshVertexData:Vector.<Number>;
            private var _meshInexData:Vector.<uint>;
      
            private var _vertexBuffer:VertexBuffer3D;
            private var _indexBuffer:IndexBuffer3D;
      
            public function Stage3DBasic()
            {
                if(stage != null) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
            }
      
            private function init(e:Event = null):void
            {
                if(hasEventListener(Event.ADDED_TO_STAGE))
                    removeEventListener(Event.ADDED_TO_STAGE, init);
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
      
                _view_width = stage.stageWidth;
                _view_height = stage.stageHeight;
      
                stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
                stage.stage3Ds[0].requestContext3D();
            }
      
            private function onContext3DCreate(e:Event):void
            {
                _renderContext = stage.stage3Ds[0].context3D;
                _renderContext.configureBackBuffer(_view_width, _view_height, 0, true);
      
                initData();
      
                _vertexBuffer = _renderContext.createVertexBuffer(_meshVertexData.length / 6, 6);
                _vertexBuffer.uploadFromVector(_meshVertexData, 0, _meshVertexData.length / 6);
      
                _indexBuffer = _renderContext.createIndexBuffer(_meshInexData.length);
                _indexBuffer.uploadFromVector(_meshInexData, 0, _meshInexData.length);
            }
      
            private function initData():void
            {
                _meshVertexData = Vector.<Number>([
                        //X,  Y,     Z,  r, g, b
                        -0.3, -0.301, 0, 0,
                        0,    0.3,   00, 1, 0,
                        0.3, -0.3,   00, 0, 1
                    ]);
                _meshInexData = Vector.<uint>([
                        0, 1, 2
                    ]);
            }
        }
    }

    createVertexBuffer,传入的几个定点,以及每个定点包含的数据量。根据现有demo定义的meshVertexData,一共有meshVertexData.lenght/ 6个顶点,其实也就是3个,然后每个定点包含了:x,y,z,r,g,b,6个数据。

    6、编译Vertex Shader

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    package
    {
        import com.adobe.utils.AGALMiniAssembler;
      
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.display3D.Context3D;
        import flash.display3D.Context3DProgramType;
        import flash.display3D.IndexBuffer3D;
        import flash.display3D.VertexBuffer3D;
        import flash.events.Event;
        import flash.utils.ByteArray;
      
        [SWF(width="600",height="400",frameRate="60")]
        public class Stage3DBasic extends Sprite
        {
            private var _view_Number;
            private var _view_height:Number;
      
            private var _renderContext:Context3D;
      
            private var _meshVertexData:Vector.<Number>;
            private var _meshInexData:Vector.<uint>;
      
            private var _vertexBuffer:VertexBuffer3D;
            private var _indexBuffer:IndexBuffer3D;
      
            private var _vertexShader:ByteArray;
      
            public function Stage3DBasic()
            {
                if(stage != null) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
            }
      
            private function init(e:Event = null):void
            {
                if(hasEventListener(Event.ADDED_TO_STAGE))
                    removeEventListener(Event.ADDED_TO_STAGE, init);
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
      
                _view_width = stage.stageWidth;
                _view_height = stage.stageHeight;
      
                stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
                stage.stage3Ds[0].requestContext3D();
            }
      
            private function onContext3DCreate(e:Event):void
            {
                _renderContext = stage.stage3Ds[0].context3D;
                _renderContext.configureBackBuffer(_view_width, _view_height, 0, true);
      
                initData();
      
                _vertexBuffer = _renderContext.createVertexBuffer(_meshVertexData.length / 6, 6);
                _vertexBuffer.uploadFromVector(_meshVertexData, 0, _meshVertexData.length / 6);
      
                _indexBuffer = _renderContext.createIndexBuffer(_meshInexData.length);
                _indexBuffer.uploadFromVector(_meshInexData, 0, _meshInexData.length);
      
                var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                _vertexShader = vertexShaderAssembler.assemble(
                        Context3DProgramType.VERTEX,
                        "mov op, va0\n" +
                        "mov v0, va1\n"
                    );
            }
      
            private function initData():void
            {
                _meshVertexData = Vector.<Number>([
                        //X,  Y,     Z,  r, g, b
                        -0.3, -0.301, 0, 0,
                        0,    0.3,   00, 1, 0,
                        0.3, -0.3,   00, 0, 1
                    ]);
                _meshInexData = Vector.<uint>([
                        0, 1, 2
                    ]);
            }
        }
    }

    示例包含了两行AGAL代码,使用了同一个opcode:mov,第一行将va0(将保存位置信息)输出到op,然后第二行将保存了颜色信息的va1赋值给v0,这种寄存器保存的信息共享于vertex shader和fragment shader。

    7、编译Fragment Shader

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    package
    {
        import com.adobe.utils.AGALMiniAssembler;
      
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.display3D.Context3D;
        import flash.display3D.Context3DProgramType;
        import flash.display3D.IndexBuffer3D;
        import flash.display3D.VertexBuffer3D;
        import flash.events.Event;
        import flash.utils.ByteArray;
      
        [SWF(width="600",height="400",frameRate="60")]
        public class Stage3DBasic extends Sprite
        {
            private var _view_Number;
            private var _view_height:Number;
      
            private var _renderContext:Context3D;
      
            private var _meshVertexData:Vector.<Number>;
            private var _meshInexData:Vector.<uint>;
      
            private var _vertexBuffer:VertexBuffer3D;
            private var _indexBuffer:IndexBuffer3D;
      
            private var _vertexShader:ByteArray;
            private var _fragmentShader:ByteArray;
      
            public function Stage3DBasic()
            {
                if(stage != null) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
            }
      
            private function init(e:Event = null):void
            {
                if(hasEventListener(Event.ADDED_TO_STAGE))
                    removeEventListener(Event.ADDED_TO_STAGE, init);
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
      
                _view_width = stage.stageWidth;
                _view_height = stage.stageHeight;
      
                stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
                stage.stage3Ds[0].requestContext3D();
            }
      
            private function onContext3DCreate(e:Event):void
            {
                _renderContext = stage.stage3Ds[0].context3D;
                _renderContext.configureBackBuffer(_view_width, _view_height, 0, true);
      
                initData();
      
                _vertexBuffer = _renderContext.createVertexBuffer(_meshVertexData.length / 6, 6);
                _vertexBuffer.uploadFromVector(_meshVertexData, 0, _meshVertexData.length / 6);
      
                _indexBuffer = _renderContext.createIndexBuffer(_meshInexData.length);
                _indexBuffer.uploadFromVector(_meshInexData, 0, _meshInexData.length);
      
                var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                _vertexShader = vertexShaderAssembler.assemble(
                        Context3DProgramType.VERTEX,
                        "mov op, va0\n" +
                        "mov v0, va1\n"
                    );
      
                var fragmentShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                _fragmentShader = fragmentShaderAssembler.assemble(
                        Context3DProgramType.FRAGMENT,
                        "mov oc, v0\n"
                    );
            }
      
            private function initData():void
            {
                _meshVertexData = Vector.<Number>([
                        //X,  Y,     Z,  r, g, b
                        -0.3, -0.301, 0, 0,
                        0,    0.3,   00, 1, 0,
                        0.3, -0.3,   00, 0, 1
                    ]);
                _meshInexData = Vector.<uint>([
                        0, 1, 2
                    ]);
            }
        }
    }

    此处的fragment shader只是将v0保存的颜色信息给输出出来。

    8、创建Program3D实例,并上传Shader

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    package
    {
        import com.adobe.utils.AGALMiniAssembler;
      
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.display3D.Context3D;
        import flash.display3D.Context3DProgramType;
        import flash.display3D.IndexBuffer3D;
        import flash.display3D.Program3D;
        import flash.display3D.VertexBuffer3D;
        import flash.events.Event;
        import flash.utils.ByteArray;
      
        [SWF(width="600",height="400",frameRate="60")]
        public class Stage3DBasic extends Sprite
        {
            private var _view_Number;
            private var _view_height:Number;
      
            private var _renderContext:Context3D;
      
            private var _meshVertexData:Vector.<Number>;
            private var _meshInexData:Vector.<uint>;
      
            private var _vertexBuffer:VertexBuffer3D;
            private var _indexBuffer:IndexBuffer3D;
      
            private var _vertexShader:ByteArray;
            private var _fragmentShader:ByteArray;
      
            private var _shaderProgram:Program3D;
      
            public function Stage3DBasic()
            {
                if(stage != null) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
            }
      
            private function init(e:Event = null):void
            {
                if(hasEventListener(Event.ADDED_TO_STAGE))
                    removeEventListener(Event.ADDED_TO_STAGE, init);
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
      
                _view_width = stage.stageWidth;
                _view_height = stage.stageHeight;
      
                stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
                stage.stage3Ds[0].requestContext3D();
            }
      
            private function onContext3DCreate(e:Event):void
            {
                _renderContext = stage.stage3Ds[0].context3D;
                _renderContext.configureBackBuffer(_view_width, _view_height, 0, true);
      
                initData();
      
                _vertexBuffer = _renderContext.createVertexBuffer(_meshVertexData.length / 6, 6);
                _vertexBuffer.uploadFromVector(_meshVertexData, 0, _meshVertexData.length / 6);
      
                _indexBuffer = _renderContext.createIndexBuffer(_meshInexData.length);
                _indexBuffer.uploadFromVector(_meshInexData, 0, _meshInexData.length);
      
                var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                _vertexShader = vertexShaderAssembler.assemble(
                        Context3DProgramType.VERTEX,
                        "mov op, va0\n" +
                        "mov v0, va1\n"
                    );
      
                var fragmentShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                _fragmentShader = fragmentShaderAssembler.assemble(
                        Context3DProgramType.FRAGMENT,
                        "mov oc, v0\n"
                    );
      
                _shaderProgram = _renderContext.createProgram();
                _shaderProgram.upload(_vertexShader, _fragmentShader);
      
            }
      
            private function initData():void
            {
                _meshVertexData = Vector.<Number>([
                        //X,  Y,     Z,  r, g, b
                        -0.3, -0.301, 0, 0,
                        0,    0.3,   00, 1, 0,
                        0.3, -0.3,   00, 0, 1
                    ]);
                _meshInexData = Vector.<uint>([
                        0, 1, 2
                    ]);
            }
        }
    }

    9、设置Shader数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    package
    {
        import com.adobe.utils.AGALMiniAssembler;
      
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        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.utils.ByteArray;
      
        [SWF(width="600",height="400",frameRate="60")]
        public class Stage3DBasic extends Sprite
        {
            private var _view_Number;
            private var _view_height:Number;
      
            private var _renderContext:Context3D;
      
            private var _meshVertexData:Vector.<Number>;
            private var _meshInexData:Vector.<uint>;
      
            private var _vertexBuffer:VertexBuffer3D;
            private var _indexBuffer:IndexBuffer3D;
      
            private var _vertexShader:ByteArray;
            private var _fragmentShader:ByteArray;
      
            private var _shaderProgram:Program3D;
      
            public function Stage3DBasic()
            {
                if(stage != null) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
            }
      
            private function init(e:Event = null):void
            {
                if(hasEventListener(Event.ADDED_TO_STAGE))
                    removeEventListener(Event.ADDED_TO_STAGE, init);
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
      
                _view_width = stage.stageWidth;
                _view_height = stage.stageHeight;
      
                stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
                stage.stage3Ds[0].requestContext3D();
            }
      
            private function onContext3DCreate(e:Event):void
            {
                _renderContext = stage.stage3Ds[0].context3D;
                _renderContext.configureBackBuffer(_view_width, _view_height, 0, true);
      
                initData();
      
                _vertexBuffer = _renderContext.createVertexBuffer(_meshVertexData.length / 6, 6);
                _vertexBuffer.uploadFromVector(_meshVertexData, 0, _meshVertexData.length / 6);
      
                _indexBuffer = _renderContext.createIndexBuffer(_meshInexData.length);
                _indexBuffer.uploadFromVector(_meshInexData, 0, _meshInexData.length);
      
                var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                _vertexShader = vertexShaderAssembler.assemble(
                        Context3DProgramType.VERTEX,
                        "mov op, va0\n" +
                        "mov v0, va1\n"
                    );
      
                var fragmentShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                _fragmentShader = fragmentShaderAssembler.assemble(
                        Context3DProgramType.FRAGMENT,
                        "mov oc, v0\n"
                    );
      
                _shaderProgram = _renderContext.createProgram();
                _shaderProgram.upload(_vertexShader, _fragmentShader);
      
                _renderContext.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
                _renderContext.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_3);
            }
      
            private function initData():void
            {
                _meshVertexData = Vector.<Number>([
                        //X,  Y,     Z,  r, g, b
                        -0.3, -0.301, 0, 0,
                        0,    0.3,   00, 1, 0,
                        0.3, -0.3,   00, 0, 1
                    ]);
                _meshInexData = Vector.<uint>([
                        0, 1, 2
                    ]);
            }
        }
    }

    设置shader数据,分别设置了va0和va1。

    10、设置当前的shader程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    package
    {
        import com.adobe.utils.AGALMiniAssembler;
      
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        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.utils.ByteArray;
      
        [SWF(width="600",height="400",frameRate="60")]
        public class Stage3DBasic extends Sprite
        {
            private var _view_Number;
            private var _view_height:Number;
      
            private var _renderContext:Context3D;
      
            private var _meshVertexData:Vector.<Number>;
            private var _meshInexData:Vector.<uint>;
      
            private var _vertexBuffer:VertexBuffer3D;
            private var _indexBuffer:IndexBuffer3D;
      
            private var _vertexShader:ByteArray;
            private var _fragmentShader:ByteArray;
      
            private var _shaderProgram:Program3D;
      
            public function Stage3DBasic()
            {
                if(stage != null) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
            }
      
            private function init(e:Event = null):void
            {
                if(hasEventListener(Event.ADDED_TO_STAGE))
                    removeEventListener(Event.ADDED_TO_STAGE, init);
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
      
                _view_width = stage.stageWidth;
                _view_height = stage.stageHeight;
      
                stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
                stage.stage3Ds[0].requestContext3D();
            }
      
            private function onContext3DCreate(e:Event):void
            {
                _renderContext = stage.stage3Ds[0].context3D;
                _renderContext.configureBackBuffer(_view_width, _view_height, 0, true);
      
                initData();
      
                _vertexBuffer = _renderContext.createVertexBuffer(_meshVertexData.length / 6, 6);
                _vertexBuffer.uploadFromVector(_meshVertexData, 0, _meshVertexData.length / 6);
      
                _indexBuffer = _renderContext.createIndexBuffer(_meshInexData.length);
                _indexBuffer.uploadFromVector(_meshInexData, 0, _meshInexData.length);
      
                var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                _vertexShader = vertexShaderAssembler.assemble(
                        Context3DProgramType.VERTEX,
                        "mov op, va0\n" +
                        "mov v0, va1\n"
                    );
      
                var fragmentShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                _fragmentShader = fragmentShaderAssembler.assemble(
                        Context3DProgramType.FRAGMENT,
                        "mov oc, v0\n"
                    );
      
                _shaderProgram = _renderContext.createProgram();
                _shaderProgram.upload(_vertexShader, _fragmentShader);
      
                _renderContext.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
                _renderContext.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_3);
      
                _renderContext.setProgram(_shaderProgram);
            }
      
            private function initData():void
            {
                _meshVertexData = Vector.<Number>([
                        //X,  Y,     Z,  r, g, b
                        -0.3, -0.301, 0, 0,
                        0,    0.3,   00, 1, 0,
                        0.3, -0.3,   00, 0, 1
                    ]);
                _meshInexData = Vector.<uint>([
                        0, 1, 2
                    ]);
            }
        }
    }

    11、渲染

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    package
    {
        import com.adobe.utils.AGALMiniAssembler;
      
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        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.utils.ByteArray;
      
        [SWF(width="600",height="400",frameRate="60")]
        public class Stage3DBasic extends Sprite
        {
            private var _view_Number;
            private var _view_height:Number;
      
            private var _renderContext:Context3D;
      
            private var _meshVertexData:Vector.<Number>;
            private var _meshInexData:Vector.<uint>;
      
            private var _vertexBuffer:VertexBuffer3D;
            private var _indexBuffer:IndexBuffer3D;
      
            private var _vertexShader:ByteArray;
            private var _fragmentShader:ByteArray;
      
            private var _shaderProgram:Program3D;
      
            public function Stage3DBasic()
            {
                if(stage != null) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
            }
      
            private function init(e:Event = null):void
            {
                if(hasEventListener(Event.ADDED_TO_STAGE))
                    removeEventListener(Event.ADDED_TO_STAGE, init);
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
      
                _view_width = stage.stageWidth;
                _view_height = stage.stageHeight;
      
                stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
                stage.stage3Ds[0].requestContext3D();
            }
      
            private function onContext3DCreate(e:Event):void
            {
                _renderContext = stage.stage3Ds[0].context3D;
                _renderContext.configureBackBuffer(_view_width, _view_height, 0, true);
      
                initData();
      
                _vertexBuffer = _renderContext.createVertexBuffer(_meshVertexData.length / 6, 6);
                _vertexBuffer.uploadFromVector(_meshVertexData, 0, _meshVertexData.length / 6);
      
                _indexBuffer = _renderContext.createIndexBuffer(_meshInexData.length);
                _indexBuffer.uploadFromVector(_meshInexData, 0, _meshInexData.length);
      
                var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                _vertexShader = vertexShaderAssembler.assemble(
                        Context3DProgramType.VERTEX,
                        "mov op, va0\n" +
                        "mov v0, va1\n"
                    );
      
                var fragmentShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                _fragmentShader = fragmentShaderAssembler.assemble(
                        Context3DProgramType.FRAGMENT,
                        "mov oc, v0\n"
                    );
      
                _shaderProgram = _renderContext.createProgram();
                _shaderProgram.upload(_vertexShader, _fragmentShader);
      
                _renderContext.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
                _renderContext.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_3);
      
                _renderContext.setProgram(_shaderProgram);
      
                addEventListener(Event.ENTER_FRAME, render);
            }
      
            private function render(e:Event):void
            {
                _renderContext.clear(0,0,0,0);
                _renderContext.drawTriangles(_indexBuffer);
                _renderContext.present();
            }
      
            private function initData():void
            {
                _meshVertexData = Vector.<Number>([
                        //X,  Y,     Z,  r, g, b
                        -0.3, -0.301, 0, 0,
                        0,    0.3,   00, 1, 0,
                        0.3, -0.3,   00, 0, 1
                    ]);
                _meshInexData = Vector.<uint>([
                        0, 1, 2
                    ]);
            }
        }
    }

    最终结果:

    虽然只是一个三角,但是这正是stage3d底层开发的一个开端,虽然步骤看上去很多,而且不同的情况下这些步骤的细节会有所调整,但是掌握好这个demo才能继续接下来的内容。下一篇文章我将继续Stage3D的底层开发,使用uv贴图。尽请期待。

  • 相关阅读:
    《Linux命令行与shell脚本编程大全 第3版》高级Shell脚本编程---07
    《Linux命令行与shell脚本编程大全 第3版》高级Shell脚本编程---05
    shell-查看手机分辨率
    imageView-scaleType 图片压缩属性
    actionbar-displayOptions 属性分析
    setting.system-全局属性的设定
    ActivityChooserView-如何隐藏选择的应用图标
    mIsFunui-判断Funui方法
    setting-在设置中添加新的选项
    install-软件安装跟push的区别
  • 原文地址:https://www.cnblogs.com/hisiqi/p/2948743.html
Copyright © 2020-2023  润新知