昨日の記事に書いたように 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 が含まれていないことがわかります。
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( memory ); const void* image_data= address_add( memory, sizeof(KTX_Header) + hp->bytesOfKeyValueData ); unsigned int image_size= *reinterpret_cast ( 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; }