Stage3D學習筆記(三):使用GPU繪制一個圖片

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

Stage3D學習筆記(三):使用GPU繪制一個圖片

还是先看看最终效果:

Stage3D學習筆記(三):使用GPU繪制一個圖片

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

  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,
                         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("\n"), fragmentArr.join("\n"));
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 }
更多相关文章
一周排行
  • IOS04 湯姆貓開發
     汤姆猫,截图如下:  1.1以前一直觉得这个小游戏不错,很好玩,现在学习IOS才发现其实
  •          小菜一直对操作系统心存畏惧,以前也很少接触,这次创业购买了Linux云主机,由于木有人幫忙,只能自己动手优化服务器了....          小菜的云主机配置大致为:centeos6(32位),4 ...
  • http://www.lydsy.com/JudgeOnline/problem.php?id=1638 一条边(u, v)经过的数量=度0到u的数量×v到n的数量 两次记忆化dfs算出他们即可 #include & ...
  • https://vijos.org/p/1750 是不是我想复杂了.... 自己yy了个二维线段树,然后愉快的敲打. 但是wa了两法.......sad 原因是在处理第二维的更新出现了个小问题,sad. void p
  • Linux通过UID和GID来识别用户和组,使用id命令来查看用户的UID和GID以及用户所属的组. [[email protected] ~]# id root uid=0(root) gid=0(root) group
  • 下拉刷新是很多应用都使用的很流行的一种效果,今天也算是彻底的理解了一下PullToRefreshListView的使用,但是弄了一天却在一个很傻的地方犯了错误. @Override public View getVi ...
  • CISCO PIX/ASA Failover 技术 是一项故障转移配置的技术,需要两台完全一样的设备,通过一个连接,连接到对方(这个连接也叫心跳线).该技术用到的两台设备分为 主用和备用,备用处于待机状态.当主用设备 ...
  •   背景 Background 怪盗基德 VS OIBH系列  第一话 描述 Description 怪盗基德煞费苦心历尽九九八十一难终于来到了存放Paris Sunshine的OIBH总部大楼顶上.基德知道这幢大楼
  • 6.4.7 头文件名 语法 1.header-name:         <  h-char-sequence  >         "  q-char-sequence  "     ...
  • 安装配置Xtrabackup 先看看如何安装Xtrabackup,最简单的安装方式是使用RPM包,不过想使用源代码方式安装的话,其安装方式有点古怪,因为它采用的在MySQL源代码上打补丁构建的方式安装的.这里使用二进