Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
O formato BC7 é um formato de compressão de textura usado para compressão de alta qualidade de dados RGB e RGBA.
- Sobre BC7/DXGI_FORMAT_BC7
- de implementação do BC7
- Decodificando o formato BC7
- Tópicos relacionados
Para obter informações sobre os modos de bloco do formato BC7, consulte de referência do modo de formato BC7.
Sobre BC7/DXGI_FORMAT_BC7
BC7 é especificado pelos seguintes valores de enumeração DXGI_FORMAT:
- DXGI_FORMAT_BC7_TYPELESS.
- DXGI_FORMAT_BC7_UNORM.
- DXGI_FORMAT_BC7_UNORM_SRGB.
O formato BC7 pode ser usado para recursos de textura Texture2D (incluindo matrizes), Texture3D ou TextureCube (incluindo matrizes). Da mesma forma, esse formato se aplica a qualquer superfície de mapa MIP associada a esses recursos.
BC7 usa um tamanho de bloco fixo de 16 bytes (128 bits) e um tamanho de bloco fixo de 4x4 texels. Tal como nos formatos BC anteriores, as imagens de textura maiores do que o tamanho de mosaico suportado (4x4) são comprimidas utilizando vários blocos. Essa identidade de endereçamento também se aplica a imagens tridimensionais e mapas MIP, cubemaps e matrizes de textura. Todos os blocos de imagem devem ter o mesmo formato.
O BC7 comprime imagens de dados de ponto fixo de três canais (RGB) e quatro canais (RGBA). Normalmente, os dados de origem são de 8 bits por componente de cor (canal), embora o formato seja capaz de codificar dados de origem com bits mais altos por componente de cor. Todos os blocos de imagem devem ter o mesmo formato.
O decodificador BC7 executa a descompressão antes que a filtragem de textura seja aplicada.
O hardware de descompressão BC7 deve ser preciso em bits; ou seja, o hardware deve retornar resultados idênticos aos resultados retornados pelo decodificador descrito neste documento.
Implementação BC7
Uma implementação BC7 pode especificar um dos 8 modos, com o modo especificado no bit menos significativo do bloco de 16 bytes (128 bits). O modo é codificado por zero ou mais bits com um valor de 0 seguido por um 1.
Um bloco BC7 pode conter vários pares de pontos finais. Para os fins desta documentação, o conjunto de índices que correspondem a um par de pontos finais pode ser referido como um "subconjunto". Além disso, em alguns modos de bloco, a representação do ponto de extremidade é codificada em um formato que -- novamente, para os fins desta documentação -- deve ser referido como "RGBP", onde o bit "P" representa um bit menos significativo compartilhado para os componentes de cor do ponto de extremidade. Por exemplo, se a representação do ponto de extremidade para o formato for "RGB 5.5.5.1", então o ponto de extremidade será interpretado como um valor RGB 6.6.6, onde o estado do P-bit define o bit menos significativo de cada componente. Da mesma forma, para dados de origem com um canal alfa, se a representação para o formato for "RGBAP 5.5.5.5.1", então o ponto de extremidade é interpretado como RGBA 6.6.6.6. Dependendo do modo de bloco, você pode especificar o bit menos significativo compartilhado para ambos os pontos de extremidade de um subconjunto individualmente (2 P-bits por subconjunto) ou compartilhado entre os pontos de extremidade de um subconjunto (1 P-bit por subconjunto).
Para blocos BC7 que não codificam explicitamente o componente alfa, um bloco BC7 consiste em bits de modo, bits de partição, pontos de extremidade compactados, índices compactados e um P-bit opcional. Nesses blocos, os pontos de extremidade têm uma representação somente RGB e o componente alfa é decodificado como 1.0 para todos os texels nos dados de origem.
Para blocos BC7 que combinaram componentes de cor e alfa, um bloco consiste em bits de modo, pontos de extremidade compactados, índices compactados e bits de partição opcionais e um P-bit. Nesses blocos, as cores do ponto de extremidade são expressas no formato RGBA e os valores dos componentes alfa são interpolados ao lado dos valores dos componentes de cor.
Para blocos BC7 que têm componentes de cor e alfa separados, um bloco consiste em bits de modo, bits de rotação, pontos de extremidade compactados, índices compactados e um bit seletor de índice opcional. Estes blocos têm um vetor RGB efetivo [R, G, B] e um canal alfa escalar [A] codificado separadamente.
A tabela a seguir lista os componentes de cada tipo de bloco.
| O bloco BC7 contém... | bits de modo | bits de rotação | bit seletor de índice | bits de partição | Pontos finais comprimidos | P-bit | índices comprimidos |
|---|---|---|---|---|---|---|---|
| apenas componentes de cor | Necessário | N/A | N/A | Necessário | Necessário | opcional | Necessário |
| cor + alfa combinado | Necessário | N/A | N/A | opcional | Necessário | opcional | Necessário |
| cor e alfa separados | Necessário | Necessário | opcional | N/A | Necessário | N/A | Necessário |
BC7 define uma paleta de cores em uma linha aproximada entre dois pontos de extremidade. O valor do modo determina o número de pares de pontos finais interpolantes por bloco. BC7 armazena um índice de paleta por texel.
Para cada subconjunto de índices que corresponde a um par de pontos de extremidade, o codificador corrige o estado de um bit dos dados de índice compactados para esse subconjunto. Ele faz isso escolhendo uma ordem de ponto final que permite que o índice para o índice "fix-up" designado defina seu bit mais significativo como 0 e que pode ser descartado, salvando um bit por subconjunto. Para modos de bloco com apenas um único subconjunto, o índice de correção é sempre o índice 0.
Decodificando o formato BC7
O pseudocódigo a seguir descreve as etapas para descompactar o pixel em (x,y) dado o bloco BC7 de 16 bytes.
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);
}
}
O pseudocódigo a seguir descreve as etapas para decodificar totalmente a cor do ponto de extremidade e os componentes alfa para cada subconjunto dado um bloco BC7 de 16 bytes.
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
}
}
}
Para gerar cada componente interpolado para cada subconjunto, use o seguinte algoritmo: deixe "c" ser o componente a ser gerado; Seja "e0" o componente do ponto final 0 do subconjunto; e que "e1" seja o componente do ponto final 1 do subconjunto.
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);
}
O pseudocódigo a seguir ilustra como extrair índices e contagens de bits para componentes de cor e alfa. Blocos com cor separada e alfa também têm dois conjuntos de dados de índice: um para o canal vetorial e outro para o canal escalar. Para o Modo 4, esses índices são de larguras diferentes (2 ou 3 bits), e há um seletor de um bit que especifica se os dados vetoriais ou escalares usam os índices de 3 bits. (Extrair a contagem de bits alfa é semelhante a extrair a contagem de bits de cor, mas com comportamento inverso baseado no idxMode bit.)
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;
}
Tópicos relacionados
-
Compressão de blocos de textura no Direct3D 11