iOS和android游戲紋理優化和內存優化(cocos2d-x)
(未完成)
1、2d游戲最占內存的無疑是圖片資源。
2、cocos2d-x不同平臺讀取紋理的機制不同。ios下面使用CGImage,android和windows下是直接調用png庫。我測試了下,使用png庫直接讀取png會比CGImage還要節約1mb左右內存(圖片所占內存4mb)但是速度要比CGImage慢一倍。時間和空間如何取舍就看實際情況了。不過最佳的選擇似乎是pvr(即使android版本,即使不使用pvrtc4)。
3、一般來說,我們可以直接使用 w * h * bpp得到一張紋理所占的內存,比如一張1024*1024格式為argb8888,那么他所占的內存就是1024*1024*4=4mb。之前看到有博客提到jpg會開辟3倍與此的內存(先轉換為png,然后解析png),但是新的ios系統似乎沒有這個問題。jpg與png所消耗的內存幾乎相同,并且jpg解析速度更快(幾乎都是4mb解析+4mb紋理數據,而jpg解析時間是png的一半),但是這樣反而很怪異,因為jpg是沒有透明色的,一個像素最多3字節,而png一個像素4字節,jpg紋理應該占用內存更小才對,后來看了下cocos2d的ios加載圖片的代碼,它把所有紋理轉換成rgba8888格式,所以無論是jpg還是png,占用的都是4字節。正因cocos2d對其他紋理支持不夠好,pvr才會顯得那么高效。
4、pvr格式可以被顯卡所認可,而不需要開辟臨時內存來讀取,所以即便同為argb8888格式的圖片,pvr也會比png有效率,雖然不會節約程序穩定運行時的內存,但是會避免加載大量圖片時的內存暴漲。 并且如果是ios設備的話,可以使用pvrtc4格式的圖片,這個格式相當于windows下的dds圖片,是可以被顯卡直接支持的。它是有損壓縮,一個像素只占4位,不過如果不是有漸變半透明色的話,一般效果可以接受,而其節約的內存和cpu時間非常非常顯著。
5、pvr也不是萬金油。android設備下雖然可以使用pvr格式,但是不能使用pvrtc4,希望通過pvr像ios設備上一樣真正減少游戲內存是不太可行的。
6、pvr.ccz其實就是pvr圖片zip打包下,程序讀的時候還是先解壓出pvr資源,然后再讀取pvr。不過由于壓縮下可以極大的減小圖片體積,所以雖然多了解壓過程也不會有特別多的cpu消耗。
7、一張jpg圖片實際加載過程內存消耗,以一張1024*1024 argb8888 500k的jpg圖片為例: a.讀取圖片文件(消耗圖片大小內存,500k) b、解析jpg數據(cgimage, 4mb) c、釋放500k的圖片內存 d、opengl紋理數據(4mb) e、釋放cgimage的4mb內存。 注意,這個過程不是必然的順序執行,釋放cgimage內存的實際是有系統決定的,會很快,但是不一定是立即執行。 所以內存會瞬間飆升9mb左右,然后減少5mb,穩定到4mb左右
png圖片的加載過程與此相同
pvr圖片可以節約解析圖片數據到紋理這一步的消耗。也就是說讀取pvr圖片資源(等價于解壓pvr.ccz到內存,如果是1024*1024 argb8888格式的話,那么圖片大小就是4mb,ccz壓縮后圖片1mb左右)消耗4mb,將pvr圖片數據提交給顯卡消耗4mb。然后釋放文件數據4mb。這么看似乎跟Png從內存占用上相比也不是非常有優勢。(注意這里說的pvr是指pvr封裝的argb8888,與pvrtc4的性能有天壤之別)
8、由于最終消耗內存的都是紋理數據,所以只要紋理數據格式是一定的,無論圖片是什么格式消耗的內存都是一樣的。比如使用Png8圖片,體積會減少70%,但是內存占用與png24/png32是等價的(讀取的時候會內部把調色板還原成真彩色,也就是說,雖然png8是一個像素只占8位,但是讀取到內存中的時候會將調色板顏色還原,依然需要開辟1024*1024*4字節的空間存放紋理數據)。 當然有無透明色,cocos2d的處理還是有區別的。如果是無透明色,可以使用png24,那么所需開辟的紋理空間就是3mb。
這里還有一點需要說明,一般我們處理windows下的dds紋理的時候,都習慣將其按2的整次冪對其,雖然圖片內容只有900*900,但是圖片大小卻是1024*1024。那我們讀取這個圖片所消耗的內存就是4mb,按2的整次冪對其是有助于提高運行效率的,但是不是非常必須的。ios和android的設備都支持非2的整次冪的紋理。所以如果是png圖片,那么它該多大就多大。此時消耗的內存就只有900*900*4=3mb。
9、不要過于迷信所謂的去除alpha通道以節約內存。這個還要實際分析下具體結果。 我測試過(分別用cocos2d-x和鬼火3d引擎),rgba8888和rgb888格式的png圖片顯示所消耗的內存是一樣的。24位圖片雖然讀取的時候開辟的內存只有3mb(1024*1024*3,注意如果是用CGImage讀取的話,那這個值就是4mb),但是glTexImage2D提交給顯卡后依然會增加4mb內存。可能跟顯卡的數據對齊有關。
這里我測試還有一個詭異的地方,如果是用pvr的npot圖片的話,rgb888要比rgba8888所消耗的內存要小,但是pot圖片兩者又是一樣的(png圖片兩種情況都是一樣的)。可能是powervr顯卡有特殊處理。
10、rgb565和rgb5551的圖片所消耗的內存是rgba8888的一半,如果沒有透明漸變的話,視覺上也看不出什么區別。一些大的背景圖可以優先選擇這種格式。
11、pvr圖片加載速度要比png和jpg快3~5倍(同樣1024*1024 argb8888),png消耗的時間可能是700ms左右,但是pvr只需要100ms左右。如果是pvr.ccz壓縮下,消耗的時間是200ms左右。可見pvr在加載速度上還是有非常大的優勢的。這個應該是因為png和jpg需要把圖片數據還原為rgba,但是pvr可以直接把圖片數據傳遞給顯卡。pvrtc4的圖片是可以被powervr顯卡直接支持的。
總結下:
1、最終決定圖片占用內存的是它的像素格式和大小,與其擴展名無關。png8 png32 jpg pvr只要其像素格式都是argb8888,那么最終圖片占用的內存是一樣的。
2、如果不是pvrtc4的格式,那么不要擴展成2的整次冪,因為圖片越小,占用內存越小
3、單單去除透明通道不會減少圖片所消耗的內存,png和jpg圖片也無法減少圖片體積,所以不推薦rgb888的格式。替代選擇rgb565和rgb5551。
5、小心加載圖片時臨時開辟的紋理數據造成的內存飆高,可以考慮加入內存池,及時的開辟和釋放緩沖區。
6、如果是為了減少圖片體積可以選擇:1、jpg--壓縮比最高,質量較好,但是不支持半透明 2、png8--同樣圖片會比jpg略大一些,使用ImageAlpha進行轉換,視覺上幾乎看不出差別。 這兩種圖片格式都可以極大的減少圖片體積(減少70%~80%),但是無助于減少內存
7、如果是為了減少內存可以選擇:1、沒有透明色的圖片統一轉換為rgb565格式,這個時候無法使用png8了,所以png和pvr.ccz圖片大小幾乎相同,pvr.ccz速度更快,所以推薦pvr.ccz的rgb565格式 2、如果透明色僅僅是進行關鍵色標注,而沒有漸變混合,那么推薦rgb5551 (r5_a1)的pvr.ccz格式
8、可以考慮寫個打包系統,統一把資源文件打包,而不是單個文件用pvr.ccz進行zip壓縮,這樣可以獲得更高的效率。(比如我封裝了下暴雪的mpq打包,其讀取速度與本地文件讀取速度相當,這樣就可以獲得最佳的讀取效率)
最后附上我測試的數據日志,圖片是一張1024*1024的圖片,實際圖片內容大小為960*700。測試設備iphone4,png jpg等圖片加載代碼修改為windows版本。tex后面是圖片的加載時間。 over后面的括號里面是圖片加載所消耗的內存。
2012-12-27 14:28:54.614 HelloCpp[4939:707] cocos2d: surface size: 960x640 Cocos2d: cocos2d: cocos2d-2.1beta3-x-2.1.0 Cocos2d: cocos2d: GL_VENDOR: Imagination Technologies Cocos2d: cocos2d: GL_RENDERER: PowerVR SGX 535 Cocos2d: cocos2d: GL_VERSION: OpenGL ES 2.0 IMGSGX535-63.24 Cocos2d: cocos2d: GL_MAX_TEXTURE_SIZE: 2048 Cocos2d: cocos2d: GL_MAX_TEXTURE_UNITS: 8 Cocos2d: cocos2d: GL supports PVRTC: YES Cocos2d: cocos2d: GL supports BGRA8888 textures: NO Cocos2d: cocos2d: GL supports NPOT textures: YES Cocos2d: cocos2d: GL supports discard_framebuffer: YES Cocos2d: cocos2d: GL supports shareable VAO: YES Cocos2d: cocos2d: compiled with Profiling Support: NO tex 195 map_001_BG.pvr map_001_BG.pvr ---over proess:11.0mb (4.0mb) free:274.6mb tex 159 map_001_BG_rgb.pvr map_001_BG_rgb.pvr ---over proess:15.0mb (4.0mb) free:270.6mb tex 711 map_001_BG.jpg map_001_BG.jpg ---over proess:19.1mb (4.1mb) free:266.7mb tex 653 map_001_BG_rgb.jpg map_001_BG_rgb.jpg ---over proess:23.1mb (4.0mb) free:262.6mb tex 670 map_001_BG.png map_001_BG.png ---over proess:27.1mb (4.1mb) free:258.7mb tex 739 map_001_BG_rgb.png map_001_BG_rgb.png ---over proess:31.1mb (4.0mb) free:254.3mb tex 240 map_001_BG.pvr.ccz map_001_BG.pvr.ccz ---over proess:35.1mb (4.0mb) free:250.4mb tex 204 map_001_BG_rgb.pvr.ccz map_001_BG_rgb.pvr.ccz ---over proess:39.2mb (4.0mb) free:246.5mb tex 97 map_001_BG_rgb565.pvr map_001_BG_rgb565.pvr ---over proess:41.2mb (2.0mb) free:244.6mb tex 710 map_001_BG_rgb565.png map_001_BG_rgb565.png ---over proess:45.2mb (4.0mb) free:241.1mb tex 591 map_001_BG_rgba8888f.png map_001_BG_rgba8888f.png ---over proess:47.8mb (2.6mb) free:238.3mb tex 484 map_001_BG_rgba8888f.jpg map_001_BG_rgba8888f.jpg ---over proess:49.7mb (1.9mb) free:236.5mb tex 123 map_001_BG_rgba8888f.pvr map_001_BG_rgba8888f.pvr ---over proess:52.4mb (2.7mb) free:234.1mb tex 589 map_001_BG_rgb888f.png map_001_BG_rgb888f.png ---over proess:55.1mb (2.7mb) free:231.2mb tex 478 map_001_BG_rgb888f.jpg map_001_BG_rgb888f.jpg ---over proess:57.0mb (1.9mb) free:229.4mb tex 92 map_001_BG_rgb888f.pvr map_001_BG_rgb888f.pvr ---over proess:59.0mb (2.0mb) free:227.8mb (lldb)
第二個日志是ios版本的圖片加載,其他與上一個相同,可以看到速度要比windows版本的png加載快一倍,但是內存消耗更高
2012-12-27 15:36:10.330 HelloCpp[4979:707] cocos2d: surface size: 960x640 Cocos2d: cocos2d: cocos2d-2.1beta3-x-2.1.0 Cocos2d: cocos2d: GL_VENDOR: Imagination Technologies Cocos2d: cocos2d: GL_RENDERER: PowerVR SGX 535 Cocos2d: cocos2d: GL_VERSION: OpenGL ES 2.0 IMGSGX535-63.24 Cocos2d: cocos2d: GL_MAX_TEXTURE_SIZE: 2048 Cocos2d: cocos2d: GL_MAX_TEXTURE_UNITS: 8 Cocos2d: cocos2d: GL supports PVRTC: YES Cocos2d: cocos2d: GL supports BGRA8888 textures: NO Cocos2d: cocos2d: GL supports NPOT textures: YES Cocos2d: cocos2d: GL supports discard_framebuffer: YES Cocos2d: cocos2d: GL supports shareable VAO: YES Cocos2d: cocos2d: compiled with Profiling Support: NO tex 196 map_001_BG.pvr map_001_BG.pvr ---over proess:11.0mb (4.0mb) free:275.8mb tex 160 map_001_BG_rgb.pvr map_001_BG_rgb.pvr ---over proess:15.0mb (4.0mb) free:271.9mb tex 130 map_001_BG.jpg map_001_BG.jpg ---over proess:19.3mb (4.3mb) free:267.6mb tex 151 map_001_BG_rgb.jpg map_001_BG_rgb.jpg ---over proess:23.5mb (4.2mb) free:263.8mb tex 344 map_001_BG.png map_001_BG.png ---over proess:28.7mb (5.3mb) free:258.7mb tex 328 map_001_BG_rgb.png map_001_BG_rgb.png ---over proess:34.0mb (5.3mb) free:253.6mb tex 237 map_001_BG.pvr.ccz map_001_BG.pvr.ccz ---over proess:38.0mb (4.0mb) free:249.6mb tex 221 map_001_BG_rgb.pvr.ccz map_001_BG_rgb.pvr.ccz ---over proess:42.0mb (4.0mb) free:245.2mb tex 98 map_001_BG_rgb565.pvr map_001_BG_rgb565.pvr ---over proess:44.0mb (2.0mb) free:243.2mb tex 300 map_001_BG_rgb565.png map_001_BG_rgb565.png ---over proess:48.9mb (4.9mb) free:238.2mb tex 293 map_001_BG_rgba8888f.png map_001_BG_rgba8888f.png ---over proess:52.8mb (3.9mb) free:234.2mb tex 87 map_001_BG_rgba8888f.jpg map_001_BG_rgba8888f.jpg ---over proess:55.7mb (2.9mb) free:231.7mb tex 143 map_001_BG_rgba8888f.pvr map_001_BG_rgba8888f.pvr ---over proess:58.3mb (2.7mb) free:228.8mb tex 300 map_001_BG_rgb888f.png map_001_BG_rgb888f.png ---over proess:62.2mb (3.9mb) free:225.3mb tex 87 map_001_BG_rgb888f.jpg map_001_BG_rgb888f.jpg ---over proess:65.1mb (2.9mb) free:222.7mb tex 91 map_001_BG_rgb888f.pvr map_001_BG_rgb888f.pvr ---over proess:67.0mb (1.9mb) free:220.7mb (lldb)
文章列表