• Flash Stage3D Molehill 学习笔记(2)


      前面已经学习了“常见的3D显像术语”与“常见的3D编码术语”。今天所要探讨的是Molehill。

    什么是Molehill:

      Molehill是Adobe官方预计推出的一套底层3D渲染引擎,该引擎能够调用GPU,借助GPU强大的浮点运算能力实现开创新的Flash3D技术。

      2010年10月,Adobe在MAX大会中公布了关于Flash Player的新项目,名为Molehill的新API集可以让开发者借助GPU大幅提升Flash的3D渲染能力。
    目前现有的Flash Player 10.1可以在30Hz下渲染几千个非Z缓冲三角形,使用Molehill和图形芯片则可以在60Hz左右的高分辨率显示器中全屏渲染近百万的Z缓冲三角形。这些新的3D API还将同时支持Flash Player和Adobe AIR,为用户提供全新的3D体验。
      Adboe介绍称,Molehill是新推出的支持GPU硬件加速底层API的总称,支持Z缓冲、模版色缓冲、碎片和顶点着色、立方体纹理等特性。借助这些3D API,开发者可以在任何情况下调用GPU,如果出现GPU不兼容的情况则会调用CPU作为图形渲染处理器。
    Flash Player10中现有的3D API将可以继续使用,Molehill主要面向高级开发人员用来构建复杂的3D模型,开发者可以按照实际需要选择使用这两种API。Adobe表示他们将会为不同的平台提供这些新的开发工具,在Windows系统中将会依赖于DirectX 9,在Mac和Linux下则依赖于OpenGL 1.3,未来还将会借助OpenGL ES 2.0支持Android和Linux Mobile等移动平台。
     
    Molehill的结构:
      对Flash而言,舞台就是画到屏幕上的东西,而各式各样的可视元素(位图、矢量图、文本、UI组件)被附加到了舞台上。同样,基于Molehill的Flash动画也被附加到了一个名为Stage3D的特殊对象上。你的舞台可以拥有一个以上的Stage3D,而每个Stage3D都有一个Context3D对象。Context3D就是引擎,它就是Molehill对象。
     
    Stage      
      这是常规的Flash舞台,任何将会显示在屏幕上的东西都要放在这里。
    Stage3D   
      是出于Flash和GUP之间的对象,不像诸如Sprite这样的常规Flash2D显示对象,Stage3D是不会出现在显示列表中的。这就意味着你不能在Stage3D对象上进行addChild()方法。Stage3D对象位于所以常规Flash内容的后面,它总是位于舞台的最底层。
    Context3D  
      stage3D对象包含了一个Context3D,就像Bitmap 对象包含 BitmapData一样。当你处理Bitmap的时候。花的大部分时间其实是在处理BitmapData.同理,在Molehill中你也很少会直接用到Stage3D.取而代之的,你将使用Context3D进行工作。你可以把Context3D当做“3D引擎”,它是所有3D数据的对象。当你想把顶点数据作为顶点数据上传到显卡时候,你会把一个数字数组送入Context3D.
    VertexBuffer3D
      3D顶点缓冲。3D世界中的模型由成千上万个顶点组成的。每个顶点定义了一个网格“定角”的X,Y,Z坐标。而VertexBuffer3D就是一个用于这些坐标的数组。在初始化3D世界的时候。我们需要将VertexBuffer3D对象交给Context3D,以此来把这庞大的数据数组送给Molehill.接下来Context3D会把这些数据直接上传到你的显存中,以备渲染时使用。
    IndexBuffer3D
      3D索引缓冲 FLash终归还是需要知道每一块是从什么地方开始又到什么地方结束的,而索引缓冲就是用来告诉Flash哪部分数据是属于哪个顶点的。
    Program3D
      3D着色器 顶点着色器和片段着色器被上传到显卡,这样一来它们就能在GPU中运行了。着色器使用一种类似于汇编语言的特殊语言进行编译,它们将告诉GPU如何去绘制上传好的网格模型。
     
      在初始化期间,所有的缓冲和编译好的着色器都将送人显卡,这个过程只有一次,一旦完成,Flash就可以反复的绘制这些模型到新的位置上了。
     
    说了这么多理论我们开始动手来写一个简单的demo 来帮助消化下这些知识:
     
     

    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.display.StageAlign;
     import flash.display.StageScaleMode;
     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;
     
     [SWF(width=1024,height=590)]
     public class lesson1 extends Sprite
     {
      [Embed(source = "assset/bricks_a_spec.jpg")]
      private var myTextureBitmap:Class;
      
      /**
       * 舞台的宽度
       */  
      public const stageW:int = 1024;
      /**
       * 舞台的高度
       */  
      public const stageH:int = 590;
      /**
       * 纹理大小
       */  
      public const textureSize:int = 512;
      /**
       * 3D图形窗口
       */  
      private var context3D:Context3D;
      /**
       *定义着色器
       */  
      private var shaderProgram:Program3D;
      /**
       * 定义一个顶点缓冲
       */  
      private var vertexBuffer:VertexBuffer3D;
      /**
       * 定义一个索引缓冲
       */  
      private var indexBuffer:IndexBuffer3D;
      /**
       * 定义网格的顶点数据
       */  
      private var meshVertexData:Vector.<Number>;
      /**
       * 定义网格的索引数据
       */  
      private var meshIndexData:Vector.<uint>;
      
      /**
       * 影响模型位置和相机的角度的矩阵
       */  
      private var projectionMatrix3D:PerspectiveMatrix3D = new PerspectiveMatrix3D();
      /**
       * 定义一个模型的矩阵
       */  
      private var modelMatrix:Matrix3D = new Matrix3D;
      
      /**
       * 定义一个视图的矩阵
       */  
      private var viewMatrix:Matrix3D = new Matrix3D;
      
      /**
       * 定义一个投影
       */  
      private var modelViewProjection:Matrix3D = new Matrix3D;
      /**
       * 用于动画的帧计数器
       */  
      private var t:Number = 0;
      /**
       * 创建纹理
       */  
      private var myTextureData:Bitmap = new myTextureBitmap();
        
      private var myTexture:Texture;
      
      public function lesson1()
      {
       this.stage ? addEventListener(Event.ADDED_TO_STAGE,init) : init();
      }
      
      private function init(event:Event = null):void
      {
       hasEventListener(Event.ADDED_TO_STAGE) && removeEventListener(Event.ADDED_TO_STAGE,init);
       stage.scaleMode = StageScaleMode.NO_SCALE;
       stage.align = StageAlign.TOP_LEFT;
       stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE,onContext3DCreate);
       stage.stage3Ds[0].requestContext3D();
      }
      
      private function onContext3DCreate(event:Event):void
      {
       removeEventListener(Event.CONTEXT3D_CREATE,onContext3DCreate);
       var stage3D:Stage3D = event.target as Stage3D;
       context3D = stage3D.context3D;
       if(!context3D)
       {
        return;
       }
       context3D.enableErrorChecking = true;
       initData();
      }
      
      private function initData():void
      {
       //定义一个正方形的顶点信息
       meshVertexData = Vector.<Number>([
        -1, -1, 1, 0, 0, 0, 0, 1,
        1, -1, 1, 1, 0, 0, 0, 1,
        1, 1, 1, 1, 1, 0, 0, 1,
        -1, 1, 1, 0, 1, 0, 0, 1
       ]);
       // 定义一个正方形的索引
       meshIndexData = Vector.<uint>
       ([
        0,1,2, 0,2,3
       ]);
       
       // 3D缓冲区的像素尺寸
       context3D.configureBackBuffer(stageW,stageH,0,true);
       //创建一个顶点着色器
       var vertexShader:AGALMiniAssembler = new AGALMiniAssembler();
       vertexShader.assemble
       (
        Context3DProgramType.VERTEX,
        // 创建一个4X4矩阵乘以相机角度
        "m44 op, va0, vc\n"+
        //告诉片段着色器X,Y,Z的值
        "mov v0, va0\n"+
        //告诉片段着色器u,v的值
        "mov v1, va1\n"
       );
       // 创建一个片段着色器
       var pixelShader:AGALMiniAssembler = new AGALMiniAssembler();
       pixelShader.assemble
       (
        Context3DProgramType.FRAGMENT,
        "tex ft0, v1, fs0 <2d,repeat,miplinear>\n"+
        // 结果输出
        "mov oc, ft0\n"
       );
       
       shaderProgram = context3D.createProgram();
       //上传网格索引
       shaderProgram.upload(vertexShader.agalcode,pixelShader.agalcode);
       indexBuffer = context3D.createIndexBuffer(meshIndexData.length);
       indexBuffer.uploadFromVector(meshIndexData,0,meshIndexData.length);
       // 上传网格顶点数据
       // 因为包含X,Y,Z,U,V,nX,nY,nZ 所以每个顶点各占8个数组元素
       vertexBuffer = context3D.createVertexBuffer(meshVertexData.length/8,8);
       vertexBuffer.uploadFromVector(meshVertexData,0,meshVertexData.length / 8);
       //产生MIP映射
       myTexture = context3D.createTexture(textureSize,textureSize,Context3DTextureFormat.BGRA,false);
       var ws:int = myTextureData.bitmapData.width;
       var hs:int = myTextureData.bitmapData.height;
       var level:int = 0;
       var transform:Matrix = new Matrix();
       var tmp:BitmapData = new BitmapData(ws,hs,true,0x00000000);
       while(ws >=1 && hs >=1)
       {
        tmp.draw(myTextureData.bitmapData,transform,null,null,null,true);
        myTexture.uploadFromBitmapData(tmp,level);
        transform.scale(0.5,0.5);
        level++;
        ws >>=1;
        hs >>=1;
        if(hs && ws)
        {
         tmp.dispose();
         tmp = new BitmapData(ws,hs,true,0x00000000);
        }
       }
       tmp.dispose();
       // 创建透视矩阵
       projectionMatrix3D.identity();
       // 设置45度视角,1024 / 590 长宽比,0,1的近裁剪面,100的远裁剪面
       projectionMatrix3D.perspectiveFieldOfViewRH(45,stageW / stageH,0.01,100);
       // 创建一个定义相机位置的矩阵
       viewMatrix.identity();
       // 为了看到Mesh,把相机往后移;
       viewMatrix.appendTranslation(0,0,-4);
       
       // 准备就绪 开始渲染
       addEventListener(Event.ENTER_FRAME,onRendering);
      }
      
      protected function onRendering(event:Event):void
      {
       context3D.clear(0,0,0);
       context3D.setProgram(shaderProgram);
       // 创建变换矩阵
       modelMatrix.identity();
       modelMatrix.appendRotation(t*0.6,Vector3D.X_AXIS);
       modelMatrix.appendRotation(t*0.7,Vector3D.Y_AXIS);
       modelMatrix.appendRotation(t*0.8,Vector3D.Z_AXIS);
       modelMatrix.appendTranslation(0,0,0);

       t+=2.0;
       
       //重置矩阵
       modelViewProjection.identity();
       modelViewProjection.append(modelMatrix);
       modelViewProjection.append(viewMatrix);
       modelViewProjection.append(projectionMatrix3D);
       
       //把矩阵传给着色器
       context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,modelViewProjection,true);
       // 着色器处理顶点数据
       context3D.setVertexBufferAt(0,vertexBuffer,0,Context3DVertexBufferFormat.FLOAT_3);
       // 着色器处理纹理
       context3D.setVertexBufferAt(1,vertexBuffer,3,Context3DVertexBufferFormat.FLOAT_3);
       context3D.setTextureAt(0,myTexture);
       context3D.drawTriangles(indexBuffer,0,meshIndexData.length / 3);
       context3D.present();
      }
     }
    }

  • 相关阅读:
    10月20日动手动脑
    10月20日
    10月19日
    10月18日
    10月17日
    10月16日
    10月15日
    10月14日
    jQuery选择器大全
    面试总结
  • 原文地址:https://www.cnblogs.com/ch06src/p/3132394.html
Copyright © 2020-2023  润新知