天天看點

手遊性能優化之深入了解Texture Compression

一、引子

  手遊項目開發日常裡,經常有美術同學搞不清Photoshop制圖軟體與Unity3D遊戲引擎之間的圖檔assets流轉邏輯,在工作輸出時經常出現如下疑問:

1、要JPG的,還是要PNG的?

2、JPG的要壓存為多高品質的?

3、PNG的還要壓?引擎不是自動處理的麼?

4、為毛非要正方形的?我這個圖實在是沒法兒做方的怎麼弄?

5、圖太大,要選哪個壓縮方式?有的怎麼選了也沒效果?有的又壓的太糊!

6、這個效果不行,開發沒有還原好啊!

  是以開發或者技美同學要經常解釋這些問題,這裡面的确有些内容比較難以說明白,一個是廠商比較多流派,另一個是有些知識點(技術曆史)需要厘清,本文的作用就在于此,但不會很全面。

  下文中出現Texture的地方均指代在Unity3D場景下。

二、不要混淆JPG/PNG等圖檔壓縮格式與Texture Compression

JPG/PNG是變長編碼格式variable bit length,它有個特點:如下圖所示,顔色變化少頻率低的部分,編碼後占的記憶體位元組數就少。

手遊性能優化之深入了解Texture Compression

  是以,編碼後長度變來變去帶來的壞處就是:無法準确的計算出原圖一個坐标處的color對應的壓縮到了哪裡?除非你把整張圖檔都解壓完畢,如下圖所示。

手遊性能優化之深入了解Texture Compression

  這一緻命弱點直接導緻了GPU 裡的Texture Sample算法機制不可用,是以Unity3D引擎裡也不會直接使用JPG/PNG這種編碼格式來打包圖檔assets資源。

  結論:JPG/PNG是用來在遊戲制作流程中間傳遞美術内容的,最終在遊戲引擎裡需要轉變成一種固定碼率的、可尋址的流式壓縮格式,以友善随機尋址和采樣。

三、PVRTC/ETC等Texture Compression格式,直接被GPU讀取到顯存,用時無需解壓

  是的,無需解壓!美術同學可能難以了解,JPG壓縮了之後不解壓你怎麼看?對,GPU就是這麼屌!下面舉個例子:

  假設一張4M的RGB三通道JPG圖檔,經過ETC1壓縮後變為1M,GPU 裡的Fragment渲染子產品根據目前的Render State決定去加載Texture Buffer裡對應的某一塊位元組資料,然後經過實時的運算來還原出相應的顔色值,即采樣過程,這中間便省去了将整個圖檔解壓還原出來的步驟,因為GPU晶片很擅長這種固定的算法。

  好處顯而易見:1. 支援随機采樣,不用把整張圖load進記憶體; 2. 即使整個load進記憶體,也不用解壓展開成4M;3.如果你嫌1M還是太大,還能在打包遊戲時用ZIP再壓縮一把;

四、PVRTC 2bpp/4bpp, ETC1, ETC2,  DXT, ASTC 這些都是什麼鬼?

  是的,手機市場就是這麼亂。GPU晶片提供商有Imagination, ARM, NVIDIA, QualComm,各有各的晶片系統(SoC) IP,我們搞軟體開發的要細究起來恐怕會吐血身亡,畢竟是不同的行業。不管那麼多,結論有:

1、Imagination是被Intel和Apple兩大頭持股的,iOS平台得優選他家的PVRTC壓縮格式;

2、ETC1基本上是Android采用的公案,是以選它沒錯,但僅支援RGB三通道,如果還有A通道,得另行單獨壓一張圖;

3、ETC2雖然更新了,但目前的主流OpenGL ES 2.0規格尚不支援,不要多想了;

五、淺析ETC1 --- 一個像素2個bits是怎麼做到的?

  ETC stands for Ericsson Texture Compression and is an open standard supported in OpenGL and OpenGL ES. The technique allows lossy compression of images at a ratio of 4:1 (depending on input format and compression method).

  ETC1 textures are supported in Android and benefit from GPU hardware decompression.

    沒錯,它居然是Ericsson公司發明的壓縮專利,好在是完全公開的,并被OpenGL ES規範所支援。它基于這樣一個事實:人類的視覺系統對明度luminance的敏感度高于色度chrominance。運用這一逆天的道理就能得到逆天的壓縮方式,如下圖:

手遊性能優化之深入了解Texture Compression

1、先對圖檔進行分塊4*4;

2、每塊取出2個base colors(上下各一個,或者左右各一個),形成左圖;

3、每塊取出明度資料(逐像素的,那就是4*4=16個);

4、算法合成得到右邊的壓縮後的效果;

  是以,ETC1要做的就是把上面2和3中産生的base colors資料和luminance資料給整起來,一起壓縮咯!這真是蛋疼,用2個基色塊就能代表16個像素的顔色,你當玩家眼瞎啊!?

  原理不多說了,直接上圖:

手遊性能優化之深入了解Texture Compression

1、4*4的像素塊分為左右或者上下兩個部分,提取2個base colors,采用差分存儲,一個存為R5G5B5,內插補點存為dR3dG3dB3;

2、如果2個base colors相差太大,導緻內插補點溢出,則直接存2個R4G4B4,比如左邊紅右邊綠的這種極端情況;

3、兩個标記位,綠色的那位表示是555差分存儲呢,還是444獨立存儲;

4、重點是這個table bits,代表這裡兩個base color對應的是明度表裡的index,正好3個bits,表裡也一共2^3=8項;

5、位置剛好夠用:16個RGB像素,編碼進4個bytes,平均下來每個像素隻需2個bits;

  Texture被GPU加載到顯存緩沖區之後,怎麼尋址,怎麼采樣,具體細節就不深究了,那是硬體工程師的事情。總之,在這種架構下,ETC的缺點就是:

a、不支援RGBA 4通道的圖檔壓縮;

b、對顔色連續過渡變化的圖檔壓縮後可能有點兒糊(是以美術同學自帶的像素眼會說你把他的圖搞糊了);

  好了,上面就是對項目中常見的材質壓縮問題的終極總結,有了這些知識點,回答前頭的日常問題應該心中有數了(結合項目具體情況取舍)。

參考資料:

https://software.intel.com/en-us/articles/accelerating-texture-compression-with-intel-streaming-simd-extensions

http://fileadmin.cs.lth.se/cs/Education/EDAN35/lectures/L8-texcomp.pdf

http://www.powervr.com/Downloads/Factsheets/PVRTextureCompression.pdf

文章轉自:http://gad.qq.com/article/detail/7154875

繼續閱讀