文章出處

為毛要寫這個


本來覺得像這樣的問題,是無法歸類的,因為不同的項目有不同的需求,但今天因為quick論壇中的一個技術疑問貼,鉤起了我整理這篇文章的興趣 http://www.cocoachina.com/bbs/read.php?tid=214811

于是,我決定盡力描述一下紋理格式選擇方面的問題,一是起到一個科普的作用,因為目前沒有發現十分完整的講這方面的文章。二是整理一下自己的思路。

當然,這些東西肯定不是我自己憑空YY出來的,我也是參考了不少文章,也從項目中總結了一些問題。在此先列出一些鏈接,先睹為快

移動平臺GPU壓縮文理大全

使用Mali官方工具進行ETC1紋理壓縮

Ericsson Texture Compression

iOS和android游戲紋理優化和內存優化(cocos2d-x)

優化你的手機游戲(沒有延遲,才是健康的)

Cocos2d-x紋理優化方案的一些總結

手機游戲開發紋理圖片優化心得

手機游戲開發,如何選擇和優化圖片素材

 

嗯 ,我覺得已經足夠多了,并且,可能你也沒有耐心把所有鏈接看完。 至少我沒有……。

 

 

GPU紋理與非GPU紋理


很多小伙伴其實一直不明白GPU紋理與非GPU紋理的區別,以致于我打了將近1000字,他也沒有懂為什么JPG不能省內存。

常見的JPG格式,是一種文件壓縮格式,即它能夠把圖片像素值,使用一種有損壓縮的方式來存儲,這樣圖片的體積會變得非常小。

而我們經常提到的GPU紋理格式,如pvrtc,etc等,是一種GPU壓縮格式,這種壓縮格式,文件大小會比JPG大,但是它讀入到內存后,不會被解壓,而是直接送到顯卡。 顯卡也不會對齊解壓,而是在執行如tex2D紋理采樣指令的時候,取訪問并索取對應像素值的內容。 這樣才能夠節省顯存和內存。 pvrtc、etc等,既能夠進行壓縮,同時又提供隨機訪問(即在不全部解壓的情況下,訪問指定UV坐標的像素值)能力,因此會比jpg大許多

 

 

圖片格式簡介


->pvrtc

pvrtc有兩種格式,一種是pvrtc 2bp,一種是pvrtc4bp。 二者沒有本質區別,最主要的區別就是2bp表示每個像素使用2 bit來存儲,4bp使用4bit來存儲。當然這是一種理論值,由于pvrtc還需要儲存額外的信息以保證能夠恢復像素值,以及提供隨機訪問能力。 所以,實際的pvrtc格式的文件,不會是1/8和1/16這么小。pvrtc格式讀入內存后,不會進行解壓,而是直接送給GPU。 GPU也不會進行解壓,從而保證了內存和顯存的節約。 而tex2D能夠對這種格式的紋理直接采樣。

另外,pvrtc目前有兩個大版本,pvrtc1和pvrtc2,pvrtc2對壓縮算法做了明顯的改進。 但需要新款的GPU才支持,所以,如果要使用pvrtc2版本的PVRTC紋理,記得檢查OPENGL ES的擴展標記。

pvrtc建議只對IOS平臺使用,因為這是power vr顯卡專用的紋理格式。

->etc

etc目前有兩種格式,etc1/etc2。 etc1是opengl es 1.x和opengl es 2.0提供的必須支持的硬件格式,其唯一的缺點就是不支持ALPHA通道。 而etc2是opengl es 3.0才支持的,且增加了ALPHA通道能力。

由于目前opengles 3.0設備的普及率還不高,目前(寫這文章的時候是2014年7月18日)建議使用etc1格式

建議etc1格式使用在ANDROID平臺上。

 

->png24/32

png24和32其實是一樣的,24表示ALPHA通道不使用,因此,這是一種RGBA8888的紋理格式,這種格式不進行任何壓縮,完全保持原始像素值。可以提供較高的質量,但這種紋理占用的磁盤空間較大。(與其內存占用等同),可以簡單地通過 長x寬x4來計算大小。 比如1024x1024的PNG24/32紋理,占用磁盤空間和內存為 4MB。

->png8

png8十分復雜,因為png8的意義比較多。

