如果将纹理的内存使用减半

ATF纹理能明显降低纹理的内存使用,但是有时候你可能不会用到它。如果你是动态生成纹理或者从第三方加载,那就不需要使用压缩的ATF纹理了。今天此文主要讲述如果在不使用ATF的情况下节省内存。


首先,确保你的应用时运行在Flash Player11.7或者AIR3.7下,可以通过Capabilities.version快速查看下。编译的时候也需要将Player11.7设为目标Flash player,可以用如下参数:-target-player=11.7.0,-swf-version=20.输入上面参数可以解锁郎中类型的纹理,这两种纹理都是每个像素是用16位来表示,而不是平常的24位或者32位。


当然需要将Context3DTextureFormat.BGR_PACKED或者Context3DTextureFormat.BGRA_PACKED传递给Context3D.createTexture,这样就可以获得16位/像素的纹理了。


Context3DTextureFormat.BGR_PACKED这种纹理的红色通道需要5位,绿色为6为,蓝色为5位。因为人眼睛对绿色的识别要好于红色跟蓝色。我们可以用RGB565来简化记忆。如果需要alpha值,那就使用Context3DTextureFormat.BGRA_PACKED,每个颜色都有一个4位的alpha值。虽然颜色不怎么精确,但是那就是支持alpha付出的代价。


建立纹理后,只需像以前那样调用Texture.uploadFromBitmapData,BitmapData就会自动样式化为16位/像素。这样在不需要透明度的图片上就减少了33%内存使用,需要透明度的减少了50%的内存使用。


