2012/08/31
圧縮テクスチャ
2012/08/28
OpenGL ES 2.0 BGRA Texture を直接読む
OpenGL と Direct3D は Texture の RGB の並びが違っています。
Vista の D3D10 で一度 OpenGL の並び順に統一されましたが
Windows 7 以降、D3D11 で元の Windows 配列が復活しました。
DDS 形式のデータはデフォルトで Windows 順の配列になっています。
OpenGL ES 2.0 では BGRA は定義されておらず、Texture Swizzle も
ないので DDS の Texture を読み込む場合は色の並び順を反転させる
必要があります。
並びの違いについて詳しくは下記の記事を参照してください。
・OpenGLES2.0 DDS テクスチャを読み込む
ですが結局 GPU としては OpenGL/D3D 両方に対応するものがほとんど
なので、この両者にそれほど違いはありません。
どちらかに決めてしまえばシェーダーでも入れ替えできます。
下記のデータを見ても、PowerVR, Adreno, Tegra は
GL_EXT_texture_format_BGRA8888 に対応していることがわかります。
・OpenGL ES Extension (Mobile GPU)
同じ PowerVR でも iOS の場合は GL_EXT_texture_format_BGRA8888
ではなく GL_APPLE_texture_format_BGRA8888 になっています。
どちらも DirectX の Windows 配列のピクセルをそのまま glTexImage2D() に
渡せる点は同じです。でも使い方が少し違います。
おそらく内部で RGBA 並びに統一した方が効率的にアクセスできるのでしょう。
PowerVR は lowp の swizzle が苦手ということもありますし、
結局ロード時に自分で byte 並びを入れ替えても変わらないかもしれません。
Mali-400MP は GL_EXT_texture_format_BGRA8888 に対応していません。
Extension として GL_ARM_rgba8 がありますが、こちらは Texture ではなく
フレームバッファの並び順です。
関連エントリ
・OpenGLES2.0 DDS テクスチャを読み込む
Vista の D3D10 で一度 OpenGL の並び順に統一されましたが
Windows 7 以降、D3D11 で元の Windows 配列が復活しました。
DDS 形式のデータはデフォルトで Windows 順の配列になっています。
Windows : B8 G8 R8 A8 OpenGL : R8 G8 B8 A8
OpenGL ES 2.0 では BGRA は定義されておらず、Texture Swizzle も
ないので DDS の Texture を読み込む場合は色の並び順を反転させる
必要があります。
並びの違いについて詳しくは下記の記事を参照してください。
・OpenGLES2.0 DDS テクスチャを読み込む
ですが結局 GPU としては OpenGL/D3D 両方に対応するものがほとんど
なので、この両者にそれほど違いはありません。
どちらかに決めてしまえばシェーダーでも入れ替えできます。
下記のデータを見ても、PowerVR, Adreno, Tegra は
GL_EXT_texture_format_BGRA8888 に対応していることがわかります。
・OpenGL ES Extension (Mobile GPU)
同じ PowerVR でも iOS の場合は GL_EXT_texture_format_BGRA8888
ではなく GL_APPLE_texture_format_BGRA8888 になっています。
どちらも DirectX の Windows 配列のピクセルをそのまま glTexImage2D() に
渡せる点は同じです。でも使い方が少し違います。
Extension InternalFormat Format Type --------------------------------------------------------------- EXT BGRA8888 GL_BGRA_EXT GL_BGRA_EXT GL_UNSIGNED_BYTE APPLE BGRA8888 GL_RGBA GL_BGRA_EXT GL_UNSIGNED_BYTE
おそらく内部で RGBA 並びに統一した方が効率的にアクセスできるのでしょう。
PowerVR は lowp の swizzle が苦手ということもありますし、
結局ロード時に自分で byte 並びを入れ替えても変わらないかもしれません。
Mali-400MP は GL_EXT_texture_format_BGRA8888 に対応していません。
Extension として GL_ARM_rgba8 がありますが、こちらは Texture ではなく
フレームバッファの並び順です。
関連エントリ
・OpenGLES2.0 DDS テクスチャを読み込む
2012/08/27
OpenGL / OpenGL ES ETC1 の互換性と KTX の落とし穴
昨日の記事に書いたように OpenGL / OpenGL ES の場合 KTX 形式の
テクスチャ読み込みが非常に簡単に出来ます。
ところが OpenGL ES 3.0 / OpenGL 4.3 の場合、ETC1 の読み込みに
問題がありました。
KTX のロード時に、ヘッダに GL_ETC1_RGB8_OES があれば
GL_COMPRESSED_RGB8_ETC2 に置き換える必要があります。
これは GPU が ETC2 に対応している場合だけです。
OpenGL ES 3.0 / OpenGL 4.3 で採用された ETC2 形式は ETC1 と
完全に上位互換性があります。
フォーマットも同一で、ETC1 は ETC2 の一部になりました。
そのため OpenGL ES 3.0 では事実上 ETC1 が無くなっています。
実際に Emulator (ES3 compatibility) で
glGetIntegerv( GL_COMPRESSED_TEXTURE_FORMATS, lists )
を列挙すると↓ ETC1 が含まれていないことがわかります。
ドキュメントによれば ETC1 画像を読み込む場合 API に
GL_COMPRESSED_RGB8_ETC2 を渡すことになっています。
そのため KTX に ETC1 が含まれている場合、OpenGL 4.3 / OpenGL ES 3.0
ではヘッダの値をそのまま使うとエラーになります。
関連エントリ
・OpenGL / OpenGL ES KTX Texture の読み込み方
テクスチャ読み込みが非常に簡単に出来ます。
ところが OpenGL ES 3.0 / OpenGL 4.3 の場合、ETC1 の読み込みに
問題がありました。
KTX のロード時に、ヘッダに GL_ETC1_RGB8_OES があれば
GL_COMPRESSED_RGB8_ETC2 に置き換える必要があります。
これは GPU が ETC2 に対応している場合だけです。
OpenGL ES 3.0 / OpenGL 4.3 で採用された ETC2 形式は ETC1 と
完全に上位互換性があります。
フォーマットも同一で、ETC1 は ETC2 の一部になりました。
そのため OpenGL ES 3.0 では事実上 ETC1 が無くなっています。
実際に Emulator (ES3 compatibility) で
glGetIntegerv( GL_COMPRESSED_TEXTURE_FORMATS, lists )
を列挙すると↓ ETC1 が含まれていないことがわかります。
tc[00]=83f0 GL_COMPRESSED_RGB_S3TC_DXT1_EXT tc[01]=83f2 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT tc[02]=83f3 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT tc[03]=8b90 GL_PALETTE4_RGB8 tc[04]=8b91 GL_PALETTE4_RGBA8 tc[05]=8b92 GL_PALETTE4_R5_G6_B5 tc[06]=8b93 GL_PALETTE4_RGBA4 tc[07]=8b94 GL_PALETTE4_RGB5_A1 tc[08]=8b95 GL_PALETTE8_RGB8 tc[09]=8b96 GL_PALETTE8_RGBA8 tc[10]=8b97 GL_PALETTE8_R5_G6_B5 tc[11]=8b98 GL_PALETTE8_RGBA4 tc[12]=8b99 GL_PALETTE8_RGB5_A1 tc[13]=9274 GL_COMPRESSED_RGB8_ETC2 tc[14]=9275 GL_COMPRESSED_SRGB8_ETC2 tc[15]=9276 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 tc[16]=9277 GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 tc[17]=9278 GL_COMPRESSED_RGBA8_ETC2_EAC tc[18]=9279 GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC tc[19]=9270 GL_COMPRESSED_R11_EAC tc[20]=9271 GL_COMPRESSED_SIGNED_R11_EAC tc[21]=9272 GL_COMPRESSED_RG11_EAC tc[22]=9273 GL_COMPRESSED_SIGNED_RG11_EAC
ドキュメントによれば ETC1 画像を読み込む場合 API に
GL_COMPRESSED_RGB8_ETC2 を渡すことになっています。
そのため KTX に ETC1 が含まれている場合、OpenGL 4.3 / OpenGL ES 3.0
ではヘッダの値をそのまま使うとエラーになります。
bool HasFormat( GLenum format ) { GLint numformat= 0; glGetIntegerv( GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numformat ); const int MAX_TLISTBUFFER= 128; GLint lists[MAX_TLISTBUFFER]; glGetIntegerv( GL_COMPRESSED_TEXTURE_FORMATS, lists ); for( int fi= 0 ; fi< numformat ; fi++ ){ if( lists[fi] == format ){ return true; } } return false; } GLuint KTX_Loader_Compressed( const void* memory, size_t memory_size ) { const KTX_Header* hp= reinterpret_cast<const KTX_Header*>( memory ); const void* image_data= address_add( memory, sizeof(KTX_Header) + hp->bytesOfKeyValueData ); unsigned int image_size= *reinterpret_cast<const int32_t*>( image_data ); image_data= address_add( image_data, sizeof(int32_t) ); GLuint texid= 0; glGenTextures( 1, &texid ); glBindTexture( GL_TEXTURE_2D, texid ); GLenum cformat= dp->glInternalFormat; if( cformat == GL_ETC1_RGB8_OES && HasFormat( GL_COMPRESSED_RGB8_ETC2 ) ){ // **** ここで ETC2 に置き換える **** cformat= GL_COMPRESSED_RGB8_ETC2; } glCompressedTexImage2D( GL_TEXTURE_2D, 0, cformat, hp->pixelWidth, hp->pixelHeight, 0, image_size, image_data ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); return texid; }
関連エントリ
・OpenGL / OpenGL ES KTX Texture の読み込み方
2012/08/26
OpenGL / OpenGL ES KTX Texture の読み込み方
OpenGL / OpenGL ES の場合 KTX 形式のテクスチャの読み込みは簡単です。
ファイルを全部メモリに読み込んだと仮定して
このように、API に渡す必要な情報が全部ヘッダに入っています。
ヘッダの構造は下記を参照してください。
・KTX File Format Specification
圧縮テクスチャの場合も簡単です。glType が 0 なら圧縮テクスチャです。
上の例はそのまま API に渡しているので、GPU が対応していない圧縮形式の場合
エラーが発生する可能性があります。
厳密には CPU とファイルの endian が一致していないケースを考慮しなければなりません。
ヘッダの endiannness を見て必要に応じて byte swap します。
データ作成環境と実行環境が一致していればあまり問題はないと思います。
KTX の注意点は DDS とデータの並びが異なっていることです。
例えば cubemap の場合、DDS は face 毎に mipmap が並びますが、
KTX は同じ mip level の face が先に来ます。
↑このようにデータの順番が異なっています。
wiki にも追記しましたが、データの入れ子構造の詳細は下記の通りです。
DDS の利点は、2D のテクスチャを 6 個並べるだけで cubemap ができること。
KTX の利点は同じサイズのサーフェースを出来るだけ一度に並べようとしていることです。
KTX の画像は下記のように 32bit のデータサイズが挿入されます。
imageSize は 1画像分の byte 数で、同じサイズのサーフェースが
並んでいるためアドレス計算が簡単になります。
glCompressedTexImage2D() にそのまま渡すことができます。
mipmap に対応するとこんな感じです。
これで mip + 圧縮テクスチャ や cubemap への対応も容易にできます。
KTX の一番の問題はデータの作成方法にあるようです。
ツールが絶望的に揃っていない状況で、まだあまり安定もしていません。
ARM の Texture Compression Tool は 64bit 環境でうまく動かず、
PVR の TexTool で ktx に出力すると PVRTC 以外は正しいヘッダ値が入りませんでした。
関連ページ
・Texture File Format
関連エントリ
・OpenGL / OpenGL ES テクスチャファイルフォーマット KTX と DDS
ファイルを全部メモリに読み込んだと仮定して
const void* address_add( const void* a, uintptr_t b ) { return reinterpret_cast<const void*>( reinterpret_cast<uintptr_t>( a ) + b ); } GLuint KTX_Loader( const void* memory, size_t memory_size ) { const KTX_Header* hp= reinterpret_cast<const KTX_Header*>( memory ); const void* image_data= address_add( memory, sizeof(KTX_Header) + hp->bytesOfKeyValueData ); image_data= address_add( image_data, sizeof(int32_t) ); GLuint texid= 0; glGenTextures( 1, &texid ); glBindTexture( GL_TEXTURE_2D, texid ); glTexImage2D( GL_TEXTURE_2D, 0, hp->glInternalFormat, hp->pixelWidth, hp->pixelHeight, 0, hp->glBaseInternalFormat, hp->glType, image_data ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); return texid; }
このように、API に渡す必要な情報が全部ヘッダに入っています。
ヘッダの構造は下記を参照してください。
・KTX File Format Specification
圧縮テクスチャの場合も簡単です。glType が 0 なら圧縮テクスチャです。
GLuint KTX_Loader_Compressed( const void* memory, size_t memory_size ) { const KTX_Header* hp= reinterpret_cast<const KTX_Header*>( memory ); const void* image_data= address_add( memory, sizeof(KTX_Header) + hp->bytesOfKeyValueData ); unsigned int image_size= *reinterpret_cast<const int32_t*>( image_data ); image_data= address_add( image_data, sizeof(int32_t) ); GLuint texid= 0; glGenTextures( 1, &texid ); glBindTexture( GL_TEXTURE_2D, texid ); glCompressedTexImage2D( GL_TEXTURE_2D, 0, hp->glInternalFormat, hp->pixelWidth, hp->pixelHeight, 0, image_size, image_data ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); return texid; }
上の例はそのまま API に渡しているので、GPU が対応していない圧縮形式の場合
エラーが発生する可能性があります。
厳密には CPU とファイルの endian が一致していないケースを考慮しなければなりません。
ヘッダの endiannness を見て必要に応じて byte swap します。
データ作成環境と実行環境が一致していればあまり問題はないと思います。
KTX の注意点は DDS とデータの並びが異なっていることです。
例えば cubemap の場合、DDS は face 毎に mipmap が並びますが、
KTX は同じ mip level の face が先に来ます。
DDS KTX -------------------------- [X+ 32x32] [X+ 32x32] [X+ 16x16] [X- 32x32] [X+ 8x8] [Y+ 32x32] [X+ 4x4] [Y- 32x32] [X+ 2x2] [Z+ 32x32] [X+ 1x1] [Z- 32x32] [X- 32x32] [X+ 16x16] [X- 16x16] [X- 16x16] [X- 8x8] [Y+ 16x16] [X- 4x4] [Y- 16x16] [X- 2x2] [Z+ 16x16] [X- 1x1] [Z- 16x16] [Y+ 32x32] [X+ 8x8] [Y+ 16x16] [X- 8x8] [Y+ 8x8] [Y+ 8x8] [Y+ 4x4] [Y- 8x8] [Y+ 2x2] [Z+ 8x8] [Y+ 1x1] [Z- 8x8] : :
↑このようにデータの順番が異なっています。
wiki にも追記しましたが、データの入れ子構造の詳細は下記の通りです。
DDS : ( ( ( ( width * height ) * volume_depth ) * mip ) * cube_face ) * array KTX : ( ( ( ( width * height ) * volume_depth ) * cube_face ) * array ) * mip
DDS の利点は、2D のテクスチャを 6 個並べるだけで cubemap ができること。
KTX の利点は同じサイズのサーフェースを出来るだけ一度に並べようとしていることです。
KTX の画像は下記のように 32bit のデータサイズが挿入されます。
int32 imageSize; // 32x32 [X+ 32x32] [X- 32x32] [Y+ 32x32] [Y- 32x32] [Z+ 32x32] [Z- 32x32] int32 imageSize; // 16x16 [X+ 16x16] [X- 16x16] [Y+ 16x16] [Y- 16x16] [Z+ 16x16] [Z- 16x16] int32 imageSize; // 8x8 [X+ 8x8] [X- 8x8] [Y+ 8x8] [Y- 8x8] [Z+ 8x8] [Z- 8x8] int32 imageSize; // 4x4 ~
imageSize は 1画像分の byte 数で、同じサイズのサーフェースが
並んでいるためアドレス計算が簡単になります。
glCompressedTexImage2D() にそのまま渡すことができます。
mipmap に対応するとこんな感じです。
GLuint KTX_Loader_Mipmap( const void* memory, size_t memory_size ) { const KTX_Header* hp= reinterpret_cast<const KTX_Header*>( memory ); const void* image_data= address_add( memory, sizeof(KTX_Header) + hp->bytesOfKeyValueData ); GLuint texid= 0; glGenTextures( 1, &texid ); glBindTexture( GL_TEXTURE_2D, texid ); unsigned int mip_level= hp->numberOfMipmapLevels > 0 ? dp->numberOfMipmapLevels : 1; unsigned int width= hp->pixelWidth; unsigned int height= hp->pixelHeight; for( unsigned int mip= 0 ; mip < mip_level ; mip++ ){ unsigned int image_size= *reinterpret_cast<const int32_t*>( image_data ); image_data= address_add( image_data, sizeof(int32_t) ); glTexImage2D( GL_TEXTURE_2D, mip, hp->glInternalFormat, width, height, 0, hp->glBaseInternalFormat, hp->glType, image_data ); width= int_max( width>>1, 1 ); height= int_max( height>>1, 1 ); image_data= address_add( image_data, (image_size+ 3) & ~3 ); } if( mip_level > 1 ){ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); }else{ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); } glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); return texid; }
これで mip + 圧縮テクスチャ や cubemap への対応も容易にできます。
KTX の一番の問題はデータの作成方法にあるようです。
ツールが絶望的に揃っていない状況で、まだあまり安定もしていません。
ARM の Texture Compression Tool は 64bit 環境でうまく動かず、
PVR の TexTool で ktx に出力すると PVRTC 以外は正しいヘッダ値が入りませんでした。
関連ページ
・Texture File Format
関連エントリ
・OpenGL / OpenGL ES テクスチャファイルフォーマット KTX と DDS
2012/08/25
OpenGL / OpenGL ES テクスチャファイルフォーマット KTX と DDS
DXT テクスチャの格納や cubemap, 3D Texture, HDR 形式など、
DDS は非常に便利なファイルフォーマットでした。
ところが DirectX は仕様自体に圧縮テクスチャが含まれているため
DXT,BC 以外のフォーマットが定義されていません。
ATITC や ETC1 など、独自の FourCC で対応しているツールもあります。
同時に PVRTC/PVRTC2、ETC2/EAC や ASTC など、DDS に格納できない
データも増えています。
KTX 形式は OpenGL の値をそのまま格納するので、Extension など
GLenum 値が決まればどんな形式も格納することができます。
今後 PVRTC2, ETC2/EAC, ASTC が出てくることを考えると ktx への
対応をきちんと考えておいた方が良さそうです。
テクスチャのファイルフォーマットについて下記のページにまとめました。
取り敢えず dds, ktx, pvr, pkm の 4 種類。
・Texture File Format
関連エントリ
・Android OpenGL ES 2.0 の圧縮テクスチャ
・Direct3D10 と DDS テクスチャフォーマット
・DirectX SDK November 2007 Gather と 新DDS フォーマット
DDS は非常に便利なファイルフォーマットでした。
ところが DirectX は仕様自体に圧縮テクスチャが含まれているため
DXT,BC 以外のフォーマットが定義されていません。
ATITC や ETC1 など、独自の FourCC で対応しているツールもあります。
同時に PVRTC/PVRTC2、ETC2/EAC や ASTC など、DDS に格納できない
データも増えています。
KTX 形式は OpenGL の値をそのまま格納するので、Extension など
GLenum 値が決まればどんな形式も格納することができます。
今後 PVRTC2, ETC2/EAC, ASTC が出てくることを考えると ktx への
対応をきちんと考えておいた方が良さそうです。
テクスチャのファイルフォーマットについて下記のページにまとめました。
取り敢えず dds, ktx, pvr, pkm の 4 種類。
・Texture File Format
関連エントリ
・Android OpenGL ES 2.0 の圧縮テクスチャ
・Direct3D10 と DDS テクスチャフォーマット
・DirectX SDK November 2007 Gather と 新DDS フォーマット
2012/08/24
サンコー Androidスティック with DUALCORE の GPU
サンコーの Android スティック ANDHDM2S を触る機会がありました。
・Androidスティック with DUALCORE
とりあえず dual core であることを確認。
CPU は NEON 使用可能で GPU は PowerVR SGX530 でした。
adb の usb ドライバは android_winusb.inf の書き換えだけで
つながりました。
関連ページ
・日本で発売された端末全リスト
・Androidスティック with DUALCORE
とりあえず dual core であることを確認。
CPU は NEON 使用可能で GPU は PowerVR SGX530 でした。
------------------- CPU ------------------- Processor : ARMv7 Processor rev 2 (v7l) processor : 0 BogoMIPS : 1061.68 processor : 1 BogoMIPS : 1064.96 Features : swp half thumb fastmult vfp edsp neon vfpv3 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x1 CPU part : 0xc09 CPU revision : 2 Hardware : EMXX Revision : 0420 Serial : 0000000000000000 ------------------- GPU ------------------- GL_VERSION: OpenGL ES 2.0 GL_RENDERER: PowerVR SGX 530 GL_VENDOR: Imagination Technologies GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 1.00 pconst=64 vconst=128 vin=16 vout=8 ptex=8 vtex=8 combotex=8 maxrender=2048 maxtexsize=2048 cubetexsize=2048 viewdims=2048 Extension: GL_OES_rgb8_rgba8 GL_OES_depth24 GL_OES_vertex_half_float GL_OES_texture_float GL_OES_texture_half_float GL_OES_element_index_uint GL_OES_mapbuffer GL_OES_fragment_precision_high GL_OES_compressed_ETC1_RGB8_texture GL_OES_EGL_image GL_OES_required_internalformat GL_OES_depth_texture GL_OES_get_program_binary GL_OES_packed_depth_stencil GL_OES_standard_derivatives GL_OES_vertex_array_object GL_OES_egl_sync GL_EXT_multi_draw_arrays GL_EXT_texture_format_BGRA8888 GL_EXT_discard_framebuffer GL_EXT_shader_texture_lod GL_IMG_shader_binary GL_IMG_texture_compression_pvrtc GL_IMG_texture_stream2 GL_IMG_texture_npot GL_IMG_texture_format_BGRA8888 GL_IMG_read_format GL_IMG_program_binary GL_IMG_multisampled_render_to_texture
adb の usb ドライバは android_winusb.inf の書き換えだけで
つながりました。
%SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_0002 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_0002&MI_01
関連ページ
・日本で発売された端末全リスト
2012/08/23
OpenGL ES 3.0 / OpenGL 4.3 ASTC 圧縮テクスチャの比較
新しい ASTC 形式で圧縮したテクスチャ画像を比べてみました。
「ETC2 の比較」 と同じ画像をエンコードして一部を切り出し 4倍に拡大しています。
↓ASTC 4x4 (8.0 bpp)

