ETC1圧縮テクスチャ ― 2013/11/13
OpenGLの中でもAndroidで共通に使える圧縮テクスチャ、ETC1に対応します。
圧縮テクスチャは、画像を圧縮した状態(サイズが小さい)でVRAMに置いておくテクスチャです。
PNG等の圧縮画像フォーマットは展開して元のサイズに戻してVRAMに転送しますが、ETC等の圧縮テクスチャではVRAM上でも小さいままなので、
・VRAMを占有するサイズが小さくなる
・描画時、転送サイズが小さいので高速
というメリットがあります。
そのかわり、
・不可逆圧縮なので、画質が落ちる
・ETC1圧縮テクスチャではαに未対応で、不透明画像のみ
といったデメリットもあります。
Android SDKでは etc1tool({sdkのフォルダ}/tools/etc1tool.exe)というPNG画像をETC1に変換するツールがありますので、そのツールで出力されるPKMフォーマットに対応します。
Texture.cpp
読み込み部分です。
ヘッダから幅と高さを取得して、データをそのまま作成関数に送っています。
"圧縮テクスチャ"というフォーマットのデータであってデータ自体は圧縮されていないので、展開処理は必要ありません。逆にいうと、データ自体にはまだ圧縮の余地があるということになります。サンプルでは assetsのzip圧縮に任せちゃっていますが。
テクスチャ作成部分です。
画像転送が glTexImage2Dから glCompressedTexImage2Dに代わり、フォーマットに GL_ETC1_RGB8_OESを指定しています。
あとは、読み込み部分でPNGとPKMに分けたり、キャッシュのサイズ計算でPKMに対応したりと細かな変更はありますが、ソースは省略します。
見た目はたいして変わらないので、スクリーンショットも省略していますが、
※ビー玉の画像は「かわいいフリー素材集 いらすとや」から使わせていただいています。どうもありがとうございます。
プロジェクト一式は、こちらから。
圧縮テクスチャは、画像を圧縮した状態(サイズが小さい)で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に対応したりと細かな変更はありますが、ソースは省略します。
見た目はたいして変わらないので、スクリーンショットも省略していますが、
※ビー玉の画像は「かわいいフリー素材集 いらすとや」から使わせていただいています。どうもありがとうございます。
プロジェクト一式は、こちらから。
最近のコメント