试试这个。我只做了一个小的应用,此应用显示了一个512*512不透明土地纹理和一个128*128的带有一点透明的Flash标志。点击下面的按钮来改变不同的纹理类型。

  1 package
  2 {
  3 import com.adobe.utils.AGALMiniAssembler;
  4 
  5 import flash.display.Bitmap;
  6 import flash.display.BitmapData;
  7 import flash.display.Sprite;
  8 import flash.display.Stage3D;
  9 import flash.display.StageAlign;
 10 import flash.display.StageScaleMode;
 11 import flash.display3D.Context3D;
 12 import flash.display3D.Context3DBlendFactor;
 13 import flash.display3D.Context3DProgramType;
 14 import flash.display3D.Context3DRenderMode;
 15 import flash.display3D.Context3DTextureFormat;
 16 import flash.display3D.Context3DVertexBufferFormat;
 17 import flash.display3D.IndexBuffer3D;
 18 import flash.display3D.Program3D;
 19 import flash.display3D.VertexBuffer3D;
 20 import flash.display3D.textures.Texture;
 21 import flash.events.Event;
 22 import flash.events.MouseEvent;
 23 import flash.text.TextField;
 24 import flash.text.TextFieldAutoSize;
 25 import flash.text.TextFormat;
 26 import flash.utils.ByteArray;
 27 
 28 public class Texture16BPP extends Sprite
 29 {
 30 private static const PAD:Number = 5;
 31 
 32 [Embed(source="earth.jpg")]
 33 private static const TEXTURE_RGB:Class;
 34 
 35 [Embed(source="flash_logo_alpha.png")]
 36 private static const TEXTURE_RGBA:Class;
 37 
 38 private var program:Program3D;
 39 private var posUV:VertexBuffer3D;
 40 private var tris:IndexBuffer3D;
 41 private var textureRGB888:Texture;
 42 private var textureRGB565:Texture;
 43 private var textureRGBA8888:Texture;
 44 private var textureRGBA4444:Texture;
 45 private var curTexture:Texture;
 46 private var context3D:Context3D;
 47 
 48 private var modeDisplay:TextField;
 49 
 50 public function Texture16BPP()
 51 {
 52 stage.align = StageAlign.TOP_LEFT;
 53 stage.scaleMode = StageScaleMode.NO_SCALE;
 54 stage.frameRate = 60;
 55 
 56 var stage3D:Stage3D = stage.stage3Ds[0];
 57 stage3D.addEventListener(Event.CONTEXT3D_CREATE, onContextCreated);
 58 stage3D.requestContext3D(Context3DRenderMode.AUTO);
 59 }
 60 
 61 protected function onContextCreated(ev:Event): void
 62 {
 63 var stage3D:Stage3D = stage.stage3Ds[0];
 64 stage3D.removeEventListener(Event.CONTEXT3D_CREATE, onContextCreated);
 65 context3D = stage3D.context3D; 
 66 context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 0);
 67 context3D.enableErrorChecking = true;
 68 
 69 makeButtons("RGB888", "RGB565", "RGBA8888", "RGBA4444");
 70 
 71 var assembler:AGALMiniAssembler = new AGALMiniAssembler();
 72 assembler.assemble(
 73 Context3DProgramType.VERTEX,
 74 "mov op, va0\n" +
 75 "mov v0, va1"
 76 );
 77 var vertexProgram:ByteArray = assembler.agalcode;
 78 
 79 assembler.assemble(
 80 Context3DProgramType.FRAGMENT,
 81 "tex oc, v0, fs0 <2d,linear,mipnone,clamp,dxt1>"
 82 );
 83 var fragmentProgram:ByteArray = assembler.agalcode;
 84 
 85 program = context3D.createProgram();
 86 program.upload(vertexProgram, fragmentProgram);
 87 
 88 posUV = context3D.createVertexBuffer(4, 5);
 89 posUV.uploadFromVector(
 90 new <Number>[
 91 // X, Y, Z, U, V
 92 -1, -1, 0, 0, 1,
 93 -1, 1, 0, 0, 0,
 94 1, 1, 0, 1, 0,
 95 1, -1, 0, 1, 1
 96 ], 0, 4
 97 );
 98 
 99 // Create the triangles index buffer
100 tris = context3D.createIndexBuffer(6);
101 tris.uploadFromVector(
102 new <uint>[
103 0, 1, 2,
104 2, 3, 0
105 ], 0, 6
106 );
107 
108 var opaque:BitmapData = (new TEXTURE_RGB() as Bitmap).bitmapData;
109 var alpha:BitmapData = (new TEXTURE_RGBA() as Bitmap).bitmapData;
110 
111 textureRGB888 = context3D.createTexture(
112 opaque.width,
113 opaque.height,
114 Context3DTextureFormat.BGRA,
115 false
116 );
117 textureRGB888.uploadFromBitmapData(opaque);
118 
119 textureRGB565 = context3D.createTexture(
120 opaque.width,
121 opaque.height,
122 Context3DTextureFormat.BGR_PACKED,
123 false
124 );
125 textureRGB565.uploadFromBitmapData(opaque);
126 
127 textureRGBA8888 = context3D.createTexture(
128 alpha.width,
129 alpha.height,
130 Context3DTextureFormat.BGRA,
131 false
132 );
133 textureRGBA8888.uploadFromBitmapData(alpha);
134 
135 textureRGBA4444 = context3D.createTexture(
136 alpha.width,
137 alpha.height,
138 Context3DTextureFormat.BGRA_PACKED,
139 false
140 );
141 textureRGBA4444.uploadFromBitmapData(alpha);
142 
143 curTexture = textureRGB888;
144 
145 modeDisplay = new TextField();
146 modeDisplay.autoSize = TextFieldAutoSize.LEFT;
147 modeDisplay.defaultTextFormat = new TextFormat("_sans", 36);
148 modeDisplay.text = "RGB888";
149 addChild(modeDisplay);
150 
151 addEventListener(Event.ENTER_FRAME, onEnterFrame);
152 }
153 
154 private function makeButtons(...labels): Number
155 {
156 var curX:Number = PAD;
157 var curY:Number = stage.stageHeight - PAD;
158 for each (var label:String in labels)
159 {
160 var tf:TextField = new TextField();
161 tf.mouseEnabled = false;
162 tf.selectable = false;
163 tf.defaultTextFormat = new TextFormat("_sans");
164 tf.autoSize = TextFieldAutoSize.LEFT;
165 tf.text = label;
166 tf.name = "lbl";
167 
168 var button:Sprite = new Sprite();
169 button.buttonMode = true;
170 button.graphics.beginFill(0xF5F5F5);
171 button.graphics.drawRect(0, 0, tf.width+PAD, tf.height+PAD);
172 button.graphics.endFill();
173 button.graphics.lineStyle(1);
174 button.graphics.drawRect(0, 0, tf.width+PAD, tf.height+PAD);
175 button.addChild(tf);
176 button.addEventListener(MouseEvent.CLICK, onButton);
177 if (curX + button.width > stage.stageWidth - PAD)
178 {
179 curX = PAD;
180 curY -= button.height + PAD;
181 }
182 button.x = curX;
183 button.y = curY - button.height;
184 addChild(button);
185 
186 curX += button.width + PAD;
187 }
188 
189 return curY - button.height;
190 }
191 
192 private function onButton(ev:MouseEvent): void
193 {
194 var mode:String = ev.target.getChildByName("lbl").text;
195 switch (mode)
196 {
197 case "RGB888":
198 curTexture = textureRGB888;
199 modeDisplay.text = "RGB888";
200 break;
201 case "RGB565":
202 curTexture = textureRGB565;
203 modeDisplay.text = "RGB565";
204 break;
205 case "RGBA8888":
206 curTexture = textureRGBA8888;
207 modeDisplay.text = "RGBA8888";
208 break;
209 case "RGBA4444":
210 curTexture = textureRGBA4444;
211 modeDisplay.text = "RGBA4444";
212 break;
213 }
214 }
215 
216 private function onEnterFrame(ev:Event): void
217 {
218 context3D.clear(0.5, 0.5, 0.5);
219 context3D.setProgram(program);
220 context3D.setBlendFactors(
221 Context3DBlendFactor.SOURCE_ALPHA,
222 Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA
223 );
224 
225 // Draw selected texture
226 context3D.setTextureAt(0, curTexture);
227 context3D.setVertexBufferAt(0, posUV, 0, Context3DVertexBufferFormat.FLOAT_3);
228 context3D.setVertexBufferAt(1, posUV, 3, Context3DVertexBufferFormat.FLOAT_2);
229 context3D.drawTriangles(tris);
230 
231 context3D.present();
232 }
233 }
234 }

结果会根据你先则的纹理图片而又稍微的不同。土地纹理使用16位的与24位的相比没多大区别,但是内存却能节省不少。Flash 标志则看起来要糟糕点。即使是阴影模式,图片的网格还是看起来很糟糕, 这可能不是一个降低内存的好例子,但是你还是降低了50%的内存消耗。

 

原文链接:如果将纹理的内存使用减半

posted @ 2013-05-30 12:32  【Winco】  阅读(591)  评论(0编辑  收藏  举报