↓ASTC 5x4 (6.5 bpp)

↓ASTC 5x5 (5.3 bpp)

↓ASTC 6x5 (4.4 bpp)

↓ASTC 6x6 (3.6 bpp)

↓ASTC 8x5 (3.3 bpp)

↓ASTC 8x6 (2.7 bpp)

↓ASTC 10x5 (2.6 bpp)

↓ASTC 10x6 (2.2 bpp)

↓ASTC 8x8 (2.0 bpp)

↓ASTC 10x8 (1.6 bpp)

↓ASTC 10x10 (1.3 bpp)

↓ASTC 12x10 (1.1 bpp)

↓ASTC 12x12 (0.9 bpp)

ASTC 4x4 は画質がよく見えるかもしれませんが当然です。
8bpp なので DXT1/ETC1/ETC2 の半分の圧縮率です。
データサイズも 2倍になっています。
圧縮率を高めると徐々にブロックが目立ちますが、
それなりに階調は保っていることがわかります。
特に右の画像は 12x12 の 0.9bpp でも劣化が目立ちません。
下記の表を見て分かる通り、12x12 の場合わずか 7.6KB しか
ありません。
使用したコマンド
関連エントリ
・OpenGL 4.3/GLES 3.0 次の圧縮テクスチャ ASTC
・OpenGL ES 3.0 / OpenGL 4.3 ETC2 テクスチャ圧縮の比較
「ETC2 の比較」 と同じ画像をエンコードして一部を切り出し 4倍に拡大しています。
↓ASTC 4x4 (8.0 bpp)


