1. 程式人生 > >常用紋理和紋理壓縮格式

常用紋理和紋理壓縮格式

簡單紋理格式

  • RGBA8888 每個畫素4位元組,RGBA通道各佔用8位
  • RGBA4444 每個畫素2位元組,RGBA通道各佔用4位
  • RGB888 每個畫素3位元組,RGB通道各佔用8位,無透明通道
  • RGB565 每個畫素2位元組,RGB通道各佔用5/6/5位,無透明通道
  • RGBA5551 每個畫素2位元組,RGB通道各佔用5位,透明通道1位,所以要麼完全透明要麼不透明

DXT紋理壓縮格式

DXT紋理壓縮格式來源於S3(Silicon & Software Systems)公司提出的S3TC(S3 Texture Compression),基本思想是把4x4的畫素塊壓縮成一個64或128位的資料塊,是有失真壓縮方式。DXT1-DXT5是S3TC演算法的五種變化,用於各種Windows裝置。

DXT1

DXT1格式主要適用於不具透明度的貼圖或僅具一位Alpha的貼圖(非完全透明則即完全不透明),對於完全RGB565格式的貼圖,DXT1具有4:1的壓縮比,即平均每個畫素顏色佔4位,雖然壓縮比並不是很好,但是DXT的特性使得它更適合用於實時遊戲之中。

DXT1將每4×4個畫素塊視為一個壓縮單位,壓縮後的4×4個畫素塊佔用64位,其中有2個16位的RGB顏色和16個2位索引,格式描繪如下圖所示:
這裡寫圖片描述

DXT1中的兩個RGB顏色負責表示所在壓縮的4×4畫素塊中顏色的兩個極端值,然後通過線性插值我們可以再計算出兩個中間顏色值,而16個2位索引則表明了這4×4個畫素塊所在畫素的顏色值,2位可以表示4種狀態,剛好可以完整表示color_0,color_1以及我們通過插值計算出的中間顏色值color_2和color_3,而對於具有一位Alpha的貼圖,則只計算一箇中間顏色值,color_3用來表示完全透明。

對於如何判斷DXT1格式是表示不透明還是具有1位alpha的貼圖,則是通過兩個顏色值color_0和color_1來實現的,如果color_0的數值大於color_1則表示貼圖是完全不透明的,反之則表示具有一位透明資訊。因為只有一位 Alpha 資訊,所以只能表示透明或不透明,因此DXT1的透明其實是一種鏤空,利用網孔達到的透明效果,我們一般對畫面質量要求不高並且不需要透明資訊的圖片使用這種格式。

DXT2/DXT3

DXT2和DXT3可以表示具有更復雜的透明資訊的貼圖,這兩種格式採用的是顯式的Alpha表示,我們知道了在DXT1中,我們使用64位資料來描述4*4的畫素塊的顏色資訊,在DXT2和DXT3中,這部分顏色資訊是不變的,而是通過另附加64位資料也就是每個畫素4位來表示他們的Alpha透明資訊,而這4位的Alpha的資訊通常情況下我們可以採用直接編碼的方式來表示即可。

這樣每個4×4畫素塊佔用128位也就是8個字,0~3字表示透明資訊;4~7表示前面描述的顏色的資訊。

DXT2和DXT3的不同之處在於,DXT2中顏色是已經完成了Premultiplied by alpha操作(已完成顏色與alpha的混合,當透明度發生改變時,直接改變整體顏色值,不必再單獨複合),DXT3的Alpha資訊則是相對獨立的,之所以要區分開了則是為了適應不同的需要,因為有些場合需要獨立的Alpha資訊。
這裡寫圖片描述

DXT2/DXT3主要用於Alpha通道較銳利,對比強烈的材質,比如鏤空或部分半透材質等。

DXT4/DXT5

DXT4、DXT5也是用於表示具有複雜的透明資訊的貼圖,與2和3不同的是4和5的Alpha資訊是通過線性插值計算所得,類似於DXT1的顏色資訊。同樣的,每4×4的畫素塊的透明資訊佔用64位,所不同的是,64位中採用了2個8位的alpha值和16個3位的索引值,既然每個畫素的索引佔3位,那麼可以表示8種不同的透明狀態。

在這裡插值的方法有兩種,一種用於表示具有完全透明和完全不透明的狀態,另一種則是僅在給出的極端值alpha_0和alpha_1中進行插值。區分的方法也是通過比較alpha_0和alpha_1的大小來實現的,如果alpha_0大於alpha_1,則通過插值計算剩下的6箇中間alpha值;否則,只通過插值計算4箇中間alpha值,alpha_6直接賦值0,alpha_7直接賦值255。

