-
一、貼圖和紋理
-
圖像文件格式和紋理格式的區別:
常用的圖像文件格式有BMP,TGA,GIF,JPG(有損不透明),PNG(無損透明)等;
常用的紋理格式有R5G6B5,A4R4G4B4,A1R5G5B5,R8G8B8, A8R8G8B8等。
- 文件格式
是圖像為了存儲信息而使用的對信息的特殊編碼方式,它存儲在磁盤中,或者內存中,但是並不能被GPU所識別,因為以向量計算見長的GPU對於這些復雜的計算無能為力。這些文件格式當被游戲讀入后,還是需要經過CPU解壓成R5G6B5,A4R4G4B4,A1R5G5B5,R8G8B8, A8R8G8B8等像素格式,再傳送到GPU端進行使用。
- 紋理格式
是能被GPU所識別的像素格式,能被快速尋址並采樣。
所以在Unity中無論導入圖片是什么格式,Unity都會轉換成紋理格式,便於GPU讀取使用。
OpenGL ES 2.0支持以上提到的R5G6B5,A4R4G4B4,A1R5G5B5,R8G8B8,A8R8G8B8等紋理格式,其中R5G6B5,A4R4G4B4,A1R5G5B5每個像素占用2個字節(BYTE),R8G8B8每個像素占用3個字節,A8R8G8B8每個像素占用4個字節。
- 紋理壓縮格式(硬件壓縮格式)Hardware Accellerated Formats
- DXT(PC) ETC(Android) PVRTC(IOS)
把紋理進一步壓縮(Texture Compression),不像png那樣采用霍夫曼編碼,而是針對GPU硬件的格式來壓縮。
如果GPU不支持當前壓縮格式,Unity就會將紋理轉換成RGB(A),會造成解壓過程消耗,內存中會保存兩個紋理。
- 圖片大小計算:
一個像素占的字節 = 位數(bit)/ 8 因為一個字節8位
一張圖片占的內存大小 = 寬 * 高 * 一個像素占的字節
比如一張512*512紋理,R5G6B5格式 = 512 * 512 *(一個像素占的字節) = 512*512*2/1024k= 0.5M
如果你使用的是mipmap貼圖,那么其大小將是普通圖片的1.3倍左右。
-
二、選擇紋理壓縮格式的衡量標准
- 解析速度
在紋理操作中,讀取紋理數據是關鍵步驟,所以解碼速度至關重要。
- 隨機讀取數據
能快速的隨機讀取任意像素
- 壓縮率和紋理質量
既要保證一個不錯的壓縮效果,也要把紋理損失控制在一定范圍內
- 壓縮速度
通常紋理壓縮在渲染前已經提前准備好,所以如果壓縮的速度比解析速度慢,也是可以接受的。
- 壓縮格式
使用目標平台支持的紋理壓縮格式時,GPU可以直接使用它,沒有增加消耗;
如果目標平台不支持紋理壓縮格式時,默認會將紋理解壓成RGBA32或RGB32,然后與壓縮的紋理一起存儲在內存中,會增加紋理加載時間和增加額外內存。
三、紋理壓縮格式
- png:
是無損壓縮有透明,也是占體積最少的。都是基於整幅圖片下進行的壓縮,比如霍夫曼編碼等,這樣像素和像素之間在解碼的過程中存在依賴關系,無法直接實現單個像素級別的解析,這就發揮不了顯卡的並發能力,更重要的是問題在於無論是png還是jpg最終在顯存中解碼后都是RGBA的紋理格式,因此並無法減少顯存的占用率。比如一張256*256的RGBA紋理,無論是png還是jpg格式,雖然文件大小不一樣,在顯卡中的大小仍然是256*256*4的顯存空間
- Jpg
是有損壓縮不透明。
- DXT壓縮原理:(PC端)
是一種有損紋理壓縮算法,可以說DXT是目前應用最廣泛的紋理壓縮格式,可以認為所有的PC端顯卡都支持DXT壓縮。在多數紋理壓縮選擇中都是最佳方案,幾乎可以認為是PC下的標准壓縮格式。
基本思想是把4x4的像素塊壓縮成一個64或128位的數據塊,是有損壓縮方式。
比如一個4*4像素R8G8B8格式的占的體積 = (4*4)(像素)*24(位)=384
壓縮后體積=2(像素,左上右下兩個位置)*16(位) + 16(位置索引)*2(位) = 64
DXT1中,4*4等於16個像素,然后將左上C0和右下C1保存兩個顏色,其它顏色由這兩個顏色進行差值計算,差值得到的另外兩個顏色的公式為:C2= 2/3*C0 + 1/3*C1, C3 = 1/3*C0 + 2/3*C1。16位中R&B各占5位,但是G占了6位,這是因為人眼對綠色最為敏感。DXT1可以表示透明或不透明,通過左上大於右下表示完全不透明,反之表示透明。
DXT1:4*4占用64位顏色
DXT2/DXT3:4*4占用64位顏色加(64位表示透明信息也就是一個像素4位)=128位8個字,(0-3位表示透明,4-7表示顏色)主要用於Alpha通道較銳利,對比強烈的材質,比如鏤空或部分半透材質等。
DXT4/DXT5:4*4占用64位顏色加(64位表示透明信息(2個8位透明值+16個3位索引值))=128位8個字
- ETC:(Android移動端)
ETC1:不支持透明通道,所以僅能用於不透明紋理
ETC1(不帶Alpha)OpenGL2.0支持、ETC2(帶Alpha)OpenGL3.0才支持
壓縮格式要求分辯率為2的次冪
- PVR:(IOS)
DXT的細節上缺陷明顯,原因是當把紋理分成4*4區域后,塊之間是獨立的,雖然簡化了壓縮算法,但丟失了相鄰間的相似性。而PVR則會考慮區域的右側、下側和右下側區域的關聯性。
壓縮格式要求壓縮分辯率是正方形,分辯率為2的次冪
PowerVR Texture Compression,PVRTC格式與基於塊的壓縮格式,比如S3TC、ETC的不同之處是,它使用2張雙線性放大的低分辨率圖,根據精度和每個像素的權重,融合到一起來呈現紋理,並且2-bpp和4-bpp都支持ARGB數據。PVRTC格式壓縮比高,也是有損壓縮。
-
四、Unity紋理格式總結
每位的像素點(bpp)是單個像素所需的存儲量。該值越低,可以在GPU的緩存中存儲的像素越多,從而可以更快地進行紋理訪問。
可變比特率(VBR)表示每個像素的比特不是固定值,而是取決於實際內容。VBR僅適用於Crunch壓縮,並且僅適用於磁盤上的紋理大小。內存中的大小與使用基礎紋理格式時的大小相同(例如,對於RGB Crunched DXT1,使用RGB Compressed DXT1)。
Crunch compression是DXT或ETC Texture壓縮之上的一種有損壓縮格式(部分數據在壓縮過程中丟失)。紋理在CPU上被解壓縮為DXT或ETC,然后在運行時加載到GPU。
Crunch compression可能需要很長時間才能壓縮,但是在運行時進行解壓縮非常快。
質量和壓縮時間之間的平衡:質量越高,文件大小越大。為了獲得最佳性能,尤其是在移動設備上,請使用應用程序所針對的硬件所支持的每像素位數最少的格式,只要該格式能夠提供足夠的視覺質量即可。
使用目標平台支持的紋理壓縮格式時,GPU可以直接使用它,沒有增加消耗;
如果目標平台不支持紋理壓縮格式時,默認會將紋理解壓成RGBA32或RGB32,然后與壓縮的紋理一起存儲在內存中,會增加紋理加載時間和增加額外內存。
-
五、總結
- Android采用RGBA Compressed ETC2 8 bits 不透明:RGB Compressed ETC 4 bits
- iOS采用RGBA Compressed PVRTC 4 bits 不透明:RGB Compressed PVRTC 4 bits
- 如果PVRTC不夠清晰可選用ASTC格式,ASTC有更好的質量和靈活性,並且壓縮速度比PVRTC快
- PC采用RGBA Compressed DXT5 不透明:RGBA Compressed DXT1
- 漸變紋理采用RGBA32
- 要求清晰可采用:
- (高清晰無壓縮)采用RGBA32
- (中清晰中壓縮)RGBA16+Dithering 要采用Floyd Steinberg抖動處理,不然漸變很明顯,拉伸就會差距
- (低清晰高壓縮)ETC2 PVRTC
-
ASTC壓縮率和清晰度都會比較好,支持的GPU :
tvOS (all), iOS (A8以上,5S以下), Android (PowerVR 6XT, Mali T600 series, Adreno 400 series, Tegra K1)
2016年之后的安卓手機基本支持這種壓縮格式
iphone6以及之后的機型支持這種壓縮格式 -
六、優化
- 在Unity中根據不同平台,不同功能要求的清晰度來設置不同的壓縮格式。
參考:
https://blog.csdn.net/wanglang3081/article/details/8869589
https://blog.csdn.net/weixin_33814685/article/details/86431607?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1
https://blog.csdn.net/ynnmnm/article/details/44983545