↓ASTC 5x4 (6.5 bpp)


↓ASTC 5x5 (5.3 bpp)


↓ASTC 6x5 (4.4 bpp)


↓ASTC 6x6 (3.6 bpp)


↓ASTC 8x5 (3.3 bpp)


↓ASTC 8x6 (2.7 bpp)


↓ASTC 10x5 (2.6 bpp)


↓ASTC 10x6 (2.2 bpp)


↓ASTC 8x8 (2.0 bpp)


↓ASTC 10x8 (1.6 bpp)


↓ASTC 10x10 (1.3 bpp)


↓ASTC 12x10 (1.1 bpp)


↓ASTC 12x12 (0.9 bpp)


ASTC 4x4 は画質がよく見えるかもしれませんが当然です。
8bpp なので DXT1/ETC1/ETC2 の半分の圧縮率です。
データサイズも 2倍になっています。
圧縮率を高めると徐々にブロックが目立ちますが、
それなりに階調は保っていることがわかります。
特に右の画像は 12x12 の 0.9bpp でも劣化が目立ちません。
下記の表を見て分かる通り、12x12 の場合わずか 7.6KB しか
ありません。
format size (byte) bpp -------------------------------------- ASTC 4x4 64.0KB (65536) 8.0bpp ASTC 5x4 52.0KB (53248) 6.5bpp ASTC 5x5 42.2KB (43264) 5.3bpp ASTC 6x5 34.9KB (35776) 4.4bpp ASTC 6x6 28.9KB (29584) 3.6bpp ASTC 8x5 26.0KB (26624) 3.3bpp ASTC 8x6 21.5KB (22016) 2.7bpp ASTC 10x5 21.1KB (21632) 2.6bpp ASTC 10x6 17.4KB (17888) 2.2bpp ASTC 8x8 16.0KB (16384) 2.0bpp ASTC 10x8 13.0KB (13312) 1.6bpp ASTC 10x10 10.5KB (10816) 1.3bpp ASTC 12x10 9.0KB ( 9152) 1.1bpp ASTC 12x12 7.6KB ( 7744) 0.9bpp ETC1/2 RGB 32.0KB (32768) 4.0bpp 元画像 192.0KB (196608) 24.0bpp (256x256)
使用したコマンド
astcenc src dest 4x4 -exhaustive
関連エントリ
・OpenGL 4.3/GLES 3.0 次の圧縮テクスチャ ASTC
・OpenGL ES 3.0 / OpenGL 4.3 ETC2 テクスチャ圧縮の比較
2012/08/21
OpenGL 4.3/GLES 3.0 次の圧縮テクスチャ ASTC
DXTC(S3TC)/PVRTC/ETC1/ETC2 など、4x4 block を 64bit 単位で
変換する圧縮テクスチャフォーマットが第一世代なら、
128bit 単位で処理する BC6H/BC7 (BPTC) は第二世代の新しい
圧縮テクスチャフォーマットと言えます。
64bit の枠を超えた余剰 bit を、モード分岐やパーティション分割等
画質を向上させるための様々な情報として用います。
ASTC も同様で、BC6H/BC7(BPTC) と同じように 128bit 単位で圧縮を
行います。その仕組はさらに複雑でより踏み込んだ内容でした。
・128bit 単位
・複雑なモード分岐
・Dual Plane 機能 (Index を 2セット持つ)
・Partition 分割 (カラーセット Endpoint を複数持つ)
これらの特徴は BC6H/BC7(BPTC) と共通のものです。
ASTC にはさらに独自の仕様が多数含まれています。
・可変 Block サイズ (4x4 ~ 12x12)
・最大 4分割 の Partition (BPTC は 3分割まで)
・2,3,5 の 3種類の基数選択
・1~4 component の自由なフォーマット (R,RG,RGB,RGBA)
Khronos の仕様では LDR モードのみ定義されていますが、
ARM のドキュメントでは 3D texture や HDR まで言及されており
より幅広い用途が想定されていたことがわかります。
・KHR_texture_compression_astc_ldr
・ARM Mali developer Center: ASTC Evaluation Codec
bit field は非常に自由で、モードと Endpoint (代表カラー値) が
下位 bit から、Index (Texel Weight) が上位 bit から必要個数並ぶという
可変フォーマットです。
そのため組み合わせ数は膨大で単純なモード数では表現できません。
また 2進数からくる制約が少ないのも大きな特徴の一つです。
例えば block サイズも 5x5 , 6x6 , 10x8 など中途半端なサイズを
選ぶことができます。
Index によるカラーの補間も、DXT 等では 2bit なので 4段階ですが、
ASTC では 3値や 5値等の任意の段階を選ぶことができます。
DXT では 2色の代表カラーを選んでも、4階調だとちょうど中間の値を
生成することができません。画像によっては都合が悪く、敢えて
DXT1 の 3色モード (Alpha 1bit) を用いることがありました。
ASTC は 3 と 5 の基数を用いることができます。
5つの 3階調値を 8bit (3^5 = 243) に格納し、同様に 3つの 5階調値を
7bit (5^3 = 125) に収めます。
これに任意ビット数のスケール値を掛けることで、2 の n 乗に制限されず
下記の値の範囲を格納することができます。
例えば 12 (0~11) 段階をエンコードするなら 5個単位で格納します。
それぞれが 2bit のスケールを持つので、8bit + 5*2bit = 18bit (5個分)
となります。
このようにより自由なエンコードアルゴリズムを用いつつ、かつハードウエアで
実装しやすいようさまざまな工夫が施されています。
関連エントリ
・OpenGL 4.3/ES 3.0 ETC2 Texture 圧縮の仕組み (PVRTC2,ASTC)
・Direct3D11/OpenGL 圧縮テクスチャ BPTC, BC6H/BC7 の詳細構造 (2)
・Direct3D11/OpenGL 圧縮テクスチャ BPTC, BC6H/BC7 の詳細構造 (1)
・OpenGL の圧縮テクスチャ (3) BPTC, BC6H/BC7
・OpenGL の圧縮テクスチャ (2) 法線圧縮
・Android OpenGL ES 2.0 の圧縮テクスチャ
変換する圧縮テクスチャフォーマットが第一世代なら、
128bit 単位で処理する BC6H/BC7 (BPTC) は第二世代の新しい
圧縮テクスチャフォーマットと言えます。
64bit の枠を超えた余剰 bit を、モード分岐やパーティション分割等
画質を向上させるための様々な情報として用います。
ASTC も同様で、BC6H/BC7(BPTC) と同じように 128bit 単位で圧縮を
行います。その仕組はさらに複雑でより踏み込んだ内容でした。
・128bit 単位
・複雑なモード分岐
・Dual Plane 機能 (Index を 2セット持つ)
・Partition 分割 (カラーセット Endpoint を複数持つ)
これらの特徴は BC6H/BC7(BPTC) と共通のものです。
ASTC にはさらに独自の仕様が多数含まれています。
・可変 Block サイズ (4x4 ~ 12x12)
・最大 4分割 の Partition (BPTC は 3分割まで)
・2,3,5 の 3種類の基数選択
・1~4 component の自由なフォーマット (R,RG,RGB,RGBA)
Khronos の仕様では LDR モードのみ定義されていますが、
ARM のドキュメントでは 3D texture や HDR まで言及されており
より幅広い用途が想定されていたことがわかります。
・KHR_texture_compression_astc_ldr
・ARM Mali developer Center: ASTC Evaluation Codec
bit field は非常に自由で、モードと Endpoint (代表カラー値) が
下位 bit から、Index (Texel Weight) が上位 bit から必要個数並ぶという
可変フォーマットです。
そのため組み合わせ数は膨大で単純なモード数では表現できません。
また 2進数からくる制約が少ないのも大きな特徴の一つです。
例えば block サイズも 5x5 , 6x6 , 10x8 など中途半端なサイズを
選ぶことができます。
Index によるカラーの補間も、DXT 等では 2bit なので 4段階ですが、
ASTC では 3値や 5値等の任意の段階を選ぶことができます。
DXT では 2色の代表カラーを選んでも、4階調だとちょうど中間の値を
生成することができません。画像によっては都合が悪く、敢えて
DXT1 の 3色モード (Alpha 1bit) を用いることがありました。
ASTC は 3 と 5 の基数を用いることができます。
5つの 3階調値を 8bit (3^5 = 243) に格納し、同様に 3つの 5階調値を
7bit (5^3 = 125) に収めます。
これに任意ビット数のスケール値を掛けることで、2 の n 乗に制限されず
下記の値の範囲を格納することができます。
3 (0-2) = 3 + 0bit 4 (0-3) = 2bit 5 (0-4) = 5 + 0bit 6 (0-5) = 3 + 1bit = 3 * 2 8 (0-7) = 3bit 10 (0-9) = 5 + 1bit = 5 * 2 12 (0-11)= 3 + 2bit = 3 * 4 :
例えば 12 (0~11) 段階をエンコードするなら 5個単位で格納します。
それぞれが 2bit のスケールを持つので、8bit + 5*2bit = 18bit (5個分)
となります。
このようにより自由なエンコードアルゴリズムを用いつつ、かつハードウエアで
実装しやすいようさまざまな工夫が施されています。
関連エントリ
・OpenGL 4.3/ES 3.0 ETC2 Texture 圧縮の仕組み (PVRTC2,ASTC)
・Direct3D11/OpenGL 圧縮テクスチャ BPTC, BC6H/BC7 の詳細構造 (2)
・Direct3D11/OpenGL 圧縮テクスチャ BPTC, BC6H/BC7 の詳細構造 (1)
・OpenGL の圧縮テクスチャ (3) BPTC, BC6H/BC7
・OpenGL の圧縮テクスチャ (2) 法線圧縮
・Android OpenGL ES 2.0 の圧縮テクスチャ
2012/08/20
OpenGL ES 3.0 / OpenGL 4.3 ETC2 テクスチャ圧縮の比較
比べてみました。
↓元 (4倍に拡大したものです)

