首页 > 代码库 > Stage3D学习笔记(三):使用GPU绘制一个图片
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, 0100 ]);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, 3112 ]);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():void122 {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():void132 {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):void171 {172 //清除已绘制过的 3D 图像173 _context3D.clear();174 //通过顶点索引数据绘制所有的三角形175 _context3D.drawTriangles(_indexBuffer);176 //将后台缓冲的图像显示到屏幕177 _context3D.present();178 }179 }180 }
Stage3D学习笔记(三):使用GPU绘制一个图片
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。