BC7 形式は、RGB および RGBA データの高品質な圧縮に使用されるテクスチャ圧縮形式です。
BC7 形式のブロック モードについては、「BC7 フォーマット モード リファレンス を参照してください。
BC7/DXGI_FORMAT_BC7について
BC7 は、次のDXGI_FORMAT列挙値によって指定されます。
- DXGI_FORMAT_BC7_TYPELESS.
- DXGI_FORMAT_BC7_UNORM.
- DXGI_FORMAT_BC7_UNORM_SRGB.
BC7 形式は、Texture2D (配列を含む)、Texture3D、または TextureCube (配列を含む) テクスチャ リソースを するために使用できます。 同様に、この形式は、これらのリソースに関連付けられているすべての MIP マップ サーフェスに適用されます。
BC7 では、16 バイト (128 ビット) の固定ブロック サイズと 4 x 4 テクセルの固定タイル サイズが使用されます。 以前の BC 形式と同様に、サポートされているタイル サイズ (4x4) よりも大きいテクスチャ イメージは、複数のブロックを使用して圧縮されます。 このアドレス指定 ID は、3 次元画像、MIP マップ、キューブマップ、テクスチャ配列にも適用されます。 すべてのイメージ タイルは同じ形式である必要があります。
BC7 は、3 チャネル (RGB) と 4 チャネル (RGBA) の両方の固定小数点データ イメージを圧縮します。 通常、ソース データはカラー コンポーネント (チャネル) ごとに 8 ビットですが、形式はカラー コンポーネントごとに上位ビットのソース データをエンコードできます。 すべてのイメージ タイルは同じ形式である必要があります。
BC7 デコーダーは、テクスチャ フィルタリングが適用される前に展開を実行します。
BC7 展開ハードウェアはビット精度である必要があります。つまり、ハードウェアは、このドキュメントで説明されているデコーダーによって返される結果と同じ結果を返す必要があります。
BC7 の実装
BC7 実装では、8 つのモードのいずれかを指定でき、モードは 16 バイト (128 ビット) ブロックの最上位ビットで指定されます。 モードは、0 以上のビットでエンコードされ、値が 0 の後に 1 が続きます。
BC7 ブロックには、複数のエンドポイント ペアを含めることができます。 このドキュメントでは、エンドポイント ペアに対応するインデックスのセットを "サブセット" と呼ぶことがあります。また、一部のブロック モードでは、エンドポイント表現は、このドキュメントの目的で再び "RGBP" と呼ばれる形式でエンコードされます。ここでも、"P" ビットはエンドポイントのカラー コンポーネントの共有の最下位ビットを表します。 たとえば、形式のエンドポイント表現が "RGB 5.5.5.1" の場合、エンドポイントは RGB 6.6.6 値として解釈され、P ビットの状態によって各コンポーネントの最下位ビットが定義されます。 同様に、アルファ チャネルを持つソース データの場合、形式の表現が "RGBAP 5.5.5.5.1" の場合、エンドポイントは RGBA 6.6.6.6 として解釈されます。 ブロック モードに応じて、サブセットの両方のエンドポイント (サブセットあたり 2 P ビット)、またはサブセットのエンドポイント間で共有される共有最下位ビット (サブセットあたり 1 P ビット) を指定できます。
アルファ コンポーネントを明示的にエンコードしない BC7 ブロックの場合、BC7 ブロックはモード ビット、パーティション ビット、圧縮エンドポイント、圧縮インデックス、およびオプションの P ビットで構成されます。 これらのブロックでは、エンドポイントは RGB のみの表現を持ち、アルファ コンポーネントはソース データ内のすべてのテクセルに対して 1.0 としてデコードされます。
カラーとアルファのコンポーネントを組み合わせた BC7 ブロックの場合、ブロックはモード ビット、圧縮エンドポイント、圧縮インデックス、およびオプションのパーティション ビットと P ビットで構成されます。 これらのブロックでは、エンドポイントの色は RGBA 形式で表され、アルファ コンポーネントの値はカラー コンポーネントの値と共に補間されます。
異なる色とアルファのコンポーネントを持つ BC7 ブロックの場合、ブロックはモード ビット、回転ビット、圧縮エンドポイント、圧縮インデックス、およびオプションのインデックス セレクター ビットで構成されます。 これらのブロックには、有効な RGB ベクトル [R, G, B] とスカラー アルファ チャネル [A] が個別にエンコードされています。
次の表に、各ブロック タイプのコンポーネントを示します。
| BC7 ブロックに含まれる... | モード ビット | 回転ビット | インデックス セレクター ビット | パーティション ビット | 圧縮エンドポイント | P ビット | 圧縮インデックス |
|---|---|---|---|---|---|---|---|
| カラー コンポーネントのみ | 必須 | N/A | N/A | 必須 | 必須 | 随意 | 必須 |
| color + alpha combined | 必須 | N/A | N/A | 随意 | 必須 | 随意 | 必須 |
| 色とアルファが区切られた | 必須 | 必須 | 随意 | N/A | 必須 | N/A | 必須 |
BC7 は、2 つの端点間の近似線上に色のパレットを定義します。 モード値は、ブロックあたりの補間エンドポイント ペアの数を決定します。 BC7 では、テクセルごとに 1 つのパレット インデックスが格納されます。
エンドポイントのペアに対応するインデックスのサブセットごとに、エンコーダーは、そのサブセットの圧縮インデックス データの 1 ビットの状態を修正します。 これを行うには、指定された "修正" インデックスのインデックスで最上位ビットを 0 に設定し、それを破棄してサブセットごとに 1 ビットを保存できるようにするエンドポイントの順序を選択します。 サブセットが 1 つだけのブロック モードの場合、修正インデックスは常にインデックス 0 になります。
BC7 形式のデコード
次の擬似コードは、16 バイトの BC7 ブロックを指定して (x,y) ピクセルを展開する手順の概要を示しています。
decompress_bc7(x, y, block)
{
mode = extract_mode(block);
//decode partition data from explicit partition bits
subset_index = 0;
num_subsets = 1;
if (mode.type == 0 OR == 1 OR == 2 OR == 3 OR == 7)
{
num_subsets = get_num_subsets(mode.type);
partition_set_id = extract_partition_set_id(mode, block);
subset_index = get_partition_index(num_subsets, partition_set_id, x, y);
}
//extract raw, compressed endpoint bits
UINT8 endpoint_array[2 * num_subsets][4] = extract_endpoints(mode, block);
//decode endpoint color and alpha for each subset
fully_decode_endpoints(endpoint_array, mode, block);
//endpoints are now complete.
UINT8 endpoint_start[4] = endpoint_array[2 * subset_index];
UINT8 endpoint_end[4] = endpoint_array[2 * subset_index + 1];
//Determine the palette index for this pixel
alpha_index = get_alpha_index(block, mode, x, y);
alpha_bitcount = get_alpha_bitcount(block, mode);
color_index = get_color_index(block, mode, x, y);
color_bitcount = get_color_bitcount(block, mode);
//determine output
UINT8 output[4];
output.rgb = interpolate(endpoint_start.rgb, endpoint_end.rgb, color_index, color_bitcount);
output.a = interpolate(endpoint_start.a, endpoint_end.a, alpha_index, alpha_bitcount);
if (mode.type == 4 OR == 5)
{
//Decode the 2 color rotation bits as follows:
// 00 – Block format is Scalar(A) Vector(RGB) - no swapping
// 01 – Block format is Scalar(R) Vector(AGB) - swap A and R
// 10 – Block format is Scalar(G) Vector(RAB) - swap A and G
// 11 - Block format is Scalar(B) Vector(RGA) - swap A and B
rotation = extract_rot_bits(mode, block);
output = swap_channels(output, rotation);
}
}
次の擬似コードでは、16 バイトの BC7 ブロックを指定して、各サブセットのエンドポイントカラーとアルファコンポーネントを完全にデコードする手順の概要を示します。
fully_decode_endpoints(endpoint_array, mode, block)
{
//first handle modes that have P-bits
if (mode.type == 0 OR == 1 OR == 3 OR == 6 OR == 7)
{
for each endpoint i
{
//component-wise left-shift
endpoint_array[i].rgba = endpoint_array[i].rgba << 1;
}
//if P-bit is shared
if (mode.type == 1)
{
pbit_zero = extract_pbit_zero(mode, block);
pbit_one = extract_pbit_one(mode, block);
//rgb component-wise insert pbits
endpoint_array[0].rgb |= pbit_zero;
endpoint_array[1].rgb |= pbit_zero;
endpoint_array[2].rgb |= pbit_one;
endpoint_array[3].rgb |= pbit_one;
}
else //unique P-bit per endpoint
{
pbit_array = extract_pbit_array(mode, block);
for each endpoint i
{
endpoint_array[i].rgba |= pbit_array[i];
}
}
}
for each endpoint i
{
// Color_component_precision & alpha_component_precision includes pbit
// left shift endpoint components so that their MSB lies in bit 7
endpoint_array[i].rgb = endpoint_array[i].rgb << (8 - color_component_precision(mode));
endpoint_array[i].a = endpoint_array[i].a << (8 - alpha_component_precision(mode));
// Replicate each component's MSB into the LSBs revealed by the left-shift operation above
endpoint_array[i].rgb = endpoint_array[i].rgb | (endpoint_array[i].rgb >> color_component_precision(mode));
endpoint_array[i].a = endpoint_array[i].a | (endpoint_array[i].a >> alpha_component_precision(mode));
}
//If this mode does not explicitly define the alpha component
//set alpha equal to 1.0
if (mode.type == 0 OR == 1 OR == 2 OR == 3)
{
for each endpoint i
{
endpoint_array[i].a = 255; //i.e. alpha = 1.0f
}
}
}
各サブセットに対して補間された各コンポーネントを生成するには、次のアルゴリズムを使用します。"c" を生成するコンポーネントにしてください。"e0" をサブセットのエンドポイント 0 のコンポーネントにする。次に、"e1" をサブセットのエンドポイント 1 のそのコンポーネントとします。
UINT16 aWeights2[] = {0, 21, 43, 64};
UINT16 aWeights3[] = {0, 9, 18, 27, 37, 46, 55, 64};
UINT16 aWeights4[] = {0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64};
UINT8 interpolate(UINT8 e0, UINT8 e1, UINT8 index, UINT8 indexprecision)
{
if(indexprecision == 2)
return (UINT8) (((64 - aWeights2[index])*UINT16(e0) + aWeights2[index]*UINT16(e1) + 32) >> 6);
else if(indexprecision == 3)
return (UINT8) (((64 - aWeights3[index])*UINT16(e0) + aWeights3[index]*UINT16(e1) + 32) >> 6);
else // indexprecision == 4
return (UINT8) (((64 - aWeights4[index])*UINT16(e0) + aWeights4[index]*UINT16(e1) + 32) >> 6);
}
次の擬似コードは、色とアルファのコンポーネントのインデックスとビット数を抽出する方法を示しています。 色とアルファが異なるブロックには、ベクトル チャネル用とスカラー チャネル用の 2 つのインデックス データ セットもあります。 モード 4 の場合、これらのインデックスは幅が異なり (2 ビットまたは 3 ビット)、ベクター データまたはスカラー データが 3 ビット インデックスを使用するかどうかを指定する 1 ビット セレクターがあります。 (アルファ ビット数の抽出は、カラー ビット数の抽出と似ていますが、idxMode ビットに基づく逆動作を使用します)。
bitcount get_color_bitcount(block, mode)
{
if (mode.type == 0 OR == 1)
return 3;
if (mode.type == 2 OR == 3 OR == 5 OR == 7)
return 2;
if (mode.type == 6)
return 4;
//The only remaining case is Mode 4 with 1-bit index selector
idxMode = extract_idxMode(block);
if (idxMode == 0)
return 2;
else
return 3;
}
関連トピック
-
Direct3D 11 でのテクスチャ ブロック圧縮の