↓DXT1 (S3TC)

↓ETC1 (RGB8)

↓ETC2 (RGB8)

結果はエンコーダーの能力にも依存します。
おそらくもっと良い圧縮ツールもあると思います。
特に DXT (S3TC) はツールが豊富なので、上の例よりも良い結果に
なるかもしれません。
ETC1 しか使えない Mali-400 等の GPU では、今までテクスチャの
圧縮方法が限られていました。
・RGB8 のみで Alpha がない
・4x2 単位で 1色しか選択できない
ひとつは Alpha が使えないなど機能的な問題ですが、もうひとつは
画質の問題です。上の例のように 4x2 の大きなブロックが生じ、
DXT1 よりも著しく劣化するケースがありました。
結果を見ても、ETC2 ではこの問題が解消されていることがわかります。
・Alpha や 1-2 component などバリエーションが豊富
・DXT のように 4x4 単位で 2色使える mode が追加された
・GPU 間で共通のフォーマットとして使える (ようになるはず、将来は)
(注意: 手元に手頃なサンプル画像がなかっただけで、決して法線圧縮に
利用しているわけではありません。)
関連エントリ
・OpenGL 4.3/ES 3.0 ETC2 Texture 圧縮の仕組み (PVRTC2,ASTC)
↓元 (4倍に拡大したものです)


↓DXT1 (S3TC)


↓ETC1 (RGB8)


↓ETC2 (RGB8)


