昨日の記事に書いたように 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;
}