僅包含ALPHA通道的8位PNG:這種通常拿來提供單獨的ALPHA通道能力,opengl d3d等均支持這種8位ALPHA紋理。

256色調色板的PNG:這種通常見于網站圖標等,它只有一位表示ALPHA,即鏤空效果。且不適合用在需要表現豐富和高飽和度的場合。

通過一些壓縮方式得到的壓縮PNG:如grunt-png8,tinypng等, 這些工具,使用了較高的壓縮技巧,使PNG24/32的RGBA可以保存在8位通道中。 且能夠提供較高的還原度。 這種和PNG一樣,讀入內存后,每個像素依然占4BYTES。

->jpg

jpg是一種通過有損壓縮算法,使原始圖片可以以很小的文件來存儲的格式。 這種和上面提到的png8十分類似,但JPG不支持ALPHA通道。 雖然不支持ALPHA通道,但它讀進內存后,內存占用依然是每個像素4BYTES。

 

另外還有一些dds,tga等,由于我個人在手機游戲開發方面涉及這方面較少(端游使用tga和dds較多),在此不作論述。

 

如何選擇紋理格式


人生之所以糾結,在于許多事情你可以選擇

                                             ---糾結帝·麒麟子·Alex

 

上面的紋理格式,同一種情況下,可能多種都適合,那如何選擇呢。 我們還是根據具體情況而定。

 

1、場景、背景、全屏圖片

2D手機游戲中,多半都有這樣的圖片,以作為背景,特別在一些SLG,橫版過關游戲中。這種圖片對ALPHA沒有要求,并且,在同一時間,只會出現一張(如果是多張拼接,也不會超過屏幕尺寸太多),內存不會成為關鍵點。所以,在這種情況下,我們大膽選擇JPG就可以了。

2、場景的前景,裝飾物,可移動對象

這種要看規模,如果規模較小,類型不多。 或者類型雖然多,但同一時間出現在場景中的類型不多,那我們可以選擇壓縮PNG8的方式,它支持ALPHA通道,文件又小。

如果同屏可能出現多種這種,則需要考慮在IOS上使用PVRTC,在ANDROID上使用ETC1+ALPHA_MASK

3、UI

UI的背景圖,可以優先考慮使用壓縮PNG8,如果達不到精度要求,則使用PNG32。而對于UI的小元素,可以考慮使用壓縮PNG8.

對于UI的圖標,一般是不帶ALPHA的PVRTC/ETC + 一張公共的ALPHA掩碼圖,通過雙層混合來實現圓邊效果。 因為圖標同屏出現可能較大。 如果圖標能夠控制在一定范圍內,由于圖標是48X48等大小,一張1024x1024的大圖,可以放400個圖標。 換用JPG,也有4MB的開銷,如果這個是可以接受的,也可以使用JPG+ALPHA_MASK的方式。

 

寫到這里才發現,其實只需要下面一句話就可以搞定。

這類圖片會不會同時出現多個,同時出現時,內存開銷是否無法接受, 如果確實無法接受,則使用GPU紋理,否則,優先考慮JPG,JPG+ALPHA,或者PNG8

 

就是說,首先要減小安裝包大小,如果內存有無法接受的情況,才需要用GPU紋理進行優化。而我們在優化的時候,最好是對某一類圖片進行統一處理。 比如場景圖片,如果決定了使用JPG,那就清一色的JPG。

 

紋理的出圖和處理


這么多格式,如果讓美術來出圖,不是要折騰死么。

因此,只需要規定,美術出圖只給PNG(有些可能會是TGA)即可,剩下的事情,程序自己寫腳本進行解決。 這樣可以保證美術出圖的規范性,同時也避免了程序在優化過程中,切換紋理格式帶來的重新出圖問題。

PS:pvrtc和etc都可以使用pvrtex tool進行轉換, etc的轉換也可以使用mali的工具,看各人愛好了。 pvr的工具不管是下載,還是查看文檔,都需要注冊,就不給鏈接了……。

 

結束


或許你會說,JJYY半天,沒有帶點實際的。

這句話真的挺嘲諷的,但我真的打算結束了,一是我想要說的,就是這些,二是,我沒有打算寫一個如何在移動平臺上使用各種紋理的文章。

希望這篇文章能夠給迷茫的兄弟帶來靈感。


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()