什麼是壓縮紋理

在實際應用特別是遊戲中紋理佔用了相當大的包體積,而且GPU無法直接解碼目前流行的圖片格式,圖片必須轉換為RGB等型別的格式才能上傳到GPU記憶體,這顯然增加了GPU記憶體的佔用。為了處理這些問題於是出現了GPU支援的壓縮紋理格式,在GPU中進行解碼。壓縮紋理屬於有失真壓縮,更在意解碼速度,而編碼在程式執行之前,因此速度較慢。

壓縮紋理的常見格式

基於OpenGL ES的壓縮紋理有常見的如下幾種實現:

1)ETC1(Ericsson texture compression)

2)ETC2(Ericsson texture compression)

3)PVRTC (PowerVR texture compression)

4)ATITC (ATI texture compression)

5)S3TC (S3 texture compression)

ETC1

ETC1格式是OpenGL ES圖形標準的一部分,並且被所有的Android裝置所支援。

副檔名為: GL_OES_compressed_ETC1_RGB8_texture,不支援透明通道,所以僅能用於不透明紋理。

且要求大小是2次冪。

當載入壓縮紋理時,引數支援如下格式: GL_ETC1_RGB8_OES(RGB,每個畫素0.5個位元組)

ETC2

ETC2 是 ETC1 的擴充套件,壓縮比率一樣,但壓縮質量更高,而且支援透明通道,能完整儲存 RGBA 資訊。ETC2 需要 OpenGL ES 3.0(對應 WebGL 2.0)環境,目前還有不少低端 Android 手機不相容,iOS 方面從 iPhone5S 開始都支援 OpenGL ES 3.0。ETC2 和 ETC1 一樣,長寬可以不相等,但要求是 2 的冪次方。

PVRTC

支援的GPU為Imagination Technologies的PowerVR SGX系列。

OpenGL ES的副檔名為: GL_IMG_texture_compression_pvrtc。

當載入壓縮紋理時,引數支援如下幾種格式: GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG (RGB,每個畫素0.5個位元組) GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG (RGB,每個畫素0.25個位元組) GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG (RGBA,每個畫素0.5個位元組) GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG (RGBA,每個畫素0.25個位元組)

ATITC

支援的GPU為Qualcomm的Adreno系列。

支援的OpenGL ES副檔名為: GL_ATI_texture_compression_atitc。

當載入壓縮紋理時,引數支援如下型別的紋理: GL_ATC_RGB_AMD (RGB,每個畫素0.5個位元組) GL_ATC_RGBA_EXPLICIT_ALPHA_AMD (RGBA,每個畫素1個位元組) GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD (RGBA,每個畫素1個位元組)

S3TC

也被稱為DXTC,在PC上廣泛被使用,但是在移動裝置上還是屬於新鮮事物。支援的GPU為NVIDIA Tegra系列。

OpenGL ES副檔名為:

GL_EXT_texture_compression_dxt1和GL_EXT_texture_compression_s3tc。

當載入壓縮紋理時,引數有如下幾種格式: GL_COMPRESSED_RGB_S3TC_DXT1 (RGB,每個畫素0.5個位元組) GL_COMPRESSED_RGBA_S3TC_DXT1 (RGBA,每個畫素0.5個位元組) GL_COMPRESSED_RGBA_S3TC_DXT3 (RGBA,每個畫素1個位元組) GL_COMPRESSED_RGBA_S3TC_DXT5 (RGBA,每個畫素1個位元組)

壓縮紋理相關API的使用

1) 獲得GPU的型號

  1. glGetString(GL_RENDERER)

2) 獲得GPU的生產廠商

  1. glGetString(GL_VENDOR);

3) 獲取GPU支援哪些壓縮紋理

  1. string extensions = (const char*)glGetString(GL_EXTENSIONS);

4)判斷是否支援ETC1格式的壓縮紋理

  1. return (extensions.find("GL_OES_compressed_ETC1_RGB8_texture")!= string::npos);

5) 判斷是否支援DXT格式的壓縮紋理

  1. return (extensions.find("GL_EXT_texture_compression_dxt1")!= string::npos ||
  2. extensions.find("GL_EXT_texture_compression_s3tc")!= string::npos);

6)判斷是否支援PVRTC格式的壓縮紋理

  1. return (extensions.find("GL_IMG_texture_compression_pvrtc")!= string::npos);