結果はエンコーダーの能力にも依存します。
おそらくもっと良い圧縮ツールもあると思います。
特に DXT (S3TC) はツールが豊富なので、上の例よりも良い結果に
なるかもしれません。
ETC1 しか使えない Mali-400 等の GPU では、今までテクスチャの
圧縮方法が限られていました。
・RGB8 のみで Alpha がない
・4x2 単位で 1色しか選択できない
ひとつは Alpha が使えないなど機能的な問題ですが、もうひとつは
画質の問題です。上の例のように 4x2 の大きなブロックが生じ、
DXT1 よりも著しく劣化するケースがありました。
結果を見ても、ETC2 ではこの問題が解消されていることがわかります。
・Alpha や 1-2 component などバリエーションが豊富
・DXT のように 4x4 単位で 2色使える mode が追加された
・GPU 間で共通のフォーマットとして使える (ようになるはず、将来は)
(注意: 手元に手頃なサンプル画像がなかっただけで、決して法線圧縮に
利用しているわけではありません。)
関連エントリ
・OpenGL 4.3/ES 3.0 ETC2 Texture 圧縮の仕組み (PVRTC2,ASTC)
2012/08/19
OpenGL 4.3 / OpenGL ES 3.0 ETC2 のエンコード
ARM Mali Developer Center で ETC2 に対応した Texture Compression Tool
が公開されています。
・Mali GPU Texture Compression Tool v4.0
ところが自分の環境 (Windows 7 x64) では画像変換時にエラーとなり
今まで正しく動いていませんでした。
GUI を使わずにコマンドラインで変換すれば動作することがわかりました。
Program Files の install フォルダ↓にパスを通しておきます。
「 ARM\Mali Developer Tools\Mali Texture Compression Tool v4.0.0\bin 」
etcpack.exe を直接実行します。
これで outputdir に ktx 形式でファイルが作られます。
ktx から ppm への逆変換もできます。
ktx 形式は OpenGL 版の dds のようなものです。
OpenGL の GLenum をそのまま用いるため、どんなフォーマットも格納できます。
詳しくは下記エントリ参照。
・Android OpenGL ES 2.0 の圧縮テクスチャ
環境を整えたら実際の変換結果なども比べてみたいと思います。
関連エントリ
・OpenGL 4.3/ES 3.0 ETC2 Texture 圧縮の仕組み (PVRTC2,ASTC)
・Android OpenGL ES 2.0 の圧縮テクスチャ
が公開されています。
・Mali GPU Texture Compression Tool v4.0
ところが自分の環境 (Windows 7 x64) では画像変換時にエラーとなり
今まで正しく動いていませんでした。
GUI を使わずにコマンドラインで変換すれば動作することがわかりました。
Program Files の install フォルダ↓にパスを通しておきます。
「 ARM\Mali Developer Tools\Mali Texture Compression Tool v4.0.0\bin 」
etcpack.exe を直接実行します。
etcpack INPUTFILE.tga outputdir -ktx -c etc2 -s slow
これで outputdir に ktx 形式でファイルが作られます。
ktx から ppm への逆変換もできます。
ktx 形式は OpenGL 版の dds のようなものです。
OpenGL の GLenum をそのまま用いるため、どんなフォーマットも格納できます。
詳しくは下記エントリ参照。
・Android OpenGL ES 2.0 の圧縮テクスチャ
環境を整えたら実際の変換結果なども比べてみたいと思います。
関連エントリ
・OpenGL 4.3/ES 3.0 ETC2 Texture 圧縮の仕組み (PVRTC2,ASTC)
・Android OpenGL ES 2.0 の圧縮テクスチャ
OpenGL ES 3.0 の API はおよそ 100 個増えています。
OpenGL ES 2.0 で 150 弱だった命令数が 250 個になりました。
シェーダーと世代の対応は下記の通り。
OpenGL ES 3.0 は OpenGL 3.x 同様に DirectX10 世代、ShaderModel 4.0 に
相当します。
ハードウエアも API も順当に進化しています。
GPU 毎に機能差は生じますが、下記はそれぞれ最小値の比較です。
Uniform Block (D3D の ConstantBuffer) があるためこのあたりの制限は
さらにゆるくなるはずです。
このあたりを踏まえて wiki もいろいろ更新しました。
・Mobile GPU 毎の機能比較表
・OpenGL のバージョン表など
・テクスチャフォーマットまとめ
・Desktop 向け OpenGL ES 2.0 / OpenGL ES 3.0 実行環境
OpenGL ES 3.0 には GeometryShader がありませんが、これは OpenGL 3.0 も
同様でした。
GeometryShader が追加されたのは OpenGL 3.2 からなので、
同じように OpenGL ES にも今後 GeometryShader が追加拡張される
可能性が高いといえます。
関連ページ
・OpenGL まとめトップ
OpenGL ES 2.0 で 150 弱だった命令数が 250 個になりました。
シェーダーと世代の対応は下記の通り。
OpenGL OpenGL ES DirectX ShaderModel --------------------------------------------------------------- OpenGL 1.x OpenGL ES 1.x Direct3D 7 Fixed Pileline OpenGL 2.x OpenGL ES 2.0 Direct3D 9 Shader Model 3 OpenGL 3.x OpenGL ES 3.0 Direct3D 10 Shader Model 4 OpenGL 4.x -- Direct3D 11 Shader Model 5
OpenGL ES 3.0 は OpenGL 3.x 同様に DirectX10 世代、ShaderModel 4.0 に
相当します。
ハードウエアも API も順当に進化しています。
GPU 毎に機能差は生じますが、下記はそれぞれ最小値の比較です。
GLES 2.0 GLES 3.0 (DirectX) ----------------------------------------------------------------- Vertex Uniform Vectors 128 256 (VSH Constant) Fragment Uniform Vectors 16 224 (PSH Constant) Vertex Attribs 8 16 (VSH Input) Vertex Output Vectors 8 16 (VSH Output) Fragment Input Vectors 8 15 (PSH Input) Draw Buffers 1 4 (PSH Output,MRT) Vertex Texture Image Units 0 16 (Vertex Texture) Texture Image Units 8 16 (Pixel Texture) Combined Texture Image Units 8 32
Uniform Block (D3D の ConstantBuffer) があるためこのあたりの制限は
さらにゆるくなるはずです。
このあたりを踏まえて wiki もいろいろ更新しました。
・Mobile GPU 毎の機能比較表
・OpenGL のバージョン表など
・テクスチャフォーマットまとめ
・Desktop 向け OpenGL ES 2.0 / OpenGL ES 3.0 実行環境
OpenGL ES 3.0 には GeometryShader がありませんが、これは OpenGL 3.0 も
同様でした。
GeometryShader が追加されたのは OpenGL 3.2 からなので、
同じように OpenGL ES にも今後 GeometryShader が追加拡張される
可能性が高いといえます。
関連ページ
・OpenGL まとめトップ
2012/08/17
OpenGL ES 3.0 と OpenGL ES 2.0 の互換性
OpenGL ES 3.0 は OpenGL ES 2.0 との上位互換性が保たれています。
まだ GL 4.3 の GL_ARB_ES3_compatibility と Mali/Adreno Emulator で
試しているだけですが、OpenGL ES 3.0 上で今までのソースコードも
シェーダーも 2.0 のまま変更なしに動いています。
OpenGL ES 3.0 は OpenGL ES 2.0 の実行環境の一つとして利用できそうです。
OpenGL ES 3.0 対応のため EGL の初期化は若干変更しています。
EGL_CONTEXT_CLIENT_VERSION に 3 を渡しています。
Mali のドキュメントでは EGL_OPENGL_ES3_BIT を使っていますが、
定義が見つからなかったため EGL_OPENGL_ES2_BIT のまま使用しました。
GLSL のシェーダーバージョン対応は下記のとおりです。
番号が重なっていないためバージョンの数値だけでもすべて区別可能です。
shader の 1行目に #version が存在しない場合、OpenGL では 1.1 とみなします。
OpenGL ES では 1.0 とみなすことになっています。
バージョン番号の後に profile を指定できるようになったのは 1.5 からです。
OpenGL 4.3 では core, compatibility の他に es も加えられています。
実際に OpenGL 4.3 の context のまま "#version 300 es" を指定しても
コンパイルは通りました。
OpenGL 3.0 以後と以前でシェーダーの書き方が変わります。
OpenGL ES 3.0 も OpenGL 3.x 以降と同じ記述方法になりました。
共存させるために下記のようなヘッダを用いています。
上記以外に texture のサンプリング命令も変わります。
まだ GL 4.3 の GL_ARB_ES3_compatibility と Mali/Adreno Emulator で
試しているだけですが、OpenGL ES 3.0 上で今までのソースコードも
シェーダーも 2.0 のまま変更なしに動いています。
OpenGL ES 3.0 は OpenGL ES 2.0 の実行環境の一つとして利用できそうです。
OpenGL ES 3.0 対応のため EGL の初期化は若干変更しています。
EGL_CONTEXT_CLIENT_VERSION に 3 を渡しています。
Mali のドキュメントでは EGL_OPENGL_ES3_BIT を使っていますが、
定義が見つからなかったため EGL_OPENGL_ES2_BIT のまま使用しました。
GLSL のシェーダーバージョン対応は下記のとおりです。
GLSL shader 内の指定 ----------------------------------------------------------- OpenGL ES 2.0 1.0 #version 100 OpenGL 2.0 1.1 #version 110 OpenGL 2.1 1.2 #version 120 OpenGL 3.0 1.3 #version 130 OpenGL 3.1 1.4 #version 140 OpenGL 3.2 1.5 #version 150 [core/compatibility] OpenGL ES 3.0 3.0 #version 300 es OpenGL 3.3 3.3 #version 330 [core/compatibility] OpenGL 4.0 4.0 #version 400 [core/compatibility] OpenGL 4.1 4.1 #version 410 [core/compatibility] OpenGL 4.2 4.2 #version 420 [core/compatibility] OpenGL 4.3 4.3 #version 430 [core/compatibility/es]
番号が重なっていないためバージョンの数値だけでもすべて区別可能です。
shader の 1行目に #version が存在しない場合、OpenGL では 1.1 とみなします。
OpenGL ES では 1.0 とみなすことになっています。
バージョン番号の後に profile を指定できるようになったのは 1.5 からです。
OpenGL 4.3 では core, compatibility の他に es も加えられています。
実際に OpenGL 4.3 の context のまま "#version 300 es" を指定しても
コンパイルは通りました。
OpenGL 3.0 以後と以前でシェーダーの書き方が変わります。
OpenGL ES 3.0 も OpenGL 3.x 以降と同じ記述方法になりました。
共存させるために下記のようなヘッダを用いています。
// Vertex Shader #ifdef GL_ES # define LOWP lowp # define MEDIUMP mediump # define HIGHP highp precision HIGHP float; #else # define LOWP # define MEDIUMP # define HIGHP #endif #if __VERSION__ < 130 # define IN attribute # define OUT varying #else # define IN in # define OUT out #endif
// Vertex Shader #ifdef GL_ES # define LOWP lowp # define MEDIUMP mediump # define HIGHP highp precision MEDIUMP float; #else # define LOWP # define MEDIUMP # define HIGHP #endif #if __VERSION__ < 130 # define IN varying # define out_FragColor gl_FragColor #else # define IN in out vec4 out_FragColor; #endif
上記以外に texture のサンプリング命令も変わります。
DXT(S3TC/BC) 等、テクスチャ圧縮は基本的に 4x4 pixel 単位で行います。
DXT1~5 (BC1~3) では代表色 2色を RGB565 で格納し、その補間値
3~4 level に対して 2bit の index を持ちます。
これを 4x4 = 16 pixel 分格納します。
16pixel 分の情報が 64bit で収まります。
1pixel あたり 2bit の選択しか出来ないので、4x4 block 単位で最大
4種類のカラー値に変換していることになります。
これはその他のテクスチャ圧縮フォーマットでもほぼ同等の制約です。
色変化の差が激しい画像など、4種類のカラー値で表現しきれない場合は
ブロックノイズとして目立つことになります。
これらの欠点を無くするために、後発のフォーマットでは様々な工夫が
行われています。
高画質化のための方針の一つがモード分岐です。
対象とする画像に応じてブロック単位に圧縮アルゴリズムそのものを
変えてしまうわけです。
特に、以前解説した BC6H/BC7 (OpenGL では BPTC) 圧縮フォーマットに
至っては、8または 14 通りものモード分岐が存在しています。
block 分割 mode を含めれば種類はもっと多くなります。
・Direct3D11/OpenGL 圧縮テクスチャ BPTC, BC6H/BC7 の詳細構造 (1)
・Direct3D11/OpenGL 圧縮テクスチャ BPTC, BC6H/BC7 の詳細構造 (2)
Mobile 系 GPU 、Android 等で使われている ETC1 では、各ブロックをさらに
4x2 のサブブロックに分割します。
各ブロック単位で代表色 1色 + 4段階補間が可能なので、4x4 単位で 8種類の
カラー値を持つことができます。
その代わり色解像度は 4x2 ブロック単位となるため、元画像よりもおよそ
1/8 に低下します。分割方向は block 単位で縦横選べますが、YUV のように
色情報を 4x2 block で共有しているようなものです。
そのため色変化が激しい画像では 4x2block の大きなノイズが生じます。
特にはっきりとした 2色の境界線では ETC1 の劣化が目立ちます。
DXT1 の方がずっと綺麗に出ます。 (2012/08/23追記 実例を載せました)
OpenGL ES 3.0 ではこれらの欠点を克服するために ETC2 が採用されました。
● ETC2 の改善点
(1) ETC1 の block ノイズが出やすいケースを軽減、高画質化
(2) DXT5/3DC-X/3DC-XY (BC3/BC4/BC5) のようなフォーマットバリエーションの追加
(1) 高画質化
ETC1 に対するモード分岐の追加です。
もともとカラー値には 2通りの格納方法がありましたが合計 5 mode 分岐に
増えました。
ETC2 の特徴の一つが ETC1 の上位互換で、bit フォーマットは完全に
互換性があります。
ETC1 の差分 mode のオーバーフローを利用して、存在し得ない bit 並び
になたっときに ETC2 とみなします。
ETC1 の上 2つは 4x2 サブブロック分割があり、分割方向を選ぶことができます。
ETC2 の T-Mode/H-Mode はサブブロック分割がありません。
そのため 4x4 block 内で 4値の選択となります。
ETC2 の最後の Planar は 4x4 block で 3色を直に格納します。
index がなく単純なグラデーションのみとなります。
ポリゴンの頂点カラーをグーロー補間するような感じです。
まだ実際に画像で試していませんが、サブブロック分割が無くなったため
斜め線など 2色の境界は表現できるようになっているようです。
(2) フォーマットバリエーションの追加
ETC1 は RGB しか格納できず alpha カラー値が含まれる場合 GPU
固有の圧縮フォーマットを用いる必要がありました。
ETC2 は 単チャンネル圧縮フォーマット EAC との組み合わせで DXT5(BC3)
のような使い方ができます。
DXT1 は Alpha 1bit のあり無しを 4x4 block 単位で選ぶことができました。
ETC2 では別フォーマット扱いとなります。
ETC1 互換モードの mode 選択 bit を流用するため ETC1 時に 1 mode 減ります。
EAC は BC4/5 同様 pixel あたり 3bit の情報を持ち、8段階選択できます。
ただしベース値を元に 11bit 相当の補間が可能となっているようです。
●その他の新テクスチャフォーマット
・PVRTC2 (PVRTCII)
ETC2 同様に PVRTC とほぼ互換性を保ちつつ、ほとんど使われることが
なかった bit を利用してモード分岐が追加されています。
4 mode あるようですが詳しい構造はわかりません。
すでにツールがあるので比較できますが、従来苦手だった画像でも良くなっており
かなり画質向上が見込めるようです。
・ASTC
ETC2 とそのバリエーションによって OpenGL ES 3.0 では S3TC(DXT) BC1~5
相当をカバーできるようになりました。
ASTC はさらにその上を狙ったもので、HDR対応などを考えるとおそらく
BC6H/BC7 (BPTC) の対抗フォーマットではないかと思います。
圧縮サイズの単位が 128bit なのも BC6H/BC7 (BPTC) と同じです。
block 圧縮のテクスチャフォーマットの方向性の一つがモード分岐の
増加ですが、ASTC はさらにブロックサイズが可変となりました。
PVRTC の 2bpp mode は、通常 4x4 サイズであるブロックを 8x4 に拡張する
ことで実現しています。8x4 = 32block では index が足りないため、
実質 32pixel で 2色の選択になります。
ASTC では可変 block サイズを汎用化しており、mode 分岐だけでなく
より効率の良い 8bpp 未満の圧縮率も同時に実現しているようです。
後ほどもう少し詳しく調べてみたいと思っています。
(2012/08/23追記 :OpenGL 4.3/GLES 3.0 次の圧縮テクスチャ ASTC)
関連エントリ
・Direct3D11/OpenGL 圧縮テクスチャ BPTC, BC6H/BC7 の詳細構造 (2)
・Direct3D11/OpenGL 圧縮テクスチャ BPTC, BC6H/BC7 の詳細構造 (1)
・OpenGL の圧縮テクスチャ (3) BPTC, BC6H/BC7
・OpenGL の圧縮テクスチャ (2) 法線圧縮
・Android OpenGL ES 2.0 の圧縮テクスチャ
DXT1~5 (BC1~3) では代表色 2色を RGB565 で格納し、その補間値
3~4 level に対して 2bit の index を持ちます。
これを 4x4 = 16 pixel 分格納します。
代表色 2色 16bit x 2色 = 32bit Index 2bit x 16pixel = 32bit
16pixel 分の情報が 64bit で収まります。
DXT1(BC1) 64bit 4bpp RGB565 256bit 16bpp RGB888 384bit 24bpp
1pixel あたり 2bit の選択しか出来ないので、4x4 block 単位で最大
4種類のカラー値に変換していることになります。
これはその他のテクスチャ圧縮フォーマットでもほぼ同等の制約です。
色変化の差が激しい画像など、4種類のカラー値で表現しきれない場合は
ブロックノイズとして目立つことになります。
これらの欠点を無くするために、後発のフォーマットでは様々な工夫が
行われています。
高画質化のための方針の一つがモード分岐です。
対象とする画像に応じてブロック単位に圧縮アルゴリズムそのものを
変えてしまうわけです。
特に、以前解説した BC6H/BC7 (OpenGL では BPTC) 圧縮フォーマットに
至っては、8または 14 通りものモード分岐が存在しています。
block 分割 mode を含めれば種類はもっと多くなります。
・Direct3D11/OpenGL 圧縮テクスチャ BPTC, BC6H/BC7 の詳細構造 (1)
・Direct3D11/OpenGL 圧縮テクスチャ BPTC, BC6H/BC7 の詳細構造 (2)
Mobile 系 GPU 、Android 等で使われている ETC1 では、各ブロックをさらに
4x2 のサブブロックに分割します。
各ブロック単位で代表色 1色 + 4段階補間が可能なので、4x4 単位で 8種類の
カラー値を持つことができます。
その代わり色解像度は 4x2 ブロック単位となるため、元画像よりもおよそ
1/8 に低下します。分割方向は block 単位で縦横選べますが、YUV のように
色情報を 4x2 block で共有しているようなものです。
そのため色変化が激しい画像では 4x2block の大きなノイズが生じます。
特にはっきりとした 2色の境界線では ETC1 の劣化が目立ちます。
DXT1 の方がずっと綺麗に出ます。 (2012/08/23追記 実例を載せました)
OpenGL ES 3.0 ではこれらの欠点を克服するために ETC2 が採用されました。
● ETC2 の改善点
(1) ETC1 の block ノイズが出やすいケースを軽減、高画質化
(2) DXT5/3DC-X/3DC-XY (BC3/BC4/BC5) のようなフォーマットバリエーションの追加
(1) 高画質化
ETC1 に対するモード分岐の追加です。
もともとカラー値には 2通りの格納方法がありましたが合計 5 mode 分岐に
増えました。
ETC2 の特徴の一つが ETC1 の上位互換で、bit フォーマットは完全に
互換性があります。
ETC1 の差分 mode のオーバーフローを利用して、存在し得ない bit 並び
になたっときに ETC2 とみなします。
ETC1 444(x4 LV) + 444(x4 LV) table 3+3 = 30+32= 62bit (4x2 block) ETC1 555(x4 LV) + diff 333(x4 LV) table 3+3 = 30+32= 62bit (4x2 block) ETC2 444(x3 LV) + 444 dist 3 = 27+32= 59bit (T-Mode) ETC2 444(x2 LV) + 444(x2 LV) dist 3 = 27+32= 59bit (H-Mode) ETC2 676 + 676 + 676 = 57bit (Planar)
ETC1 の上 2つは 4x2 サブブロック分割があり、分割方向を選ぶことができます。
ETC2 の T-Mode/H-Mode はサブブロック分割がありません。
そのため 4x4 block 内で 4値の選択となります。
ETC2 の最後の Planar は 4x4 block で 3色を直に格納します。
index がなく単純なグラデーションのみとなります。
ポリゴンの頂点カラーをグーロー補間するような感じです。
まだ実際に画像で試していませんが、サブブロック分割が無くなったため
斜め線など 2色の境界は表現できるようになっているようです。
(2) フォーマットバリエーションの追加
ETC1 は RGB しか格納できず alpha カラー値が含まれる場合 GPU
固有の圧縮フォーマットを用いる必要がありました。
ETC2 は 単チャンネル圧縮フォーマット EAC との組み合わせで DXT5(BC3)
のような使い方ができます。
ETC2 RGB 4bpp DXT1/BC1 ETC2 RGB + Alpha 1bit 4bpp DXT1/BC1 ETC2 RGB + Alpha EAC 8bpp DXT5/BC3 EAC 4bpp 3DC-X/BC4 EAC + EAC 8bpp 3DC-XY/BC5
DXT1 は Alpha 1bit のあり無しを 4x4 block 単位で選ぶことができました。
ETC2 では別フォーマット扱いとなります。
ETC1 互換モードの mode 選択 bit を流用するため ETC1 時に 1 mode 減ります。
EAC は BC4/5 同様 pixel あたり 3bit の情報を持ち、8段階選択できます。
ただしベース値を元に 11bit 相当の補間が可能となっているようです。
●その他の新テクスチャフォーマット
・PVRTC2 (PVRTCII)
ETC2 同様に PVRTC とほぼ互換性を保ちつつ、ほとんど使われることが
なかった bit を利用してモード分岐が追加されています。
4 mode あるようですが詳しい構造はわかりません。
すでにツールがあるので比較できますが、従来苦手だった画像でも良くなっており
かなり画質向上が見込めるようです。
・ASTC
ETC2 とそのバリエーションによって OpenGL ES 3.0 では S3TC(DXT) BC1~5
相当をカバーできるようになりました。
ASTC はさらにその上を狙ったもので、
BC6H/BC7 (BPTC) の対抗フォーマットではないかと思います。
圧縮サイズの単位が 128bit なのも BC6H/BC7 (BPTC) と同じです。
block 圧縮のテクスチャフォーマットの方向性の一つがモード分岐の
増加ですが、ASTC はさらにブロックサイズが可変となりました。
PVRTC の 2bpp mode は、通常 4x4 サイズであるブロックを 8x4 に拡張する
ことで実現しています。8x4 = 32block では index が足りないため、
実質 32pixel で 2色の選択になります。
ASTC では可変 block サイズを汎用化しており、mode 分岐だけでなく
より効率の良い 8bpp 未満の圧縮率も同時に実現しているようです。
後ほどもう少し詳しく調べてみたいと思っています。
(2012/08/23追記 :OpenGL 4.3/GLES 3.0 次の圧縮テクスチャ ASTC)
関連エントリ
・Direct3D11/OpenGL 圧縮テクスチャ BPTC, BC6H/BC7 の詳細構造 (2)
・Direct3D11/OpenGL 圧縮テクスチャ BPTC, BC6H/BC7 の詳細構造 (1)
・OpenGL の圧縮テクスチャ (3) BPTC, BC6H/BC7
・OpenGL の圧縮テクスチャ (2) 法線圧縮
・Android OpenGL ES 2.0 の圧縮テクスチャ
2012/08/13
OpenGL ES 2.0/3.0 Emulator
OpenGL 4.x の GL_ARB_ES2_compatibility を用いる場合 Windows では
WGL との組み合わせになります。
AMD の GPU は OpenGL ES 2.0 driver を提供しており、GL ES2 API を
native に呼び出すことが可能です。
Emulator 系 lib と同じように EGL を利用できるため、互換性を保ちやすくなります。
x64 でも動くので以前から試していますが、より便利な lib (SDK) も提供されていました。
・AMD OpenGL ES SDK
GL4 ES2/3 と Tegra Emu 以外は ABI が同一なので libEGL/libGLESv2 を
取り替えて使うことができます。
Angle Project の新しいバージョンは GL_ANGLE_depth_texture が
追加されており shadow map も使えるようになりました。
・angleproject
Angle を VisualStudio 2010 で x64 向けにビルドすると size_t のキャストで
エラーが出ます。
このエラーは Disable Specific Warnings に 4267 を追加してとりあえず
無視することができます。
Debug 版だと log を出力するため低速です。
利用する場合は必ず Release ビルドにしておきます。
関連エントリ
・Desktop の OpenGL ES 2.0 実行環境
・GeForce/RADEON で OpenGL ES 2.0 を動かす
・OpenGL ES 2.0 Emulator
WGL との組み合わせになります。
AMD の GPU は OpenGL ES 2.0 driver を提供しており、GL ES2 API を
native に呼び出すことが可能です。
Emulator 系 lib と同じように EGL を利用できるため、互換性を保ちやすくなります。
x64 でも動くので以前から試していますが、より便利な lib (SDK) も提供されていました。
・AMD OpenGL ES SDK
2012/08/13現在 GL4 ES2 WGL x86/x64 GL4.4 ES3 WGL x86/x64 AMD ES2 EGL x86/x64 libEGL/libGLESv2 Angle Project ES2 EGL x86/x64 libEGL/libGLESv2 PVR Emu ES2 EGL x86/x64 libEGL/libGLESv2 Adreno Emu ES2 EGL x86 libEGL/libGLESv2 Adreno Emu ES3 EGL x86 libEGL/libGLESv3 Mali Emu ES2 EGL x86 libEGL/libGLESv2 Mali Emu ES3 EGL x86 libEGL/libGLESv2 Tegra Emu ES2 EGL x86 libGLESv20
GL4 ES2/3 と Tegra Emu 以外は ABI が同一なので libEGL/libGLESv2 を
取り替えて使うことができます。
Angle Project の新しいバージョンは GL_ANGLE_depth_texture が
追加されており shadow map も使えるようになりました。
・angleproject
Angle を VisualStudio 2010 で x64 向けにビルドすると size_t のキャストで
エラーが出ます。
このエラーは Disable Specific Warnings に 4267 を追加してとりあえず
無視することができます。
Debug 版だと log を出力するため低速です。
利用する場合は必ず Release ビルドにしておきます。
関連エントリ
・Desktop の OpenGL ES 2.0 実行環境
・GeForce/RADEON で OpenGL ES 2.0 を動かす
・OpenGL ES 2.0 Emulator
2012/08/12
OpenGL 4.3 と GL_ARB_ES3_compatibility
NVIDIA の beta driver 305.53 で OpenGL 4.3 を試してみました。
以下は GL_ARB_ES3_compatibility を走らせた結果です。
すでに ETC2/EAC が利用可能となっていることがわかります。
ちなみに 305.53 の OpenGL 4.3 でも ETC2/EAC は有効です。
ETC2 は ETC1 と上位互換なので、Desktop GPU でも ETC1 による描画が
可能となります。
ETC1 は 4x2 pixel あたり 1色しか使えませんでしたが、
ETC2 では DXT 同様 4x4 で 2色使えるよう拡張されています。
単純なグラデーション限定ですが独立した 3色の指定も可能です。
EAC との組み合わせでほぼ DXT1/DXT5/3DC の代用が可能なので、
今後は共通の圧縮テクスチャフォーマットとして ETC2 が使われて
いくのかも知れません。
より詳細な extension はこちらに追記しました。
・Mobile GPU の OpenGL Extension
・Desktop GPU の OpenGL Extension
GLSL の version は、OpenGL と OpenGL ES で見事に重ならないように
なっています。
OpenGL ES 3.0 Emulator も出ています。
・Mali Developer Center: OpenGL ES 3.0 Emulator
・QDevNet : Mobile Gaming & Graphics Optimization (Adreno™)
Adreno は ETC2 がありませんでした。
以下は GL_ARB_ES3_compatibility を走らせた結果です。
すでに ETC2/EAC が利用可能となっていることがわかります。
GL_VERSION: OpenGL ES 3.0 305.53 GL_RENDERER: GeForce GTX 560 Ti/PCIe/SSE2 GL_VENDOR: NVIDIA Corporation GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.00 TextureFormat 23 tc[00]=83f0 GL_COMPRESSED_RGB_S3TC_DXT1_EXT tc[01]=83f2 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT tc[02]=83f3 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT tc[03]=8b90 GL_PALETTE4_RGB8 tc[04]=8b91 GL_PALETTE4_RGBA8 tc[05]=8b92 GL_PALETTE4_R5_G6_B5 tc[06]=8b93 GL_PALETTE4_RGBA4 tc[07]=8b94 GL_PALETTE4_RGB5_A1 tc[08]=8b95 GL_PALETTE8_RGB8 tc[09]=8b96 GL_PALETTE8_RGBA8 tc[10]=8b97 GL_PALETTE8_R5_G6_B5 tc[11]=8b98 GL_PALETTE8_RGBA4 tc[12]=8b99 GL_PALETTE8_RGB5_A1 tc[13]=9274 GL_COMPRESSED_RGB8_ETC2 tc[14]=9275 GL_COMPRESSED_SRGB8_ETC2 tc[15]=9276 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 tc[16]=9277 GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 tc[17]=9278 GL_COMPRESSED_RGBA8_ETC2_EAC tc[18]=9279 GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC tc[19]=9270 GL_COMPRESSED_R11_EAC tc[20]=9271 GL_COMPRESSED_SIGNED_R11_EAC tc[21]=9272 GL_COMPRESSED_RG11_EAC tc[22]=9273 GL_COMPRESSED_SIGNED_RG11_EAC
ちなみに 305.53 の OpenGL 4.3 でも ETC2/EAC は有効です。
GL_VERSION: 4.3.0 GL_RENDERER: GeForce GTX 560 Ti/PCIe/SSE2 GL_VENDOR: NVIDIA Corporation GL_SHADING_LANGUAGE_VERSION: 4.30 NVIDIA via Cg compiler pconst=2048 vconst=4096 vin=16 vout=124 ptex=32 vtex=32 combotex=192 maxrender=16384 maxtexsize=16384 cubetexsize=16384 viewdims=16384 blocks ver=14 frag=14 blocksize=65536 combined=84 geometry const=2048 tex=32 block=14 out=1024 outT=1024 comb=231424 tess ctrl const=2048 tex=32 block=14 out=128 outT=4216 in=128 comb=231424 tess eval const=2048 tex=32 block=14 out=128 patch=120 in=128 comb=231424 TextureFormat 23 tc[00]=83f0 GL_COMPRESSED_RGB_S3TC_DXT1_EXT tc[01]=83f2 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT tc[02]=83f3 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT tc[03]=8b90 GL_PALETTE4_RGB8 tc[04]=8b91 GL_PALETTE4_RGBA8 tc[05]=8b92 GL_PALETTE4_R5_G6_B5 tc[06]=8b93 GL_PALETTE4_RGBA4 tc[07]=8b94 GL_PALETTE4_RGB5_A1 tc[08]=8b95 GL_PALETTE8_RGB8 tc[09]=8b96 GL_PALETTE8_RGBA8 tc[10]=8b97 GL_PALETTE8_R5_G6_B5 tc[11]=8b98 GL_PALETTE8_RGBA4 tc[12]=8b99 GL_PALETTE8_RGB5_A1 tc[13]=9274 GL_COMPRESSED_RGB8_ETC2 tc[14]=9275 GL_COMPRESSED_SRGB8_ETC2 tc[15]=9276 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 tc[16]=9277 GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 tc[17]=9278 GL_COMPRESSED_RGBA8_ETC2_EAC tc[18]=9279 GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC tc[19]=9270 GL_COMPRESSED_R11_EAC tc[20]=9271 GL_COMPRESSED_SIGNED_R11_EAC tc[21]=9272 GL_COMPRESSED_RG11_EAC tc[22]=9273 GL_COMPRESSED_SIGNED_RG11_EAC
ETC2 は ETC1 と上位互換なので、Desktop GPU でも ETC1 による描画が
可能となります。
ETC1 は 4x2 pixel あたり 1色しか使えませんでしたが、
ETC2 では DXT 同様 4x4 で 2色使えるよう拡張されています。
単純なグラデーション限定ですが独立した 3色の指定も可能です。
EAC との組み合わせでほぼ DXT1/DXT5/3DC の代用が可能なので、
今後は共通の圧縮テクスチャフォーマットとして ETC2 が使われて
いくのかも知れません。
より詳細な extension はこちらに追記しました。
・Mobile GPU の OpenGL Extension
・Desktop GPU の OpenGL Extension
GLSL の version は、OpenGL と OpenGL ES で見事に重ならないように
なっています。
OpenGL ES 2.0 GLSL ES 1.0 #version 100 (GLSL 1.1+) OpenGL 2.0 GLSL 1.1 #version 110 OpenGL 2.1 GLSL 1.2 #version 120 OpenGL 3.0 GLSL 1.3 #version 130 OpenGL 3.1 GLSL 1.4 #version 140 OpenGL 3.2 GLSL 1.5 #version 150 OpenGL ES 3.0 GLSL ES 3.0 #version 300 es (GLSL 3.3-) OpenGL 3.3 GLSL 3.3 #version 330 OpenGL 4.0 GLSL 4.0 #version 400 OpenGL 4.1 GLSL 4.1 #version 410 OpenGL 4.2 GLSL 4.2 #version 420 OpenGL 4.3 GLSL 4.3 #version 430
OpenGL ES 3.0 Emulator も出ています。
・Mali Developer Center: OpenGL ES 3.0 Emulator
・QDevNet : Mobile Gaming & Graphics Optimization (Adreno™)
GL_VERSION: OpenGL ES 3.0 GL_RENDERER: OpenGL ES Emulator Revision r2p0-00rel0 GL_VENDOR: ARM Ltd. GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.00 pconst=512 vconst=1024 vin=16 vout=31 ptex=32 vtex=32 combotex=192 maxrender=16384 maxtexsize=16384 cubetexsize=16384 viewdims=16384 TextureFormat 10 tc[00]=9270 GL_COMPRESSED_R11_EAC tc[01]=9272 GL_COMPRESSED_RG11_EAC tc[02]=9274 GL_COMPRESSED_RGB8_ETC2 tc[03]=9276 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 tc[04]=9278 GL_COMPRESSED_RGBA8_ETC2_EAC tc[05]=9271 GL_COMPRESSED_SIGNED_R11_EAC tc[06]=9273 GL_COMPRESSED_SIGNED_RG11_EAC tc[07]=9279 GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC tc[08]=9277 GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 tc[09]=9275 GL_COMPRESSED_SRGB8_ETC2
Adreno は ETC2 がありませんでした。
GL_VERSION: OpenGL ES 3.0 Confetti Special Effects Build 01 GL_RENDERER: Qualcomm OpenGL ES 3.0 Emulator GL_VENDOR: Qualcomm GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL 3.00 pconst=224 vconst=256 vin=15 vout=8 ptex=8 vtex=1 combotex=9 maxrender=2048 maxtexsize=1024 cubetexsize=1024 viewdims=2048 TextureFormat 16 tc[00]=8c92 GL_ATC_RGB_AMD tc[01]=8c93 GL_ATC_RGBA_EXPLICIT_ALPHA_AMD tc[02]=87ee GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD tc[03]=87f9 GL_3DC_X_AMD tc[04]=87fa GL_3DC_XY_AMD tc[05]=8d64 GL_ETC1_RGB8_OES tc[06]=8b90 GL_PALETTE4_RGB8 tc[07]=8b91 GL_PALETTE4_RGBA8 tc[08]=8b92 GL_PALETTE4_R5_G6_B5 tc[09]=8b93 GL_PALETTE4_RGBA4 tc[10]=8b94 GL_PALETTE4_RGB5_A1 tc[11]=8b95 GL_PALETTE8_RGB8 tc[12]=8b96 GL_PALETTE8_RGBA8 tc[13]=8b97 GL_PALETTE8_R5_G6_B5 tc[14]=8b98 GL_PALETTE8_RGBA4 tc[15]=8b99 GL_PALETTE8_RGB5_A1