zoukankan      html  css  js  c++  java
  • Stage3D学习笔记(三):使用GPU绘制一个图片

    首先准备我们需要的图片,尺寸必须是2的幂数,我修改了一下Starling的图标拿来用:

    还是先看看最终效果:

    代码是居于上一节的代码进行修改的:

      1 package
      2 {
      3     import com.adobe.utils.AGALMiniAssembler;
      4     
      5     import flash.display.Bitmap;
      6     
      7     import flash.display.Sprite;
      8     import flash.display.Stage3D;
      9     import flash.display3D.Context3D;
     10     import flash.display3D.Context3DProfile;
     11     import flash.display3D.Context3DRenderMode;
     12     import flash.display3D.Context3DTextureFormat;
     13     import flash.display3D.Context3DVertexBufferFormat;
     14     import flash.display3D.IndexBuffer3D;
     15     import flash.display3D.Program3D;
     16     import flash.display3D.VertexBuffer3D;
     17     import flash.display3D.textures.Texture;
     18     import flash.events.ErrorEvent;
     19     import flash.events.Event;
     20     
     21     [SWF(width=800, height=600, frameRate=60)]
     22     public class DrawTexture extends Sprite
     23     {
     24         [Embed(source="img.png")]
     25         private var IMG_CLASS:Class;
     26         
     27         //3D 场景对象
     28         private var _stage3D:Stage3D;
     29         //3D 上下文渲染对象
     30         private var _context3D:Context3D;
     31         
     32         //顶点缓冲数据
     33         private var _vertexBuffer:VertexBuffer3D;
     34         //索引缓冲数据
     35         private var _indexBuffer:IndexBuffer3D;
     36         //纹理数据对象
     37         private var _texture:Texture;
     38         
     39         //着色器对象
     40         private var _program3D:Program3D;
     41         
     42         public function DrawTexture()
     43         {
     44             addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
     45         }
     46         
     47         private function addedToStageHandler(event:Event):void
     48         {
     49             removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
     50             
     51             //3D 场景存在, 一般存在 4 个 3D 场景对象
     52             if(stage.stage3Ds.length > 0)
     53             {
     54                 //使用最下层的 3D 场景
     55                 _stage3D = stage.stage3Ds[0];
     56                 //请求 3D 上下文渲染对象
     57                 _stage3D.addEventListener(ErrorEvent.ERROR, stage3DErrorHandler);
     58                 _stage3D.addEventListener(Event.CONTEXT3D_CREATE, context3DCreateHandler);
     59                 _stage3D.requestContext3D(Context3DRenderMode.AUTO, Context3DProfile.BASELINE);
     60             }
     61         }
     62         
     63         private function stage3DErrorHandler(event:ErrorEvent):void
     64         {
     65             trace("Context3D对象请求失败:", event.text);
     66         }
     67         
     68         private function context3DCreateHandler(event:Event):void
     69         {
     70             initContext3D();
     71             initBuffer();
     72             initTexture();
     73             initProgram();
     74             
     75             //每帧进行渲染
     76             addEventListener(Event.ENTER_FRAME, render);
     77         }
     78         
     79         private function initContext3D():void
     80         {
     81             //获取 3D 渲染对象
     82             _context3D = _stage3D.context3D;
     83             //调整 3D 舞台位置
     84             _stage3D.x = 150;
     85             _stage3D.y = 50;
     86             //设置后台缓冲区
     87             _context3D.configureBackBuffer(500, 500, 2);
     88         }
     89         
     90         private function initBuffer():void
     91         {
     92             //顶点数据
     93             var vertexData:Vector.<Number> = Vector.<Number>(
     94                     [
     95                     //  x,    y,    z, u, v
     96                         -0.5, -0.5, 0, 0, 1,
     97                         0.5,  -0.5, 0, 1, 1,
     98                         0.5,   0.5, 0, 1, 0,
     99                         -0.5,  0.5, 0, 0, 0
    100                     ]);
    101             
    102             //创建顶点缓冲对象, 参数设定存在几组数据和每组数据的个数
    103             _vertexBuffer = _context3D.createVertexBuffer(vertexData.length / 5, 5);
    104             //上传顶点数据到GPU, 参数设定从第几组数据开始上传和上传多少组数据
    105             _vertexBuffer.uploadFromVector(vertexData, 0, vertexData.length / 5);
    106             
    107             //索引数据
    108             var indexData:Vector.<uint> = Vector.<uint>(
    109                     [
    110                         0, 3, 1,
    111                         1, 2, 3
    112                     ]);
    113             
    114             //创建索引缓冲对象, 每个索引对应顶点数据中的相对应的一组数据, 
    115             //每3个索引组成一个会被绘制出来的三角形, 参数指定索引的长度
    116             _indexBuffer = _context3D.createIndexBuffer(indexData.length);
    117             //上传索引数据到GPU, 参数设定从第几个数据开始上传和上传多少个数据
    118             _indexBuffer.uploadFromVector(indexData, 0, indexData.length);
    119         }
    120         
    121         private function initTexture():void
    122         {
    123             //创建位图
    124             var bitmap:Bitmap = new IMG_CLASS() as Bitmap;
    125             //创建纹理, 注意尺寸必须是 2 的幂数
    126             _texture = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true);
    127             //上传纹理到 GPU, 第二个参数表示该纹理的 mipmap 级别, 级别零是高级全分辨率图像
    128             _texture.uploadFromBitmapData(bitmap.bitmapData, 0);
    129         }
    130         
    131         private function initProgram():void
    132         {
    133             //顶点着色器代码, 每个上传的顶点前都会执行一次该代码
    134             var vertexArr:Array =
    135                     [
    136                         //op 代表位置输出寄存器, 无论对顶点进行多少次的运算最终都要将结果
    137                         //赋值给他, 这里我们不进行运行, 直接赋值
    138                         "mov op, va0",
    139                         //片段着色器需要用的数据要在这里通过 v0 中转一下, 因为片段着色器不
    140                         //能直接读取 va0 和 va1 的数据
    141                         "mov v0, va1"
    142                     ];
    143             
    144             //片段着色器代码, 每个可以显示的像素都会执行一次该代码
    145             var fragmentArr:Array =
    146                     [
    147                         //对纹理 fs0 进行取样, 通过 v0 代表的 uv 坐标来获取对应的像素点颜
    148                         //色, 将该颜色值存储到 ft0 中
    149                         "tex ft0, v0, fs0 <2d,repeat,linear,nomip>",
    150                         //oc 代表颜色输出寄存器, 每个顶点的颜色数据都要赋值给他
    151                         "mov oc, ft0"
    152                     ];
    153             
    154             //使用 Adobe 自己提供的编译器编译代码为程序可使用的二进制数据
    155             var assembler:AGALMiniAssembler = new AGALMiniAssembler();
    156             _program3D = assembler.assemble2(_context3D, 1, vertexArr.join("
    "), fragmentArr.join("
    "));
    157             
    158             //----- 这段代码是从 render 里搬过来的, 因为不会进行改动就不放在帧循环中了 -----
    159             
    160             //指定着色器代码的 va0 代表的数据段, 表示顶点的 x, y, z 坐标
    161             _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
    162             //指定着色器代码的 va1 代表的数据段, 表示顶点的 u, v 数据
    163             _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
    164             //指定上传的纹理由 fs0 表示
    165             _context3D.setTextureAt(0, _texture);
    166             //指定当前使用的着色器对象
    167             _context3D.setProgram(_program3D);
    168         }
    169         
    170         private function render(event:Event):void
    171         {
    172             //清除已绘制过的 3D 图像
    173             _context3D.clear();
    174             //通过顶点索引数据绘制所有的三角形
    175             _context3D.drawTriangles(_indexBuffer);
    176             //将后台缓冲的图像显示到屏幕
    177             _context3D.present();
    178         }
    179     }
    180 }
  • 相关阅读:
    第11周学习进度条
    人月神话阅读笔记03
    人月神话阅读笔记02
    第10周学习进度条
    对各团队的评价意见
    第九周学习进度条
    《构建之法阅读笔记05》
    站立会议10
    第十一周学习进度
    cnblogs.com的用户体验
  • 原文地址:https://www.cnblogs.com/hammerc/p/4065596.html
Copyright © 2011-2022 走看看