7)判斷是否支援ATITC格式的壓縮紋理

  1. return (extensions.find("GL_AMD_compressed_ATC_texture")!= string::npos ||
  2. extensions.find("GL_ATI_texture_compression_atitc")!= string::npos);

8) 上傳壓縮紋理資料

  1. void glCompressedTexImage2D(
  2. GLenum target,
  3. GLint level,
  4. GLenum internalformat,
  5. GLsizei width,
  6. GLsizei height,
  7. GLint border,
  8. GLsizei imageSize,
  9. const GLvoid * data);

internalformat即是壓縮紋理格式的型別。

9)檢視裝置支援的texture壓縮格式,可以使用如下程式碼獲取:

  1. int num_formats;
  2. glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_formats);
  3. std::cout<<"Texture extensions: "<<num_formats<<std::endl;
  4. int *formats = (int*)alloca(num_formats * sizeof(int));
  5. glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats);
  6. for(int i=0; i<num_formats; i++)
  7. {
  8. std::cout<<i<<" 0x"<<hex<<formats[i]<<dec<<std::endl;
  9. }
  10. //注意使用PVRTC格式紋理時,紋理的filter mode不能設定為 GL_LINEAR_MIPMAP_LINEAR,
  11. //否則的話加載出來的畫線顯示黑色, 這裡有提到。

10)glTexImage中指定壓縮格式可以對上傳的紋理進行壓縮以改善記憶體使用,通過設定intenalFormat為表中一個值實現。通過這種方式進行影象壓縮增加了紋理載入的開銷,但卻能夠通過更有效地使用紋理儲存空間來增加紋理效能,如果由於某些原因無法對紋理進行壓縮,OpenGL就會使用下表中所列出的基本內部格式,並載入未經壓縮的紋理。

  1. GL_COMPRESSED_RGB : GL_RGB
  2. GL_COMPRESSED_RGBA : GL_RGBA
  3. GL_COMPRESSED_SRGB : GL_SRGB
  4. GL_COMPRESSED_SRGB_ALPHA : GL_RGBA
  5. GL_COMPRESSED_RED : GL_RED
  6. GL_COMPRESSED_RG : GL_RG

除了這些壓縮格式外,OpenGL中還加入了一些特定的壓縮格式,即GL_COMPRESSED_SIGNED_RED_RGTC1,GL_COMPRESSED_SIGNED_RED_RGTC2,和GL_COMPRESSED_SIGNED_RG_RGTC2,它們用於各種單顏色通道和雙顏色通道壓縮紋理,他們代替了相容版本中GL_LUMINANCE和GL_LUMINANCE_ALPHA的功能

11)判斷紋理是否被成功壓縮

  1. GLint comFlag;
  2. glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_COMPRESSED,&comFlag);

glGetTexLevelParameteriv第三引數支援的有:

  1. GL_TEXTURE_COMPRESSED:如果紋理被壓縮返回1,否則返回0
  2. GL_TEXTURE_COMPRESSED_IMAGE_SIZE:獲取壓縮後的紋理大小(以位元組為單位)
  3. GL_TEXTURE_INTERNAL_FORMAT:所使用的壓縮格式
  4. GL_NUM_COMPRESSED_TEXTURE_FORMATS:支援的壓縮紋理格式數量
  5. GL_COMPRESSED_TEXTURE_FORMATS:支援的壓縮紋理格式陣列
  6. GL_TEXTURE_COMPRESSION_HINT: 選擇壓縮格式的方式

11)指定選擇壓縮格式的方式

  1. glHint(GL_TEXTURE_COMPRESSION_HINT,GL_FASTEST); //最快
  2. glHint(GL_TEXTURE_COMPRESSION_HINT,GL_NICEST); //質量最好
  3. glHint(GL_TEXTURE_COMPRESSION_HINT,GL_DONT_CARE); //自行選擇

壓縮紋理工具

每種壓縮紋理以及相應的廠商都提供了壓縮紋理的工具,包括視覺化工具和命令列工具,可自行下載

1)Imagination Technologies PowerVR

PVETextTool

2)Qualcomm Adreno

Adreno Texture Tool

3)ARM Mali

Mail Texture Compression Tool

4)nVIDIA Tegra

DirectX Texture Tool