本章用来作为Starling的滤镜实现原理的一个补充,但是为了了解原理,我们会使用原生API进行编码。
我们知道,当我们调用drawTriangles方法时,我们的图像是绘制到后台缓冲区的,只有调用present方法时才会把图像呈现到屏幕。
我们先来看看Context3D的两个方法:
- setRenderToTexture:我们默认的渲染都是在后台缓冲区进行的,使用该方法可以把渲染修改到一个纹理上,调用该方法后,Context3D对象的渲染操作(clear、drawTriangles等)都会渲染到指定的纹理上而不是后台缓冲区。
- setRenderToBackBuffer:配合setRenderToTexture的方法,可以将使用的缓冲区还原到后台缓冲区。
如果本章看不明白可以看这篇文章进行补充:stage3D 搭建2d图形引擎 (八) 动态纹理
先想一下我们的渲染过程:提交顶点数据和纹理,设定着色器和常量,最后调用drawTriangles配合索引缓冲进行绘制。
对于绘制到后台缓冲区的模型,我们就不能再次进行操作了,如果我们想要对一个模型进行多次不同的渲染就需要使用setRenderToTexture方法了。
先看看正常渲染的情况:
1 package 2 { 3 import com.adobe.utils.AGALMiniAssembler; 4 5 import flash.display.Bitmap; 6 import flash.display.Sprite; 7 import flash.display.Stage3D; 8 import flash.display3D.Context3D; 9 import flash.display3D.Context3DProfile; 10 import flash.display3D.Context3DProgramType; 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=400, height=400, frameRate=60)] 22 public class FilterDemo extends Sprite 23 { 24 [Embed(source="img.png")] 25 private var IMG_CLASS:Class; 26 27 private var _stage3D:Stage3D; 28 private var _context3D:Context3D; 29 private var _vertexBuffer:VertexBuffer3D; 30 private var _indexBuffer:IndexBuffer3D; 31 private var _texture:Texture; 32 private var _program3D:Program3D; 33 34 //会被作为目标渲染的纹理 35 private var _filterTexture1:Texture; 36 private var _filterTexture2:Texture; 37 38 public function FilterDemo() 39 { 40 addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); 41 } 42 43 private function addedToStageHandler(event:Event):void 44 { 45 if(stage.stage3Ds.length > 0) 46 { 47 _stage3D = stage.stage3Ds[0]; 48 _stage3D.addEventListener(ErrorEvent.ERROR, stage3DErrorHandler); 49 _stage3D.addEventListener(Event.CONTEXT3D_CREATE, context3DCreateHandler); 50 _stage3D.requestContext3D(Context3DRenderMode.AUTO, Context3DProfile.BASELINE); 51 } 52 } 53 54 private function stage3DErrorHandler(event:ErrorEvent):void 55 { 56 trace("Context3D对象请求失败:", event.text); 57 } 58 59 private function context3DCreateHandler(event:Event):void 60 { 61 initContext3D(); 62 initBuffer(); 63 initTexture(); 64 normalRander(); 65 // filterRander1(); 66 // filterRander2(); 67 // finallyRander(); 68 } 69 70 private function initContext3D():void 71 { 72 _context3D = _stage3D.context3D; 73 _context3D.configureBackBuffer(400, 400, 2); 74 } 75 76 private function initBuffer():void 77 { 78 var vertexData:Vector.<Number> = Vector.<Number>( 79 [ 80 -0.5, -0.5, 0, 0, 1, 81 0.5, -0.5, 0, 1, 1, 82 0.5, 0.5, 0, 1, 0, 83 -0.5, 0.5, 0, 0, 0 84 ]); 85 86 _vertexBuffer = _context3D.createVertexBuffer(vertexData.length / 5, 5); 87 _vertexBuffer.uploadFromVector(vertexData, 0, vertexData.length / 5); 88 89 var indexData:Vector.<uint> = Vector.<uint>( 90 [ 91 0, 3, 1, 92 1, 2, 3 93 ]); 94 95 _indexBuffer = _context3D.createIndexBuffer(indexData.length); 96 _indexBuffer.uploadFromVector(indexData, 0, indexData.length); 97 } 98 99 private function initTexture():void 100 { 101 var bitmap:Bitmap = new IMG_CLASS() as Bitmap; 102 _texture = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); 103 _texture.uploadFromBitmapData(bitmap.bitmapData, 0); 104 } 105 106 /** 107 * 正常渲染. 108 */ 109 private function normalRander():void 110 { 111 var vertexArr:Array = 112 [ 113 "mov op, va0", 114 "mov v0, va1" 115 ]; 116 117 var fragmentArr:Array = 118 [ 119 "tex ft0, v0, fs0 <2d,repeat,linear,nomip>", 120 "mov oc, ft0" 121 ]; 122 123 var assembler:AGALMiniAssembler = new AGALMiniAssembler(); 124 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join(" "), fragmentArr.join(" ")); 125 126 _context3D.clear(); 127 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 128 _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); 129 _context3D.setTextureAt(0, _texture); 130 _context3D.setProgram(_program3D); 131 _context3D.drawTriangles(_indexBuffer); 132 _context3D.present(); 133 } 134 135 /** 136 * 使用灰色滤镜渲染到纹理. 137 */ 138 private function filterRander1():void 139 { 140 _filterTexture1 = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); 141 142 var vertexArr:Array = 143 [ 144 "mov op, va0", 145 "mov v0, va1" 146 ]; 147 148 var fragmentArr:Array = 149 [ 150 "tex ft0, v0, fs0 <2d,linear,clamp>", 151 "add ft1.x, ft0.x, ft0.y", 152 "add ft1.x, ft1.x, ft0.z", 153 "div ft1.x, ft1.x, fc0.w", 154 "mov ft0.xyz, ft1.xxx", 155 "mov oc ft0" 156 ]; 157 158 var assembler:AGALMiniAssembler = new AGALMiniAssembler(); 159 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join(" "), fragmentArr.join(" ")); 160 161 //设定渲染目标为我们的纹理 162 _context3D.setRenderToTexture(_filterTexture1); 163 _context3D.clear(); 164 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 165 _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); 166 //传递到灰色滤镜的设定值 167 _context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([0.299, 0.587, 0.114, 3])); 168 _context3D.setTextureAt(0, _texture); 169 _context3D.setProgram(_program3D); 170 _context3D.drawTriangles(_indexBuffer); 171 } 172 173 /** 174 * 使用波浪滤镜再一次渲染到纹理. 175 */ 176 private function filterRander2():void 177 { 178 _filterTexture2 = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); 179 180 var vertexArr:Array = 181 [ 182 "mov op, va0", 183 "mov v0, va1" 184 ]; 185 186 var fragmentArr:Array = 187 [ 188 "tex ft0,v0,fs0<2d,clamp,linear>", 189 "sub ft0.x,v0.x,fc0.w", 190 "mul ft0.x,ft0.x,ft0.x", 191 "sub ft0.y,v0.y,fc0.w", 192 "mul ft0.y,ft0.y,ft0.y", 193 "add ft0.z,ft0.x,ft0.y", 194 "sqt ft0.z,ft0.z", 195 "mul ft0.z,ft0.z,fc0.x", 196 "sub ft0.z,ft0.z,fc0.z", 197 "sin ft0.z,ft0.z", 198 "mul ft0.z,ft0.z,fc0.y", 199 "add ft0,v0,ft0.zzz", 200 "tex oc,ft0,fs0<2d,clamp,linear>" 201 ]; 202 203 var assembler:AGALMiniAssembler = new AGALMiniAssembler(); 204 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join(" "), fragmentArr.join(" ")); 205 206 //设定渲染目标为我们的纹理 207 _context3D.setRenderToTexture(_filterTexture2); 208 _context3D.clear(); 209 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 210 _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); 211 //设置波浪的常量 212 _context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, new <Number>[100, 0.01, 0, 0.5]); 213 _context3D.setTextureAt(0, _filterTexture1); 214 _context3D.setProgram(_program3D); 215 _context3D.drawTriangles(_indexBuffer); 216 217 //还原后台缓冲区为渲染目标 218 _context3D.setRenderToBackBuffer(); 219 } 220 221 /** 222 * 把最终的结果渲染到舞台. 223 */ 224 private function finallyRander():void 225 { 226 var vertexArr:Array = 227 [ 228 "mov op, va0", 229 "mov v0, va1" 230 ]; 231 232 var fragmentArr:Array = 233 [ 234 "tex ft0, v0, fs0 <2d,repeat,linear,nomip>", 235 "mov oc, ft0" 236 ]; 237 238 var assembler:AGALMiniAssembler = new AGALMiniAssembler(); 239 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join(" "), fragmentArr.join(" ")); 240 241 _context3D.clear(); 242 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 243 _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); 244 _context3D.setTextureAt(0, _filterTexture2); 245 _context3D.setProgram(_program3D); 246 _context3D.drawTriangles(_indexBuffer); 247 _context3D.present(); 248 } 249 } 250 }
下面是使用纹理渲染了2次滤镜的效果:
1 package 2 { 3 import com.adobe.utils.AGALMiniAssembler; 4 5 import flash.display.Bitmap; 6 import flash.display.Sprite; 7 import flash.display.Stage3D; 8 import flash.display3D.Context3D; 9 import flash.display3D.Context3DProfile; 10 import flash.display3D.Context3DProgramType; 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=400, height=400, frameRate=60)] 22 public class FilterDemo extends Sprite 23 { 24 [Embed(source="img.png")] 25 private var IMG_CLASS:Class; 26 27 private var _stage3D:Stage3D; 28 private var _context3D:Context3D; 29 private var _vertexBuffer:VertexBuffer3D; 30 private var _indexBuffer:IndexBuffer3D; 31 private var _texture:Texture; 32 private var _program3D:Program3D; 33 34 //会被作为目标渲染的纹理 35 private var _filterTexture1:Texture; 36 private var _filterTexture2:Texture; 37 38 public function FilterDemo() 39 { 40 addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); 41 } 42 43 private function addedToStageHandler(event:Event):void 44 { 45 if(stage.stage3Ds.length > 0) 46 { 47 _stage3D = stage.stage3Ds[0]; 48 _stage3D.addEventListener(ErrorEvent.ERROR, stage3DErrorHandler); 49 _stage3D.addEventListener(Event.CONTEXT3D_CREATE, context3DCreateHandler); 50 _stage3D.requestContext3D(Context3DRenderMode.AUTO, Context3DProfile.BASELINE); 51 } 52 } 53 54 private function stage3DErrorHandler(event:ErrorEvent):void 55 { 56 trace("Context3D对象请求失败:", event.text); 57 } 58 59 private function context3DCreateHandler(event:Event):void 60 { 61 initContext3D(); 62 initBuffer(); 63 initTexture(); 64 // normalRander(); 65 filterRander1(); 66 filterRander2(); 67 finallyRander(); 68 } 69 70 private function initContext3D():void 71 { 72 _context3D = _stage3D.context3D; 73 _context3D.configureBackBuffer(400, 400, 2); 74 } 75 76 private function initBuffer():void 77 { 78 var vertexData:Vector.<Number> = Vector.<Number>( 79 [ 80 -0.5, -0.5, 0, 0, 1, 81 0.5, -0.5, 0, 1, 1, 82 0.5, 0.5, 0, 1, 0, 83 -0.5, 0.5, 0, 0, 0 84 ]); 85 86 _vertexBuffer = _context3D.createVertexBuffer(vertexData.length / 5, 5); 87 _vertexBuffer.uploadFromVector(vertexData, 0, vertexData.length / 5); 88 89 var indexData:Vector.<uint> = Vector.<uint>( 90 [ 91 0, 3, 1, 92 1, 2, 3 93 ]); 94 95 _indexBuffer = _context3D.createIndexBuffer(indexData.length); 96 _indexBuffer.uploadFromVector(indexData, 0, indexData.length); 97 } 98 99 private function initTexture():void 100 { 101 var bitmap:Bitmap = new IMG_CLASS() as Bitmap; 102 _texture = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); 103 _texture.uploadFromBitmapData(bitmap.bitmapData, 0); 104 } 105 106 /** 107 * 正常渲染. 108 */ 109 private function normalRander():void 110 { 111 var vertexArr:Array = 112 [ 113 "mov op, va0", 114 "mov v0, va1" 115 ]; 116 117 var fragmentArr:Array = 118 [ 119 "tex ft0, v0, fs0 <2d,repeat,linear,nomip>", 120 "mov oc, ft0" 121 ]; 122 123 var assembler:AGALMiniAssembler = new AGALMiniAssembler(); 124 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join(" "), fragmentArr.join(" ")); 125 126 _context3D.clear(); 127 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 128 _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); 129 _context3D.setTextureAt(0, _texture); 130 _context3D.setProgram(_program3D); 131 _context3D.drawTriangles(_indexBuffer); 132 _context3D.present(); 133 } 134 135 /** 136 * 使用灰色滤镜渲染到纹理. 137 */ 138 private function filterRander1():void 139 { 140 _filterTexture1 = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); 141 142 var vertexArr:Array = 143 [ 144 "mov op, va0", 145 "mov v0, va1" 146 ]; 147 148 var fragmentArr:Array = 149 [ 150 "tex ft0, v0, fs0 <2d,linear,clamp>", 151 "add ft1.x, ft0.x, ft0.y", 152 "add ft1.x, ft1.x, ft0.z", 153 "div ft1.x, ft1.x, fc0.w", 154 "mov ft0.xyz, ft1.xxx", 155 "mov oc ft0" 156 ]; 157 158 var assembler:AGALMiniAssembler = new AGALMiniAssembler(); 159 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join(" "), fragmentArr.join(" ")); 160 161 //设定渲染目标为我们的纹理 162 _context3D.setRenderToTexture(_filterTexture1); 163 _context3D.clear(); 164 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 165 _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); 166 //传递到灰色滤镜的设定值 167 _context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([0.299, 0.587, 0.114, 3])); 168 _context3D.setTextureAt(0, _texture); 169 _context3D.setProgram(_program3D); 170 _context3D.drawTriangles(_indexBuffer); 171 } 172 173 /** 174 * 使用波浪滤镜再一次渲染到纹理. 175 */ 176 private function filterRander2():void 177 { 178 _filterTexture2 = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); 179 180 var vertexArr:Array = 181 [ 182 "mov op, va0", 183 "mov v0, va1" 184 ]; 185 186 var fragmentArr:Array = 187 [ 188 "tex ft0,v0,fs0<2d,clamp,linear>", 189 "sub ft0.x,v0.x,fc0.w", 190 "mul ft0.x,ft0.x,ft0.x", 191 "sub ft0.y,v0.y,fc0.w", 192 "mul ft0.y,ft0.y,ft0.y", 193 "add ft0.z,ft0.x,ft0.y", 194 "sqt ft0.z,ft0.z", 195 "mul ft0.z,ft0.z,fc0.x", 196 "sub ft0.z,ft0.z,fc0.z", 197 "sin ft0.z,ft0.z", 198 "mul ft0.z,ft0.z,fc0.y", 199 "add ft0,v0,ft0.zzz", 200 "tex oc,ft0,fs0<2d,clamp,linear>" 201 ]; 202 203 var assembler:AGALMiniAssembler = new AGALMiniAssembler(); 204 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join(" "), fragmentArr.join(" ")); 205 206 //设定渲染目标为我们的纹理 207 _context3D.setRenderToTexture(_filterTexture2); 208 _context3D.clear(); 209 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 210 _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); 211 //设置波浪的常量 212 _context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, new <Number>[100, 0.01, 0, 0.5]); 213 _context3D.setTextureAt(0, _filterTexture1); 214 _context3D.setProgram(_program3D); 215 _context3D.drawTriangles(_indexBuffer); 216 217 //还原后台缓冲区为渲染目标 218 _context3D.setRenderToBackBuffer(); 219 } 220 221 /** 222 * 把最终的结果渲染到舞台. 223 */ 224 private function finallyRander():void 225 { 226 var vertexArr:Array = 227 [ 228 "mov op, va0", 229 "mov v0, va1" 230 ]; 231 232 var fragmentArr:Array = 233 [ 234 "tex ft0, v0, fs0 <2d,repeat,linear,nomip>", 235 "mov oc, ft0" 236 ]; 237 238 var assembler:AGALMiniAssembler = new AGALMiniAssembler(); 239 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join(" "), fragmentArr.join(" ")); 240 241 _context3D.clear(); 242 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 243 _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); 244 _context3D.setTextureAt(0, _filterTexture2); 245 _context3D.setProgram(_program3D); 246 _context3D.drawTriangles(_indexBuffer); 247 _context3D.present(); 248 } 249 } 250 }
我们发现最终的效果里我们的图像变小了很多,这是为啥呢?原因就是我们每次渲染时上传的顶点坐标是:
1 var vertexData:Vector.<Number> = Vector.<Number>( 2 [ 3 -0.5, -0.5, 0, 0, 1, 4 0.5, -0.5, 0, 1, 1, 5 0.5, 0.5, 0, 1, 0, 6 -0.5, 0.5, 0, 0, 0 7 ]);
这样的结果是每次绘制图像都是占屏幕的一半,而我们经过3次渲染所以图像就变成了很小,要让图像不变的话,只有把顶点数据的0.5都改为1即可。
最终效果:
1 package 2 { 3 import com.adobe.utils.AGALMiniAssembler; 4 5 import flash.display.Bitmap; 6 import flash.display.Sprite; 7 import flash.display.Stage3D; 8 import flash.display3D.Context3D; 9 import flash.display3D.Context3DProfile; 10 import flash.display3D.Context3DProgramType; 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=400, height=400, frameRate=60)] 22 public class FilterDemo extends Sprite 23 { 24 [Embed(source="img.png")] 25 private var IMG_CLASS:Class; 26 27 private var _stage3D:Stage3D; 28 private var _context3D:Context3D; 29 private var _vertexBuffer:VertexBuffer3D; 30 private var _indexBuffer:IndexBuffer3D; 31 private var _texture:Texture; 32 private var _program3D:Program3D; 33 34 //会被作为目标渲染的纹理 35 private var _filterTexture1:Texture; 36 private var _filterTexture2:Texture; 37 38 public function FilterDemo() 39 { 40 addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); 41 } 42 43 private function addedToStageHandler(event:Event):void 44 { 45 if(stage.stage3Ds.length > 0) 46 { 47 _stage3D = stage.stage3Ds[0]; 48 _stage3D.addEventListener(ErrorEvent.ERROR, stage3DErrorHandler); 49 _stage3D.addEventListener(Event.CONTEXT3D_CREATE, context3DCreateHandler); 50 _stage3D.requestContext3D(Context3DRenderMode.AUTO, Context3DProfile.BASELINE); 51 } 52 } 53 54 private function stage3DErrorHandler(event:ErrorEvent):void 55 { 56 trace("Context3D对象请求失败:", event.text); 57 } 58 59 private function context3DCreateHandler(event:Event):void 60 { 61 initContext3D(); 62 initBuffer(); 63 initTexture(); 64 // normalRander(); 65 filterRander1(); 66 filterRander2(); 67 finallyRander(); 68 } 69 70 private function initContext3D():void 71 { 72 _context3D = _stage3D.context3D; 73 _context3D.configureBackBuffer(400, 400, 2); 74 } 75 76 private function initBuffer():void 77 { 78 var vertexData:Vector.<Number> = Vector.<Number>( 79 [ 80 -1, -1, 0, 0, 1, 81 1, -1, 0, 1, 1, 82 1, 1, 0, 1, 0, 83 -1, 1, 0, 0, 0 84 ]); 85 86 _vertexBuffer = _context3D.createVertexBuffer(vertexData.length / 5, 5); 87 _vertexBuffer.uploadFromVector(vertexData, 0, vertexData.length / 5); 88 89 var indexData:Vector.<uint> = Vector.<uint>( 90 [ 91 0, 3, 1, 92 1, 2, 3 93 ]); 94 95 _indexBuffer = _context3D.createIndexBuffer(indexData.length); 96 _indexBuffer.uploadFromVector(indexData, 0, indexData.length); 97 } 98 99 private function initTexture():void 100 { 101 var bitmap:Bitmap = new IMG_CLASS() as Bitmap; 102 _texture = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); 103 _texture.uploadFromBitmapData(bitmap.bitmapData, 0); 104 } 105 106 /** 107 * 正常渲染. 108 */ 109 private function normalRander():void 110 { 111 var vertexArr:Array = 112 [ 113 "mov op, va0", 114 "mov v0, va1" 115 ]; 116 117 var fragmentArr:Array = 118 [ 119 "tex ft0, v0, fs0 <2d,repeat,linear,nomip>", 120 "mov oc, ft0" 121 ]; 122 123 var assembler:AGALMiniAssembler = new AGALMiniAssembler(); 124 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join(" "), fragmentArr.join(" ")); 125 126 _context3D.clear(); 127 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 128 _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); 129 _context3D.setTextureAt(0, _texture); 130 _context3D.setProgram(_program3D); 131 _context3D.drawTriangles(_indexBuffer); 132 _context3D.present(); 133 } 134 135 /** 136 * 使用灰色滤镜渲染到纹理. 137 */ 138 private function filterRander1():void 139 { 140 _filterTexture1 = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); 141 142 var vertexArr:Array = 143 [ 144 "mov op, va0", 145 "mov v0, va1" 146 ]; 147 148 var fragmentArr:Array = 149 [ 150 "tex ft0, v0, fs0 <2d,linear,clamp>", 151 "add ft1.x, ft0.x, ft0.y", 152 "add ft1.x, ft1.x, ft0.z", 153 "div ft1.x, ft1.x, fc0.w", 154 "mov ft0.xyz, ft1.xxx", 155 "mov oc ft0" 156 ]; 157 158 var assembler:AGALMiniAssembler = new AGALMiniAssembler(); 159 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join(" "), fragmentArr.join(" ")); 160 161 //设定渲染目标为我们的纹理 162 _context3D.setRenderToTexture(_filterTexture1); 163 _context3D.clear(); 164 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 165 _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); 166 //传递到灰色滤镜的设定值 167 _context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([0.299, 0.587, 0.114, 3])); 168 _context3D.setTextureAt(0, _texture); 169 _context3D.setProgram(_program3D); 170 _context3D.drawTriangles(_indexBuffer); 171 } 172 173 /** 174 * 使用波浪滤镜再一次渲染到纹理. 175 */ 176 private function filterRander2():void 177 { 178 _filterTexture2 = _context3D.createTexture(128, 128, Context3DTextureFormat.BGRA, true); 179 180 var vertexArr:Array = 181 [ 182 "mov op, va0", 183 "mov v0, va1" 184 ]; 185 186 var fragmentArr:Array = 187 [ 188 "tex ft0,v0,fs0<2d,clamp,linear>", 189 "sub ft0.x,v0.x,fc0.w", 190 "mul ft0.x,ft0.x,ft0.x", 191 "sub ft0.y,v0.y,fc0.w", 192 "mul ft0.y,ft0.y,ft0.y", 193 "add ft0.z,ft0.x,ft0.y", 194 "sqt ft0.z,ft0.z", 195 "mul ft0.z,ft0.z,fc0.x", 196 "sub ft0.z,ft0.z,fc0.z", 197 "sin ft0.z,ft0.z", 198 "mul ft0.z,ft0.z,fc0.y", 199 "add ft0,v0,ft0.zzz", 200 "tex oc,ft0,fs0<2d,clamp,linear>" 201 ]; 202 203 var assembler:AGALMiniAssembler = new AGALMiniAssembler(); 204 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join(" "), fragmentArr.join(" ")); 205 206 //设定渲染目标为我们的纹理 207 _context3D.setRenderToTexture(_filterTexture2); 208 _context3D.clear(); 209 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 210 _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); 211 //设置波浪的常量 212 _context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, new <Number>[100, 0.01, 0, 0.5]); 213 _context3D.setTextureAt(0, _filterTexture1); 214 _context3D.setProgram(_program3D); 215 _context3D.drawTriangles(_indexBuffer); 216 217 //还原后台缓冲区为渲染目标 218 _context3D.setRenderToBackBuffer(); 219 } 220 221 /** 222 * 把最终的结果渲染到舞台. 223 */ 224 private function finallyRander():void 225 { 226 var vertexArr:Array = 227 [ 228 "mov op, va0", 229 "mov v0, va1" 230 ]; 231 232 var fragmentArr:Array = 233 [ 234 "tex ft0, v0, fs0 <2d,repeat,linear,nomip>", 235 "mov oc, ft0" 236 ]; 237 238 var assembler:AGALMiniAssembler = new AGALMiniAssembler(); 239 _program3D = assembler.assemble2(_context3D, 1, vertexArr.join(" "), fragmentArr.join(" ")); 240 241 _context3D.clear(); 242 _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 243 _context3D.setVertexBufferAt(1, _vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2); 244 _context3D.setTextureAt(0, _filterTexture2); 245 _context3D.setProgram(_program3D); 246 _context3D.drawTriangles(_indexBuffer); 247 _context3D.present(); 248 } 249 } 250 }