cocosCreator版本:2.4.4
平臺:android
測試工具:adb ,perfdog: https://perfdog.qq.com/
紋理壓縮工具:cocoscreator 提供的etc1A slow模式
測試參數:一張 1280 * 720 的png格式的背景圖片
這篇文章主要圍繞「cocoscreator提供的紋理壓縮功能」及 「紋理壓縮相關的知識點」來進行的,通過閱讀本篇文章,你可以 更清晰的認識在你的項目中 如何權衡 是否用紋理壓縮 來達到你想要的 優化效果。
紋理壓縮相關知識點
1,計算機中計量存儲容量計量單位:
「位(bit」 數據存儲的最小單位。在計算機中的二進制數系統中,位,簡記爲b,也稱爲比特,每個0或1就是一個位(bit)。計算機中的CPU位數指的是CPU一次能處理的最大位數。
「字節(byte」字節(Byte)是計算機信息技術用於計量存儲容量的一種計量單位,也表示一些計算機編程語言中的數據類型和語言字符。Byte是從0-255的無符號類型,所以不能表示負數 。
KB: 千字節 是計算機信息技術用於計量存儲容量的一種計量單位
MB:兆字節 是計算機信息技術用於計量存儲容量的一種計量單位
GB:是計算機信息技術用於計量存儲容量的一種計量單位
關係:
1GB = 1024MB
1MB = 1024KB
1KB = 1024Byte
1Byte = 8bit
1bit(位) 是數據存儲最小單位
2,像素格式。
像素格式描述了像素數據存儲所用的格式。定義了像素在內存中的編碼方式。
「像素深度」:像素深度是指存儲每個像素所用的位數,也用它來度量圖像的分辨率。像素深度決定彩色圖像的每個像素可能有的顏色數,或者確定灰度圖像的每個像素可能有的灰度級數。例如,一幅彩色圖像的每個像素用R,G,B三個分量表示,若每個分量用8位,那麼一個像素共用24位表示,就說像素的深度爲24。一個像素的位數越多,它能表達的顏色數目就越多,而它的深度就越深。
「顏色通道」:一般用RGBA來表示 顏色通道中R,G,B,A的意義是:R 紅色成分,通常範圍從0.0(沒有紅色)到1.0(全部的紅色)。G 綠色成分,通常範圍從0.0(沒有綠色)到1.0(全部的綠色)。B 藍色成分,通常範圍從0.0(沒有藍色)到1.0(全部的藍色)。A alpha(不透明度)成分,通常範圍從0.0(完全透明)到1.0(不透明)。
「像素格式」:每個像素所使用的顏色通道的組合模式
常見的像素格式有:
「RGBA4444」 :每個通道佔4位(bit) 及用此種格式表示一個像素 佔用的存儲大小是 4*4 = 16 位 = 2Byte。
「RGBA8888」 :每個通道佔8位(bit) 及用此種格式表示一個像素 佔用的存儲大小是 4*8 = 32 位 = 4Byte。
「RGB565」 :佔用的存儲大小 5+6+5 = 16 位 = 2Byte
「RGB888」 :每個通道佔8位(bit) 及用此種格式表示一個像素 佔用的存儲大小是 3*8 = 24 位 = 3BYte。
等等其他格式。
每個像素的大小 取決於 像素深度 及每個顏色通道所佔的位數 所有通道位數的累加。
2,一張圖片在磁盤中的大小,一張圖片加載到內存中的大小
「我們在 磁盤中看到的一張圖片的大小 與 加載到內存中該圖片所佔用的大小 是不一樣的 ,png格式是一種複雜的編碼壓縮格式,可以把圖像信息 高比例壓縮,便於傳輸,而加載到內存中 需要解壓解碼還原原始信息。所以 在內存中佔用的大小要遠遠大於我們在磁盤中看到的大小」後面會詳細解釋,這裏先了解一下。
通常情況下 計算一張png圖片加載到內存的佔用大小公式是: 「圖片分辨率4 = 佔用內存」* 單位是字節
比如一張1280 * 720 的背景圖 所佔的內存(顯存)是
1280 * 720 * 4 = 3686400 byte = 3686400 / 1024 = 3600 kb = 3600 / 1024 = 3.515 MB
因爲一張圖片加載到內存中的大小 是由他的像素格式決定的,也是就是 每個像素所用的 像素格式 一般情況下 是默認「rgba8888」格式也就是 一個像素32位 及4個字節。 如果 格式用「rgba4444」 那就是 16位 及2個字節 那計算出來的 內存佔用是:
「圖片分辨率2 = 佔用內存」* 單位是字節
細化後的 計算公式是「分辨率寬分辨率高 * 像素格式通道所佔用的位數 / 8 = 內存佔用」*
如果是安卓手機 圖片在不同目錄下 系統會根據 所在目錄的dpi(圖像每英寸長度內的像素點數) 進行 計算。
另外 如果用壓縮紋理格式的話 , 壓縮後的紋理大小 跟紋理加載到gpu的大小 是一樣的。比如 一張1280 * 720 的png圖片 壓縮紋理後大小 1441kb 傳遞給 gpu 使用時的大小就是 1441kb。
1,圖片文件格式與紋理格式的區別
「圖片文件格式是」:將「位圖信息(圖像的表述方式,二維數組)」 通過 特殊的編碼 生成的存儲格式,用於圖像信息的存儲和傳輸,一般在磁盤,內存及網絡中存儲與傳輸。我們經常看到的圖片文件格式 有 png,jpg等格式,「png(無損壓縮)」, 「jpg(有損壓縮」也會把這些圖片稱爲紋理,但他們並不是紋理格式,不能被GPU直接讀取並顯示。這些文件格式當被遊戲讀入後,需要經過CPU解碼成 「原始位圖(位圖的每個像素可以用RGB格式(像素/紋理格式)表述如:RGB565,RGBA4444,RGBA5555,RGB888, RGBA8888)」 ,再傳送到GPU端進行使用。
「紋理格式」:是能被GPU所識別的像素/紋理格式(「RGB565,RGBA4444,RGBA5555,RGB888, RGBA8888等」),能被快速尋址並採樣。是GPU能直接使用的數據格式。
2,什麼是紋理壓縮,常見的壓縮紋理格式
「紋理壓縮格式」 :
紋理壓縮原理參考地址:https://www.khronos.org/registry/OpenGL/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt
參考博客:https://www.cnblogs.com/fuckgiser/p/5497013.html
壓縮紋理,是一種GPU能直接讀取並顯示的格式,使得圖像無需解壓即可進行渲染,可節約大量的內存。常見的紋理壓縮格式ETC,PVRTC.
「ETC:」是一種爲感知質量設計的有損算法,其依據是人眼對亮度改變的反應要高於色度改變。是把4x4的像素塊壓縮成一個64或128位的數據塊,,是有損壓縮。壓縮率6:1,ETC 分爲兩種,「ETC1」和「ETC2」 ETC1適用於Opengl ES 2.0 支持幾乎所有市面上的Android機,所有iPhone ETC2 適用於 Opengl ES 3.0 支持大部分高端Android機,iPhone 5S及以上機型。
「PVRTC:」PVRTC格式與基於塊的壓縮格式,與ETC的不同之處是,它使用2張雙線性放大的低分辨率圖,根據精度和每個像素的權重,融合到一起來呈現紋理,並且2-bpp和4-bpp都支持ARGB數據。PVRTC格式壓縮比較高,也是有損壓縮。壓縮比 2-bpp 16:1 4-bpp 8:1. 只支持長寬相等且爲2的冪次方的紋理,支持部分Android機(GPU:PowerVR系列),iPhone全系列機型
「opengl與webgl版本對應關係」
OpenGL 2.0 ——> OpenGL ES 2.0 ——> WebGL 1.0
OpenGL 3.3 ——> OpenGL ES 3.0 ——> WebGL 2.0
紋理壓縮對遊戲項目的影響
1,包體
1)紋理壓縮後的文件要比 png文件大很多(etc紋理壓縮的文件名後綴是.pkm) 一張35kb左右的 1280 * 720 的png格式 的圖片 紋理壓縮後的 pkm文件是 1.4MB左右。
2)打成蘋果包和安卓包 後 大小 壓縮紋理的 包要比 png的包小 一些 項目中只有一張自己添加的1280 * 720的背景圖
沒有壓縮紋理的包體是 9254kb
壓縮紋理的包體是 9227kb
3)如果需要動態加載又想節省下載時間成本 可以考慮 紋理壓縮後進行zip壓縮 下載到本地後進行解壓縮 這種方案。權衡利弊。
zip壓縮後的大小:測試用的工具是 7-zip 僅用於測試。項目中可以考慮用gzip 命令gzip地址 http://gnuwin32.sourceforge.net/packages/gzip.htm
壓縮前1441kb 壓縮後9kb2,內存
1)通過翻閱大量資料和實際測試 png格式的圖片 加載到內存 到提供給gpu渲染。會保存兩份 cpu解碼後的位圖數據 ,一份放在cpu 一份放在gpu. 壓縮紋理的數據 則只在gpu保留一份。
2)測試數據 兩種方式:一種將1280 * 720的圖片直接拖到編輯器 第二種是 用cc.resources.load動態加載
「a」:直接拖到編輯器 貼圖大小 1280*720 加載之前 內存佔用 約 121MB 加載紋理壓縮後的 圖片 內存佔用122-123MB 未壓縮紋理的加載佔用內存是 125-126左右
「b」:用cc.resources.load動態加載
未進行紋理壓縮的圖片:
未加載---加載後----加載瞬間內存佔用
118MB 128MB 130MB
117MB 128MB 130MB
118MB 127MB 130MB
114MB 124MB 125MB
104MB 116MB 116MB
進行紋理壓縮後的內存佔用:
124MB 129MB 129MB
118MB 123MB 123MB
117MB 122MB 122MB
117MB 122MB 122MB
117MB 122MB 122MB
通過測試數據可以看出
1)計算 一張圖片 加載到內存的 大小公式:分辨率 * 通道數 *單個通道佔用內存的大小(bit) 與 實際測試的 數據 有些偏差。
2)通過直接將圖片拖到編輯器上 與 動態加載圖片 的內存佔用 數據 偏差很大 ,前者佔用較小 與 計算公式所得的結果 相近, 後者翻了2倍左右
3)壓縮紋理後佔用內存 大小 遠遠小於 未壓縮紋理佔用內存大小,約 2倍左右。
注意:webgl 只支持rgba8888格式
最後 會按照 32的倍數 佔用內存
3,加載時間
理論上 壓縮紋理的 加載時間 要遠遠小於 未壓縮紋理的時間 。因爲 壓縮紋理 可以被gpu快速尋址採樣,不需要cpu的解碼 ,這個過程時間的消耗很大。而未壓縮紋理的 需要經過特定的解碼規則 進行解碼,還原 成原始位圖,傳送給gpu 進行渲染。
4,cup負荷
因爲未壓縮紋理的圖片 在加入到內存後 需要cpu進行解碼 還原成位圖,而壓縮紋理格式不需要,所以 後者會減輕cpu的負荷。
總結一下壓縮紋理的 優缺點:
「優點」:包體較小,減小首包下載時間和流量。內存佔用小,對cpu的壓力小 ,減少手機耗電量,減少遊戲由於佔用內存過大導致的崩潰概率。
「缺點」:不同的壓縮紋理格式對手機設備的支持 不盡相同,所以 需要根據市場情況選擇不同的壓縮格式。紋理壓縮後的文件 遠遠大於png等壓縮格式的大小,對於熱更新,動態遠程加載資源 來說 是很大的考驗,時間久資源包體大。可以進行zip壓縮解壓縮,處理這種問題。
在cocosCreator中配置及使用紋理壓縮功能
官方文檔參考