OpenGLの中でもAndroidで共通に使える圧縮テクスチャ、ETC1に対応します。
圧縮テクスチャは、画像を圧縮した状態(サイズが小さい)でVRAMに置いておくテクスチャです。
PNG等の圧縮画像フォーマットは展開して元のサイズに戻してVRAMに転送しますが、ETC等の圧縮テクスチャではVRAM上でも小さいままなので、
・VRAMを占有するサイズが小さくなる
・描画時、転送サイズが小さいので高速
というメリットがあります。
そのかわり、
・不可逆圧縮なので、画質が落ちる
・ETC1圧縮テクスチャではαに未対応で、不透明画像のみ
といったデメリットもあります。
Android SDKでは etc1tool({sdkのフォルダ}/tools/etc1tool.exe)というPNG画像をETC1に変換するツールがありますので、そのツールで出力されるPKMフォーマットに対応します。
Texture.cpp
/**********************************
PKM読み込み
引数 data = PKMデータ
**********************************/
void Texture::load_pkm(const u8* data)
{
format = FORMAT_ETC;
width = (u16)(((u16)data[8] << 8) | data[9]);
height = (u16)(((u16)data[10] << 8) | data[11]);
make(data + 0x10);
}
読み込み部分です。
ヘッダから幅と高さを取得して、データをそのまま作成関数に送っています。
"圧縮テクスチャ"というフォーマットのデータであってデータ自体は圧縮されていないので、展開処理は必要ありません。逆にいうと、データ自体にはまだ圧縮の余地があるということになります。サンプルでは assetsのzip圧縮に任せちゃっていますが。
/*****************************************
作成
引数 data = テクスチャデータ
*****************************************/
void Texture::make(const u8* data)
{
clear();
glGenTextures(1, &texture); // テクスチャオブジェクト作成
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
switch ( format ) {
case FORMAT_RGBA :
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
break;
case FORMAT_RGB :
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
break;
case FORMAT_ETC :
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, width, height, 0, width*height/2, data);
break;
default :
assert(FALSE);
break;
}
}
テクスチャ作成部分です。
画像転送が glTexImage2Dから glCompressedTexImage2Dに代わり、フォーマットに GL_ETC1_RGB8_OESを指定しています。
あとは、読み込み部分でPNGとPKMに分けたり、キャッシュのサイズ計算でPKMに対応したりと細かな変更はありますが、ソースは省略します。
見た目はたいして変わらないので、スクリーンショットも省略していますが、
※ビー玉の画像は
「かわいいフリー素材集 いらすとや」から使わせていただいています。どうもありがとうございます。
プロジェクト一式は、
こちらから。
セコメントをする