首页 > 代码库 > Stage3D学习笔记(六):旋转动画效果
Stage3D学习笔记(六):旋转动画效果
我们这节在上一篇代码的基础上再进一步,让显示的纹理进行旋转。
实现旋转,只需要每帧修改_modelViewMatrix的旋转角度即可,我们需要一个变量来记录旋转:
1 //旋转度数2 private var _rotation:Number = 0;
每帧修改后的数据需要重新提交到GPU,而已经提交的数据不改动则不需要重新进行提交,所以我们修改一下render方法即可:
1 private function render(event:Event):void 2 { 3 //没有变动的数据就不需要进行重复的上传了 4 //每帧进行旋转 5 _rotation += 1; 6 //重置模型矩阵 7 _modelViewMatrix.identity(); 8 //移动模型到舞台中心 9 _modelViewMatrix.prependTranslation(stage.stageWidth / 2, stage.stageHeight / 2, 0);10 //应用新的旋转角度11 _modelViewMatrix.prependRotation(_rotation, Vector3D.Z_AXIS);12 //设置模型大小13 _modelViewMatrix.prependScale(128, 128, 1);14 //设置模型的注册点为中心, 注意这里使用的是百分比, 不要使用 -64 哦15 _modelViewMatrix.prependTranslation(-0.5, -0.5, 0);16 //同样需要再次上传我们的矩阵数据用于运算17 var mvpMatrix:Matrix3D = new Matrix3D();18 mvpMatrix.append(_modelViewMatrix);19 mvpMatrix.append(_projectionMatrix);20 _context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mvpMatrix, true);21 //省略22 }
对于上传后的数据的销毁,Texture、VertexBuffer3D、IndexBuffer3D和Program3D都有名为dispose的方法,我们如果向GPU上传了数据,调用该方法会清除上传到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.Context3DProgramType; 12 import flash.display3D.Context3DRenderMode; 13 import flash.display3D.Context3DTextureFormat; 14 import flash.display3D.Context3DVertexBufferFormat; 15 import flash.display3D.IndexBuffer3D; 16 import flash.display3D.Program3D; 17 import flash.display3D.VertexBuffer3D; 18 import flash.display3D.textures.Texture; 19 import flash.events.ErrorEvent; 20 import flash.events.Event; 21 import flash.geom.Matrix3D; 22 import flash.geom.Vector3D; 23 24 [SWF(width=550, height=400, frameRate=60)] 25 public class Matrix3DTest extends Sprite 26 { 27 [Embed(source="img.png")] 28 private var IMG_CLASS:Class; 29 30 //3D 场景对象 31 private var _stage3D:Stage3D; 32 //3D 上下文渲染对象 33 private var _context3D:Context3D; 34 35 //顶点缓冲数据 36 private var _vertexBuffer:VertexBuffer3D; 37 //索引缓冲数据 38 private var _indexBuffer:IndexBuffer3D; 39 //纹理数据对象 40 private var _texture:Texture; 41 42 //着色器对象 43 private var _program3D:Program3D; 44 45 //正交矩阵 46 private var _projectionMatrix:Matrix3D; 47 //模型矩阵, 通过操作该矩阵来变换纹理的显示 48 private var _modelViewMatrix:Matrix3D; 49 50 //旋转度数 51 private var _rotation:Number = 0; 52 53 public function Matrix3DTest() 54 { 55 addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); 56 } 57 58 private function addedToStageHandler(event:Event):void 59 { 60 removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); 61 62 //3D 场景存在, 一般存在 4 个 3D 场景对象 63 if(stage.stage3Ds.length > 0) 64 { 65 //使用最下层的 3D 场景 66 _stage3D = stage.stage3Ds[0]; 67 //请求 3D 上下文渲染对象 68 _stage3D.addEventListener(ErrorEvent.ERROR, stage3DErrorHandler); 69 _stage3D.addEventListener(Event.CONTEXT3D_CREATE, context3DCreateHandler); 70 _stage3D.requestContext3D(Context3DRenderMode.AUTO, Context3DProfile.BASELINE); 71 } 72 } 73 74 private function stage3DErrorHandler(event:ErrorEvent):void 75 { 76 trace("Context3D对象请求失败:", event.text); 77 } 78 79 private function context3DCreateHandler(event:Event):void 80 { 81 initContext3D(); 82 initOrthographicProjection(stage.stageWidth, stage.stageHeight); 83 initBuffer(); 84 initTexture(); 85 transformMatrix(); 86 initProgram(); 87 88 //每帧进行渲染 89 addEventListener(Event.ENTER_FRAME, render); 90 } 91 92 private function initContext3D():void 93 { 94 //获取 3D 渲染对象 95 _context3D = _stage3D.context3D; 96 //设置后台缓冲区 97 _context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 2); 98 } 99 100 private function initOrthographicProjection(width:Number, height:Number, near:Number = -1.0, far:Number = 1.0):void101 {102 //创建正交矩阵的实例103 _projectionMatrix = new Matrix3D();104 //设置正交矩阵数据, 这个公式记死即可105 var coords:Vector.<Number> = new <Number>106 [107 2.0 / width, 0.0, 0.0, 0.0,108 0.0, -2.0 / height, 0.0, 0.0,109 0.0, 0.0, -2.0 / (far - near), 0.0,110 -1.0, 1.0, -(far + near) / (far - near), 1.0111 ];112 _projectionMatrix.copyRawDataFrom(coords);113 }114 115 private function initBuffer():void116 {117 //顶点数据, 因为只需要显示一张图片所以这里的顶点数据是可以写死的, 同时可以去掉 z 轴118 //的数据, 因为不需要使用到 z 轴, 我们按照下面的规则来排列顶点:119 //0 - 1120 //| / |121 //2 - 3122 //有趣的是 uv 的数据和顶点数据其实是一致的, 所以 uv 的数据也可以去除, 不过我们这里123 //先留着, Starling 框架中 uv 数据是已经去掉的124 var vertexData:Vector.<Number> = Vector.<Number>(125 [126 // x, y, u, v127 0, 0, 0, 0,128 1, 0, 1, 0,129 0, 1, 0, 1,130 1, 1, 1, 1131 ]);132 133 //创建顶点缓冲对象, 参数设定存在几组数据和每组数据的个数134 _vertexBuffer = _context3D.createVertexBuffer(vertexData.length / 4, 4);135 //上传顶点数据到GPU, 参数设定从第几组数据开始上传和上传多少组数据136 _vertexBuffer.uploadFromVector(vertexData, 0, vertexData.length / 4);137 138 //索引数据139 var indexData:Vector.<uint> = Vector.<uint>(140 [141 0, 1, 2,142 1, 2, 3143 ]);144 145 //创建索引缓冲对象, 每个索引对应顶点数据中的相对应的一组数据, 146 //每3个索引组成一个会被绘制出来的三角形, 参数指定索引的长度147 _indexBuffer = _context3D.createIndexBuffer(indexData.length);148 //上传索引数据到GPU, 参数设定从第几个数据开始上传和上传多少个数据149 _indexBuffer.uploadFromVector(indexData, 0, indexData.length);150 }151 152 private function initTexture():void153 {154 //创建位图155 var bitmap:Bitmap = new IMG_CLASS() as Bitmap;156 //创建纹理, 注意尺寸必须是 2 的幂数157 _texture = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true);158 //上传纹理到 GPU, 第二个参数表示该纹理的 mipmap 级别, 级别零是高级全分辨率图像159 _texture.uploadFromBitmapData(bitmap.bitmapData, 0);160 }161 162 private function transformMatrix():void163 {164 //设置纹理的转换矩阵165 _modelViewMatrix = new Matrix3D();166 //设置矩阵的位置167 _modelViewMatrix.prependTranslation(0, 0, 0);168 //设置矩阵的旋转169 _modelViewMatrix.prependRotation(0, Vector3D.Z_AXIS);170 //设置矩阵的尺寸171 _modelViewMatrix.prependScale(128, 128, 1);172 //设置纹理的中心点173 _modelViewMatrix.prependTranslation(0, 0, 0);174 175 //将纹理的转换矩阵和正交矩阵结合就得到了最终需要的上传到 GPU 进行运算的矩阵数据176 var mvpMatrix:Matrix3D = new Matrix3D();177 mvpMatrix.append(_modelViewMatrix);178 mvpMatrix.append(_projectionMatrix);179 //将我们的最终矩阵作为常量传递到 GPU 中, 指定其是名称为 vc0 的那个寄存器180 _context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mvpMatrix, true);181 }182 183 private function initProgram():void184 {185 //顶点着色器代码, 每个上传的顶点前都会执行一次该代码186 var vertexArr:Array =187 [188 //op 代表位置输出寄存器, 无论对顶点进行多少次的运算最终都要将结果189 //赋值给他, 这里和我们的正交矩阵进行相乘的运算190 "m44 op, va0, vc0",191 //片段着色器需要用的数据要在这里通过 v0 中转一下, 因为片段着色器不192 //能直接读取 va0 和 va1 的数据193 "mov v0, va1"194 ];195 196 //片段着色器代码, 每个可以显示的像素都会执行一次该代码197 var fragmentArr:Array =198 [199 //对纹理 fs0 进行取样, 通过 v0 代表的 uv 坐标来获取对应的像素点颜200 //色, 将该颜色值存储到 ft0 中201 "tex ft0, v0, fs0 <2d,repeat,linear,nomip>",202 //oc 代表颜色输出寄存器, 每个顶点的颜色数据都要赋值给他203 "mov oc, ft0"204 ];205 206 //使用 Adobe 自己提供的编译器编译代码为程序可使用的二进制数据207 var assembler:AGALMiniAssembler = new AGALMiniAssembler();208 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join("\n"), fragmentArr.join("\n"));209 210 //----- 这段代码是从 render 里搬过来的, 因为不会进行改动就不放在帧循环中了 -----211 212 //指定着色器代码的 va0 代表的数据段, 表示顶点的 x, y 坐标213 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);214 //指定着色器代码的 va1 代表的数据段, 表示顶点的 u, v 数据215 _context3D.setVertexBufferAt(1, _vertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2);216 //指定上传的纹理由 fs0 表示217 _context3D.setTextureAt(0, _texture);218 //指定当前使用的着色器对象219 _context3D.setProgram(_program3D);220 }221 222 private function render(event:Event):void223 {224 //没有变动的数据就不需要进行重复的上传了225 //每帧进行旋转226 _rotation += 1;227 //重置模型矩阵228 _modelViewMatrix.identity();229 //移动模型到舞台中心230 _modelViewMatrix.prependTranslation(stage.stageWidth / 2, stage.stageHeight / 2, 0);231 //应用新的旋转角度232 _modelViewMatrix.prependRotation(_rotation, Vector3D.Z_AXIS);233 //设置模型大小234 _modelViewMatrix.prependScale(128, 128, 1);235 //设置模型的注册点为中心, 注意这里使用的是百分比, 不要使用 -64 哦236 _modelViewMatrix.prependTranslation(-0.5, -0.5, 0);237 //同样需要再次上传我们的矩阵数据用于运算238 var mvpMatrix:Matrix3D = new Matrix3D();239 mvpMatrix.append(_modelViewMatrix);240 mvpMatrix.append(_projectionMatrix);241 _context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mvpMatrix, true);242 243 //清除已绘制过的 3D 图像244 _context3D.clear();245 //通过顶点索引数据绘制所有的三角形246 _context3D.drawTriangles(_indexBuffer);247 //将后台缓冲的图像显示到屏幕248 _context3D.present();249 }250 }251 }
Stage3D学习笔记(六):旋转动画效果
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。