DXT4和DXT5的區別同DXT2和DXT3的區別相同,DXT4的顏色值是理解為已經完成Premultiplied by alpha操作的。

FOURCC Description Alpha premultiplied? Compression ratio Texture Type
DXT1 1-bit Alpha/Opaque N/A 6:1(對24位源圖) Simple non-alpha
DXT2 Explicit alpha Yes 4:1 Sharp alpha
DXT3 Explicit alpha No 4:1 Sharp alpha
DXT4 Interpolated alpha Yes 4:1 Gradient alpha
DXT5 Interpolated alpha No 4:1 Gradient alpha

ETC紋理壓縮格式

Ericsson Texture Compression,是由 Khronos 支援的開放標準,在移動平臺中廣泛採用。它是一種為感知質量設計的有損演算法,其依據是人眼對亮度改變的反應要高於色度改變。類似於DXT,ETC也是把4x4的畫素塊壓縮成一個64或128位的資料塊,也是有失真壓縮。

ETC1

ETC1把一個4x4的畫素單元組壓成一個64位的資料塊。4x4的畫素組先被水平或垂直分割成2個4x2的組,每一半組有1個基礎顏色(分別是RGB444/RGB444或RGB555/RGB333格式)、1個4位的亮度索引、8個2位畫素索引。每個畫素的顏色等於基礎顏色加上索引指向的亮度範圍。

比如對於某一個半組:
1. 12位的基礎顏色是RGB(0, 34, 255);
2. 4位的亮度索引從亮度表中選擇亮度補充,亮度表有16個,下表是0-7,8-15是0-7的2倍。
這裡寫圖片描述
亮度索引1對應(-12, -4, 4, 12);
3. 2位的畫素索引是0,所以亮度補充是-12。由此可以得到此畫素的顏色值是(0-12, 34-12, 255-12),也即(0, 22, 243)。

四大移動裝置GPU都支援ETC1,所以在各種Android裝置上非透明紋理都可以採用ETC1格式,遺憾的是ETC1不支援透明。對於透明紋理,在Android裝置上,可以把RGB和Alpha拆到2張ETC1紋理上,遊戲中再合成使用。

ETC2

ETC2是ETC1的擴張,向後相容ETC1,對RGB的壓縮質量更好,並且支援透明通道。目前下列ETC2壓縮格式在OpenGL ES 3.0和OpenGL 4.3上被要求支援:
- GL_COMPRESSED_RGB8_ETC2 壓縮的RGB888格式,類似於ETC1
- GL_COMPRESSED_RGBA8_ETC2_EAC 壓縮的RGBA8888格式,支援完全的透明通道
- GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 壓縮的RGBA資料,只有一位Alpha

ETC2比ETC1壓縮質量更高,而且支援透明,在Android裝置上再也不需要打不同紋理格式的包了。不過需要OpenGL ES 3.0以上才可以,目前很多裝置只支援OpenGL ES 2.0。

PVRTC紋理壓縮格式

PowerVR Texture Compression,PVRTC格式與基於塊的壓縮格式,比如S3TC、ETC的不同之處是,它使用2張雙線性放大的低解析度圖,根據精度和每個畫素的權重,融合到一起來呈現紋理,並且2-bpp和4-bpp都支援ARGB資料。PVRTC格式壓縮比高,也是有失真壓縮。

PVRTC 2-bpp

2 bits per pixel,每個畫素2位,質量較差,把一個8×4的畫素單元組壓成一個64位的資料塊。每個資料塊中儲存了6個變數:調製資料(32位),punch-through Alpha標誌(1位),顏色A(15位),顏色A不透明標誌(1位),顏色B(14位)和顏色B的不透明標誌(1位)。

PVRTC 4-bpp

4 bits per pixel,每個畫素4位,把一個4×4的畫素單元組壓成一個64位的資料塊。每個資料塊中儲存了6個變數:調製資料(32位),調製標誌(1位),顏色B(14位),硬轉換標誌(1位),顏色A(15位)和不透明標誌(1位)。

注意:顏色A和B必須格式相同(都為RGB或RGBA),並且整個紋理都是這個RGB或RGBA格式。關於PVRTC的詳細細節請參考[7],下面給出一張PVRTC2的格式圖:
這裡寫圖片描述

PVRTC格式可以用在所有的iOS裝置和使用PowerVR GPU的Android裝置上,它要求紋理的高、寬必須都是2的整數次冪,最小為8,並且必須是正方形。

參考: