こんにちは。ウェブテクノロジの清水です。
前回の「DirectX 11の圧縮フォーマットBC1~BC7について(前編)」では概要とBC1~BC5 までを解説しました。今回は続きとなるBC6HとBC7について解説いたします。
BC6H
- BC6HはDirectX 11で追加された圧縮テクスチャ形式で、HDR(ハイダイナミックレンジ)のRGB画像データを格納するためのものです。BC6Hのことを単にBC6と呼ぶこともあります。なお、OpenGLでは、BC6Hに相当する圧縮テクスチャ形式はBPTCと呼ばれています。
- BC6Hでは、RGB各16ビットの無圧縮のHDR画像を4×4ピクセル毎に16バイトに圧縮できます。元画像データがRGB各16ビットの無圧縮のHDR画像は4×4ピクセルで96バイトになるので、圧縮率は1/6になります。
- BC6HではRGBのみで、アルファチャンネルはサポートしていません。BC6Hには、表現できる値が符号付きのBC6H_SF16と、符号なしのBC6H_UF16の2つのテクスチャ形式が用意されています(他にBC6H_TYPELESSという「型無し」のBC6Hのテクスチャ形式がありますが、通常は使用しません)。
- BC6Hでは、4×4ピクセル毎に16バイトの圧縮データを使用しますが、この16バイト(128ビット)の圧縮データには、以下の表のような、モードビット、インデックス値、パーティション、エンドポイントの情報がモード別に異なる形式で詰め込まれています。
表1 BC6Hの圧縮データ内の情報(1ブロック)
モード名 | モードビット | インデックス値 | パーティション | エンドポイント | エンドポイントの表現形式 |
---|---|---|---|---|---|
1 | 2ビット | 46ビット | 5ビット | 75ビット | RGB101010 + 差分RGB555 × 3組 |
2 | 2ビット | 46ビット | 5ビット | 75ビット | RGB777 + 差分RGB666 × 3組 |
3 | 5ビット | 46ビット | 5ビット | 72ビット | RGB111111 + 差分RGB544 × 3組 |
4 | 5ビット | 46ビット | 5ビット | 72ビット | RGB111111 + 差分RGB454 × 3組 |
5 | 5ビット | 46ビット | 5ビット | 72ビット | RGB111111 + 差分RGB445 × 3組 |
6 | 5ビット | 46ビット | 5ビット | 72ビット | RGB999 + 差分RGB555 × 3組 |
7 | 5ビット | 46ビット | 5ビット | 72ビット | RGB888 + 差分RGB655 × 3組 |
8 | 5ビット | 46ビット | 5ビット | 72ビット | RGB888 + 差分RGB565 × 3組 |
9 | 5ビット | 46ビット | 5ビット | 72ビット | RGB888 + 差分RGB556 × 3組 |
10 | 5ビット | 46ビット | 5ビット | 72ビット | RGB666 × 4組 |
11 | 5ビット | 63ビット | なし | 60ビット | RGB101010 × 2組 |
12 | 5ビット | 63ビット | なし | 60ビット | RGB111111 + 差分RGB999 |
13 | 5ビット | 63ビット | なし | 60ビット | RGB121212 + 差分RGB888 |
14 | 5ビット | 63ビット | なし | 60ビット | RGB161616 + 差分RGB444 |
モードビット
- BC6Hでサポートされている14種類のモードを区別するためのビットパターンです(モード名の数字の二進数表現とは異なります)。
- 使用できるモードは4×4ピクセルのブロック毎に自由に選べますが、モードを選ぶのはエンコーダ(テクスチャ圧縮を行うプログラム) 側の話で、エンコーダがテクスチャ圧縮の際に自動的に各ブロックに適したモードを決定します。
- このモードビットにはいくつか使用されていないビットパターンがありますが、これらのビットパターンはリザーブとなっていて、エンコーダでの使用が禁止されています。
インデックス値
- インデックス値は4×4ピクセルの各ピクセルがどの色なのかを表した情報です。
- BC6H では、エンドポイントの表現形式からブロックの代表色を決め、その代表色を線形補間して8個または16個のパレットを計算しますが、4×4ピクセルの各ピクセルが、そのパレットの何番の色なのかを示す値がインデックス値です。パレットが8個ならインデックス値は各ピクセル3ビット、パレットが16個なら、インデックス値は各ピクセル4ビットになります。
- インデックス値の総ビット数が3ビット×4×4の48ビットではなく46ビットになっていたり、4ビット×4×4の64ビットではなく63ビットなどの中途半端な数字になっているのは、4×4ピクセルの中で特定の位置(モードやパーティションの値で変わる) のピクセルだけ、インデックス値として割り当てられるビット数が1ビット少なく、選べるパレットが制限されているためです。
パーティション
- BC6Hでは、ブロックノイズが目立つのを防ぐために、4×4ピクセルを2つの領域に分割して、それぞれの領域で代表色を変える事が可能になっています。
- パーティションは、この領域の分割パターンを示す値で、BC6Hではモード1~10のために以下のような32種類の分割パターンが予め固定的に規定されています。モード11~14では領域分割は行われません。
図1 2分割用の分割パターン(クリックで拡大)
エンドポイント
- 4×4ピクセル毎の、そのブロックの代表色となる情報を即値や即値との差分で表したもので、RGBのビット数や即値・差分の組み合わせが異なるものがモード別に用意されています。
- エンドポイントの表現形式が「即値RGB+差分RGB×3組」のモードの場合、エンドポイントとして格納されている情報は即値RGBが1個、差分RGBが3個の計4個で、ブロックの代表色は、
- 即値RGB
- 即値RGB+差分RGB
- 即値RGB+差分RGB
- 即値RGB+差分RGB
の4色となります。この4色から、分割した領域のそれぞれで、サブセットと呼ばれる2色の代表色が割り当てられます。
- BC6Hではエンドポイントの表現形式が複雑になっているため、各ブロックの16バイト(128ビット)の圧縮データの中のエンドポイントの各RGB値の格納位置などもモードによって異なります。
- BC6H の詳細仕様については、マイクロソフト社の開発者向けページ(MSDN BC6H Format)をご覧ください。
BC7
- BC7はDirectX 11で追加された圧縮テクスチャ形式で、BC1~BC3よりも高品質な画像データを格納するためのものです。OpenGLでは、BC7に相当する圧縮テクスチャ形式はBPTCと呼ばれています。
- BC7は無圧縮のRGB画像やRGBA画像を4×4ピクセル毎に16バイトに圧縮します。元画像データが無圧縮のRGB画像の場合は4×4ピクセルで48バイトなので、圧縮率は1/3になります。また、元画像データが無圧縮のRGBA画像の場合は4×4ピクセルで64バイトなので、圧縮率は1/4になります。
- BC7には、表現するRGB値がリニアなBC7_UNORMと、RGB値がsRGBのBC7_UNORM_SRGBの2つのテクスチャ形式が用意されています。この形式の違いはRGB値の色空間の識別のためで、圧縮アルゴリズム自体は共通です(他にBC7_TYPELESSという「型無し」のBC7のテクスチャ形式がありますが、通常は使用しません)。
- BC7では、4×4ピクセル毎に16バイトの圧縮データを使用しますが、この16バイト(128ビット)の圧縮データには、以下の表のような、モードビット、インデックス値、パーティション、交換情報、エンドポイント、付加情報といった情報が詰め込まれています。
表2 BC7の圧縮データ内の情報(1ブロック)
モード名 | モードビット | インデックス値 | パーティション | 交換情報 | エンドポイント | エンドポイントの表現形式 | エンドポイントの表現形式 |
---|---|---|---|---|---|---|---|
0 | 1ビット | 45ビット | 4ビット | なし | 72ビット | 6ビット | RGB444 × 6組 |
1 | 2ビット | 46ビット | 6ビット | なし | 72ビット | 2ビット | RGB666 × 4組 |
2 | 3ビット | 29ビット | 6ビット | なし | 90ビット | なし | RGB555 × 6組 |
3 | 4ビット | 30ビット | 6ビット | なし | 84ビット | 4ビット | RGB777 × 4組 |
4 | 5ビット | 31+47ビット | なし | 2ビット | 42ビット | 1ビット | RGBA5556 × 2組 |
5 | 6ビット | 31+31ビット | なし | 2ビット | 58ビット | なし | RGBA7778 × 2組 |
6 | 7ビット | 63ビット | なし | なし | 56ビット | 2ビット | RGBA7777 × 2組 |
7 | 8ビット | 30ビット | 6ビット | なし | 80ビット | 4ビット | RGBA5555 × 4組 |
モードビット
- BC7でサポートされている8種類のモードを区別するためのビットパターンです。
- モードビットは「接頭符号」になっているため、モードによってビット数が違います。モードビットは、ビット1が出現するまでのビット0の個数がモード名の番号と一致するような符号になっています。たとえば、モード3は0001というビットパターンになっています。
- モードビットで使用されていないビットパターン(8ビットすべて0) はリザーブとなっていて、エンコーダでの使用が禁止されています。使用できるモードは4×4ピクセルのブロック毎に自由に選べますが、モードを選ぶのはエンコーダ(テクスチャ圧縮を行うプログラム) 側の話で、エンコーダがテクスチャ圧縮の際に自動的に各ブロックに適したモードを決定します。
インデックス値
- インデックス値は4×4ピクセルの各ピクセルがどの色なのかを表した情報です。
- BC7では、エンドポイントの表現形式からブロックの代表色を決め、その代表色を線形補間して4個または8個または16個のパレットを計算しますが、4×4ピクセルの各ピクセルが、そのパレットの何番の色なのかを示す値がインデックス値です。
- モード0,1ではインデックス値はピクセル毎に3ビット、モード2,3,5,7ではピクセル毎に2ビット、モード6ではピクセル毎に4ビットです。
- モード5では、RGB 用のインデックス値とアルファ用のインデックス値が独立していて、RGB 用が2ビット、アルファ用が2ビットです。
- モード4では、RGB用とアルファ用のインデックス値が独立していて、付加情報のインデックスセレクタによってRGB用が2ビットでアルファ用が3ビットの場合と、RGB用が3ビットでアルファ用が2ビットの場合があります。
- インデックス値の総ビット数が3ビット×4×4の48ビットではなく45ビットになっていたり、2ビット×4×4の32ビットではなく30ビットなどの中途半端な数字になっているのは、特定の(モードやパーティションで変わる)位置のピクセルだけインデックス値として割り当てられるビット数が1ビット少なく、選べるパレットが制限されているためです。
パーティション
- BC7では、ブロックノイズが目立つのを防ぐため、4×4ピクセルを2つまたは3つの領域に分割して、それぞれの領域で代表色を変える事が可能になっています。
- パーティションは、この領域分割のパターンを示す値で、BC7では以下のような2分割用の64種類の分割パターンと、3分割用の64種類の分割パターンが予め固定的に規定されています(モード0は先頭16種類のみ使用)。
図2 2分割用の分割パターン(クリックで拡大)
※ ○=領域0、●=領域1 (前半の32種類の分割パターンはBC6Hの分割パターンと同じです)
図3 3分割用の分割パターン(クリックで拡大)
※ ○=領域0、◎=領域1、●=領域2
交換情報
- BC7 のモード4とモード5では、インデックス値が2組あり、通常はRGB 用とアルファ用で使い分けますが、その使い分けを変更できる機能があります。この指定をするのが交換情報で、インデックス値を他の成分とは別にしたい成分(補間計算で他の要素から独立させたい成分) を指定する2ビットの値になっています。
表3 BC7の交換情報
交換情報 | 独立成分 | 運動成分 |
---|---|---|
00 | A | R,G,B |
01 | R | G, B, A |
10 | G | R, B, A |
11 | B | R, G, A |
エンドポイント
- 4×4ピクセル毎の、そのブロックの代表色となる色情報を即値で表したもので、モードによって色情報が何組あるのかが決まっています。
- 4×4ピクセルが複数の領域に分割されるモードの場合は、それぞれの領域ごとに代表色が記録されています。この代表色を元に、インデックス値が2ビットなら4個、3ビットなら8個、4ビットなら16個のパレットを直線補間計算で求めると、この計算結果のパレットと各ピクセルのインデックス値から各ピクセルの表現する値が判ります。
表4 補間計算(2ビットのインデックス用)
パレット番号 | 計算式(2ビットのインデックス用) |
---|---|
0 | A |
1 | (A * (64 – 21) + B * 21 + 32) / 64 |
2 | (A * (64 – 43) + B * 43 + 32) / 64 |
3 | B |
表5 補間計算(3ビットのインデックス用)
パレット番号 | 計算式(3ビットのインデックス用) |
---|---|
0 | A |
1 | (A * (64 – 9) + B * 9 + 32) / 64 |
2 | (A * (64 – 18) + B * 18 + 32) / 64 |
3 | (A * (64 – 27) + B * 27 + 32) / 64 |
4 | (A * (64 – 37) + B * 37 + 32) / 64 |
5 | (A * (64 – 46) + B * 46 + 32) / 64 |
6 | (A * (64 – 55) + B * 55 + 32) / 64 |
7 | B |
表6 補間計算(4ビットのインデックス用)
パレット番号 | 計算式(4ビットのインデックス用) |
---|---|
0 | A |
1 | (A * (64 – 4) + B * 4 + 32) / 64 |
2 | (A * (64 – 9) + B * 9 + 32) / 64 |
3 | (A * (64 – 13) + B * 13 + 32) / 64 |
4 | (A * (64 – 17) + B * 17 + 32) / 64 |
5 | (A * (64 – 21) + B * 21 + 32) / 64 |
6 | (A * (64 – 26) + B * 26 + 32) / 64 |
7 | (A * (64 – 30) + B * 30 + 32) / 64 |
8 | (A * (64 – 34) + B * 34 + 32) / 64 |
9 | (A * (64 – 38) + B * 38 + 32) / 64 |
10 | (A * (64 – 43) + B * 43 + 32) / 64 |
11 | (A * (64 – 47) + B * 47 + 32) / 64 |
12 | (A * (64 – 51) + B * 51 + 32) / 64 |
13 | (A * (64 – 55) + B * 55 + 32) / 64 |
14 | (A * (64 – 60) + B * 60 + 32) / 64 |
15 | B |
付加情報
- モード0,1,3,6,7には、エンドポイントのRGB値の精度不足を補うために「Pビット」という付加情報が用意されています。これは、RGBの各ビット数を1ビット増やし、その最下位ビットを1ビットのPビットで表す、というような処理になっていて、表現できる輝度成分の階調数を倍増する効果があります。たとえば、RGB555+Pビットの場合、色の輝度成分の階調に関してはRGB666と同等になります。
- Pビットは、モード0のようにエンドポイントの各RGB値に1個が付く場合と、モード1のようにサブセットに対して1個が付く場合があります。
- モード4には、インデックスセレクタという1ビットの付加情報が用意されています。モード4では2ビットのインデックス値と3ビットのインデックス値が格納されていて、どちらがRGB用でどちらがアルファ用なのかを、このインデックスセレクタで指定するようになっています。
- BC7 の詳細仕様については、マイクロソフト社の開発者向けページ(MSDN BC7 Format)をご覧ください。
まとめ
DirectX 11ではBC1~BC7(BC1、BC2、BC3、BC4、BC5、BC6H、BC7)の圧縮テクスチャが使用できますが、BC1_UNORM~BC3_UNORMに関してはDXT1~DXT5の呼び方が変わったもの程度の理解で問題ないでしょう。
たとえば、マイクロソフト社のツールでも、デフォルト設定ではBC1_UNORM形式は従来の(DirectX 9互換の)DXT1形式で出力されるようになっています。これは、対応ツールが少ないDX10拡張DDSでBC1_UNORM~BC3_UNORMで保存するより、対応ツールが多いDXT1~DXT5互換形式で保存するほうが何かと都合が良いためです。
BC1_UNORM_SRGBなどのsRGB形式に関してはDirectX 9互換形式では保存できないので、DX10拡張DDS で保存するしかありません。
なお、DX10拡張DDSは従来のDirectX 9のDDSファイルとは異なる形式となります。このあたりの都合に関しては使用する3Dエンジンなどにも依存する話なので、プログラマーとデザイナー間で予め使用するファイルフォーマットの調整をしておきましょう。
BC4~BC5についてはRGB画像データ以外の1成分や2成分のデータを扱う場合のフォーマットなので、BC4~BC5が利用可能なデータで、その形式を使うことが指示されていたら使用する、という、どちらかというと消極的な用途になる場合が多いと思います。
BC6はHDR(ハイダイナミックレンジ)のRGB画像専用なので、HDRを使わない場合は利用価値がありませんが、HDRを使う場合は、他のHDR画像用のフォーマットよりも高圧縮率なので、ファイルサイズを抑えたい場合は便利に使えるでしょう。
BC7は、従来ではDXT2~DXT5を使用していたテクスチャを置き換えるのに最適なフォーマットですが、当初(2009年~2011年頃)はマイクロソフト社が提供していた変換ツールが正常に動かなかったり処理が非常に遅かったりと色々と問題があり、BC7形式を利用する際の障害になっていました。しかし、現在はそれもほぼ解決されています。
表7 BC7形式への変換時間と変換後の画質
マイクロソフト社の変換ツール | 変換時間 | 画質 |
---|---|---|
texconvex.exe(2010年版) | 正常に動作しない | |
texconvex.exe(2011年版) | 110秒 | 高 |
texconv.exe(DirectXTex version), CPU使用 | 12秒 | 高 |
texconv.exe(DirectXTex version), GPU使用 | 1秒 | 中 |
* 画像サイズ:256×256ドット
* PC環境:Windows 7(Core i7 2700K + GeForce GTX 650 Ti)
texconv.exe(DirectXTex version)をデフォルトのGPU使用モードで変換した場合と、明示的にCPU使用モードを指定(-nogpuオプション)して変換した場合を比較すると、圧縮結果は同じにはならず、高速なGPU使用モードの方が画質が低くなってしまうようです。おそらく、GPGPU使用モードは画質よりも変換速度を重視して圧縮処理を行っているためだと思いますが、同一の画質で処理速度だけが違う、という訳ではない点には注意が必要です。このため、アプリの開発中は高速なGPU使用モードでBC7への変換を行い、マスター作成など開発の終盤ではCPU使用モードでBC7への変換をやりなおす、などの運用でカバーする必要があるかもしれません。
以上、DirectX系のアプリケーションの開発に携わっている方々の参考になれば幸いです。