OpenGL 4.3/ES 3.0 ETC2 Texture 圧縮の仕組み (PVRTC2,ASTC)

DXT(S3TC/BC) 等、テクスチャ圧縮は基本的に 4×4 pixel 単位で行います。
DXT1~5 (BC1~3) では代表色 2色を RGB565 で格納し、その補間値
3~4 level に対して 2bit の index を持ちます。
これを 4×4 = 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 の選択しか出来ないので、4×4 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 では、各ブロックをさらに
4×2 のサブブロックに分割します。
各ブロック単位で代表色 1色 + 4段階補間が可能なので、4×4 単位で 8種類の
カラー値を持つことができます。

その代わり色解像度は 4×2 ブロック単位となるため、元画像よりもおよそ
1/8 に低下します。分割方向は block 単位で縦横選べますが、YUV のように
色情報を 4×2 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つは 4×2 サブブロック分割があり、分割方向を選ぶことができます。
ETC2 の T-Mode/H-Mode はサブブロック分割がありません。
そのため 4×4 block 内で 4値の選択となります。

ETC2 の最後の Planar は 4×4 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 のあり無しを 4×4 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 は、通常 4×4 サイズであるブロックを 8×4 に拡張する
ことで実現しています。8×4 = 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 の圧縮テクスチャ