zoukankan      html  css  js  c++  java
  • 第一次使用stage3D创建一个图形流程

    stage3D成像的具体流程一般我们分为:准备阶段和在每一帧中的渲染阶段

    一、准备阶段:

    1、初始化stage3D

    2、对舞台进行一些简单的设置

    3、准备模型数据(通过数组形式存储)

    • 准备存放顶点信息的数组
    • 准备存放顶点的索引数组

    4、把模型数据上传给显卡(通过顶索引缓冲IndexBuffer3D和顶点信息缓冲VertexBuffer3D上传)

    5、把纹理上传给显卡

    6、创建着色器

    • 创建顶点着色器
    • 创建片段着色器
    • 合并着色器提交给显卡

    7、准备摄像机

    8、启动主循环进行对模型数据在每一帧中的渲染

    二、渲染阶段

    1、清空缓冲区

    2、给着色器传入参数,调用着色器

    • 调整模型的transform
    • 把主矩阵传给顶点着色器的vc0(主矩阵即为存放包括模型矩阵、摄像机矩阵、视场矩阵,vc0为顶点着色器的常量寄存器,编号自己取)
    • 将顶点位置和大小等信息传给顶点着色器的特殊寄存器va0
    • 将顶点的颜色信息(rgba)传给顶点着色器的特殊寄存器的va1
    • 将顶点的UV信息传给顶点着色器的特殊寄存器的va2
    • 将模型的颜色的指定的信息传给片段着色器的常量寄存器的fc0
    • 将材质上传给片段着色器的特殊寄存器fs0

    3、画三角形

    4、准备下一个缓冲区

    以上步骤代码实现如下:(黄色背景的为准备阶段的操作、红色背景的为渲染阶段的操作)

    需注意在传入的图片的大小必须是2的幂次

    package
    {
        import com.adobe.utils.AGALMiniAssembler;
        import com.adobe.utils.PerspectiveMatrix3D;
        
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.display.Sprite;
        import flash.display.Stage3D;
        import flash.display3D.Context3D;
        import flash.display3D.Context3DProgramType;
        import flash.display3D.Context3DTextureFormat;
        import flash.display3D.Context3DVertexBufferFormat;
        import flash.display3D.IndexBuffer3D;
        import flash.display3D.Program3D;
        import flash.display3D.VertexBuffer3D;
        import flash.display3D.textures.Texture;
        import flash.events.Event;
        import flash.geom.Matrix;
        import flash.geom.Matrix3D;
        import flash.geom.Vector3D;
        
        public class Stage3DTest002_Texture extends Sprite
        {
            //纹理所需的图片
            [Embed(source="Delicious.png")]private var Img1:Class;
            [Embed(source="meinv.jpg")]private var Img2:Class;
            /******核心3D引擎*********/
            private var context3D:Context3D;
            
            /******模型数据**********/
            private var vertexIndexData:Vector.<uint>;
            private var vertexData:Vector.<Number>;
            
            /******顶点索引的缓冲(通过这个东西上传给GPU)**********/
            private var indexBuffer:IndexBuffer3D;
            private var vertexBuffer:VertexBuffer3D;
            
            /**定义自己的着色器*/
            private var shaderProgram:Program3D;
    
            /**摄像机所需的矩阵**/
            private var modelMatrix:Matrix3D = new Matrix3D();//用于描述模型的变化transform
            private var viewMatrix:Matrix3D = new Matrix3D();//用于描述摄像机的transform
            private var vohMatrix:PerspectiveMatrix3D = new PerspectiveMatrix3D();//视场矩阵
            private var mainMatrix:Matrix3D = new Matrix3D();//上述三个矩阵的合并
            
            /**********颜色***************/
            private var col:Vector.<Number> = new Vector.<Number>();
            /************纹理************/
            private var texture1:Texture;
            private var texture2:Texture;
            public function Stage3DTest002_Texture()
            {
                /*******************************************1初始化stage3D*********************************************************************/
                var stage3D:Stage3D = stage.stage3Ds[0];
                stage3D.addEventListener(Event.CONTEXT3D_CREATE,onContext3DCreated);
                stage3D.requestContext3D();
            }
            
            protected function onContext3DCreated(event:Event):void
            {
                //3D引擎创建完成
                //进行相关的设置
                /********************************************2进行一些简单的设置******************************************************************/
                var stage3D:Stage3D = event.target as Stage3D;
                //或得context3D,因为所有实际功能,比如上传、渲染全部都是调用的context3D的方法
                context3D = stage3D.context3D;
                //启用错误检查(以牺牲效率为代价,在控制台打印出AGAL的运行信息)
                context3D.enableErrorChecking = true;
                //开启一块缓冲区
                context3D.configureBackBuffer(stage.stageWidth,stage.stageHeight,1);//
                /********************************************3准备模型数据************************************************************************/
                initData();
                /********************************************4把模型数据上传给显卡******************************************************************/
                indexBuffer = context3D.createIndexBuffer(vertexIndexData.length);
                indexBuffer.uploadFromVector(vertexIndexData,0,vertexIndexData.length);
                vertexBuffer = context3D.createVertexBuffer(vertexData.length / 9,9);
                vertexBuffer.uploadFromVector(vertexData,0,vertexData.length /9);
                /********************************************5把纹理上传***************************************************************************/
                texture1 = uploadTexture(new Img1());
                texture2 = uploadTexture(new Img2());
                /*********************************************6创建着色器**************************************************************************/
                initShader();
                
                /**********************************************7准备摄像机**************************************************************************/
                initCamear();
                
                //设定颜色
                col.push(1,1,1,1);//红色
                modelMatrix.appendRotation(-90,Vector3D.Z_AXIS);
                /***********************************************8启动渲染循环***********************************************************************/
                stage.addEventListener(Event.ENTER_FRAME , update);
            }
            
            /**上传纹理*/
            private function uploadTexture(img:Bitmap):Texture
            {
                var texture:Texture = context3D.createTexture(img.width,img.height,Context3DTextureFormat.BGRA,true);
                //上传纹理
                texture.uploadFromBitmapData(img.bitmapData);
                //mip映射
                var w:int = img.width;
                var h:int  = img.height;
                var level:int = 0;
                var matrix:Matrix = new Matrix();
                //创建一个bitmapData来绘制每个级别的mip映射像素
                var bmd:BitmapData = new BitmapData(w,h,true,0);
                while(w > 1 && h > 1){
                    bmd.draw(img,matrix,null,null,null,true);
                    texture.uploadFromBitmapData(bmd,level);
                    trace(bmd.width+" "+bmd.height+" "+level);
                    
                    w >>= 1;
                    h >>= 1;
                    
                    matrix.scale(0.5,0.5);
                    level++;
                    //清空,然后创建一个原来的一半大小的bitmapdata
                    bmd.dispose();
                    bmd = new BitmapData(w,h,true,0);
                }
                return texture;
            }
            
            protected function update(event:Event):void
            {
                /********************************************1清空当前的缓冲区***************************************************************/
                context3D.clear();
                /********************************************2给着色器传入参数,调用着色器****************************************************/
                context3D.setProgram(shaderProgram);//指定着色器,(着色器可能有多个,一个负责。。。,另一个负责..)
                
                this.mainMatrix.identity();//单位化此矩阵,去掉所有的transform信息,转化为单位矩阵
                mainMatrix.append(this.modelMatrix);
                mainMatrix.append(this.viewMatrix);
                mainMatrix.append(this.vohMatrix);
                
                //让图形动起来
    
                modelMatrix.appendRotation(1,Vector3D.Z_AXIS);            modelMatrix.appendRotation(1,Vector3D.Y_AXIS);            modelMatrix.appendRotation(1,Vector3D.X_AXIS);
                
                //把这个矩阵传给顶点着色器的vc0(第0个常量寄存器)
                context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,mainMatrix,true);
                //va0传值.给顶点着色器的第0个传入定点数据
                context3D.setVertexBufferAt(0,vertexBuffer,0,Context3DVertexBufferFormat.FLOAT_3);
                //给顶点着色器的第1个va寄存器
                context3D.setVertexBufferAt(1,this.vertexBuffer,5,Context3DVertexBufferFormat.FLOAT_4);
                //给顶点着色器的第2个va寄存器传入UV值
                context3D.setVertexBufferAt(2,vertexBuffer,3,Context3DVertexBufferFormat.FLOAT_2);
                //给片段着色器的fc0传值
                col.splice(0,4);
                col.push(Math.random(),Math.random(),Math.random(),Math.random());
                context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT,0,col);
                //上传纹理fs0
                context3D.setTextureAt(0,texture1);
                //上传纹理fs1
                context3D.setTextureAt(1,texture2);
                /*************************************************3画三角形*********************************************************************/
                context3D.drawTriangles(indexBuffer,0,vertexIndexData.length/3);
                /*************************************************4准备下一个缓冲区**************************************************************/
                context3D.present();
            }
            
            /**
             * 初始化摄像机
             * */
            private function initCamear():void
            {
                //让摄像机向后移
                viewMatrix.appendTranslation(0,0,-10);
                //利用voh对场景进行裁剪
                vohMatrix.perspectiveFieldOfViewRH(Math.PI/4,stage.stageWidth/stage.stageHeight,0.01,100);
            }
            
            /**
             * 创建一个简单的着色器
             * 1.创建顶点着色器
             * 2.创建片段着色器
             * 3.合并为一个着色器提交给显卡
             * */
            private function initShader():void
            {
                /**汇编语言
                 * 操作码  目标寄存器,源寄存器,.......源寄存器
                 * 常用操作码:mov nul add sub sin cos 
                 * 特殊操作码:m33 m44 m34(矩阵乘法) tex(纹理采样)
                 * */
                        
                //1.创建顶点着色器
                var vertaxShader:AGALMiniAssembler = new AGALMiniAssembler();
                vertaxShader.assemble(
                    Context3DProgramType.VERTEX,
                    "m44 op,va0,vc0
    "+    //"m44 vt0,va0,vc0"+
                                        //"mov op,vt0
    "这两句就相当于下面一句
                                         //让第0个va着色器和第0个vc着色器进行m44运算(4*4矩阵乘法 )
                                            //va寄存器:传入顶点的位置
                                            //vc寄存器:传入一些全局变量,比如矩阵
                                            //op顶点寄存器的最终目的地
                    "mov v0,va1
    "+
                    "mov v1,va2"
                );
                //顶点着色器,每个顶点都会执行一次,也就是说,在每次执行时,va0就是当前正在处理的这个顶点的位置
                //1.创建片段着色器
                var fragmentShader:AGALMiniAssembler = new AGALMiniAssembler();
                fragmentShader.assemble(
                    Context3DProgramType.FRAGMENT,
                    "tex ft0,v1,fs0<2d,repeat>
    "+  //添加纹理
                    "mul ft1,v1,fc0
    "+
                    "tex ft2,ft1,fs1
    "+
                    "mul ft3,ft0,fc0
    "+
                    "mul oc,ft2,ft3"
                   );
                //片段着色器为每个像素都执行一次
                //合并为一个着色器提交给显卡
                shaderProgram = context3D.createProgram();
                shaderProgram.upload(vertaxShader.agalcode , fragmentShader.agalcode);
            }
            
            /**
             * 准备模型数据
             * 包含两个部分,定点数据和定点索引数据,在实际开发中,这些数据是来自于3Dmax工具到处 
             * */
            private function initData():void
            {
                //存放顶点的数据
                vertexData = new Vector.<Number>();
                vertexData.push(
                    //x   y   z     u   v    r   g   b   a 
                    /**
                     * 三角形
                     * */
    //                  1 ,1 ,0,    1 ,0,   0, 0 ,0 ,1,   //0
    //                  -1,1 ,0,    0 ,0,   0, 0 ,0 ,0,   //1
    //                  -1,-1,0,    0 ,1,   0, 0 ,0 ,0    //2
                    /**正方形*/
                      -3 , 5 , 0,    0 , 0,   1 , 0 , 0 , 1,     //0
                       5 , 3 , 0,    0 , 1,   0 , 1 , 0 , 1,     //1
                       5 ,-3 , 0,    1 , 1,   0 , 0 , 1 , 1,     //2
                      -3 ,-5 , 0,    1 , 0,   0 , 0 , 1 , 1         //3
                      /**正方体*/
    //                  -1 , 1 , -1,    1 , 0,   1 , 0 , 0 , 1,     //0
    //                  1  , 1 , -1,    0 , 0,   0 , 1 , 0 , 0,     //1
    //                  -1 ,-1 , -1,    0 , 1,   0 , 0 , 1 , 0,     //2
    //                  1  ,-1 , -1,    1 , 1,   0 , 0 , 0 , 0,     //3
    //                  1  , -1 , 1,    1 , 0,   0 , 0 , 0 , 1,     //4
    //                  1  , 1 ,  1,    0 , 0,   0 , 0 , 0 , 0,     //5
    //                  -1 , 1 ,  1,    0 , 1,   0 , 0 , 0 , 0,     //6
    //                  -1 ,-1 ,  1,    1 , 1,   0 , 0 , 0 , 0      //7
                );
                //存放索引
                vertexIndexData = new Vector.<uint>();
    //            vertexIndexData.push(0,1,2);
                vertexIndexData.push(
                    /**正方形**/
                    0 , 1 , 2,
                    0 , 2 , 3
                    /**正方体*/
    //                0 , 1 , 3,
    //                0 , 3 , 2,
    //                1 , 3 , 4,
    //                1 , 4 , 5,
    //                1 , 0 , 6,
    //                1 , 6 , 5,
    //                4 , 5 , 6,
    //                4 , 6 , 7,
    //                0 , 2 , 7,
    //                0 , 7 , 6,
    //                2 , 3 , 4,
    //                2 , 4 , 7
                );
            }
        }
    }
  • 相关阅读:
    基于NFS实现WordPress
    基于三台主机部署phpwind
    phpMyAdmin安装部署
    配置LAMP实现WordPress
    配置HTTPS服务
    部署DNS服务
    文本三剑客---awk(gawk)基础
    文本三剑客---sed 基础
    2019-2020-1 20199308《Linux内核原理与分析》第七周作业
    2019-2020-1 20199308《Linux内核原理与分析》第六周作业
  • 原文地址:https://www.cnblogs.com/xhz-blog/p/3409609.html
Copyright © 2011-2022 走看看