Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
De BC7-indeling is een patrooncompressie-indeling die wordt gebruikt voor hoogwaardige compressie van RGB- en RGBA-gegevens.
Zie BC7 Format Mode Referencevoor informatie over de blokmodi van de BC7-indeling.
Over BC7/DXGI_FORMAT_BC7
BC7 wordt opgegeven door de volgende DXGI_FORMAT opsommingswaarden:
- DXGI_FORMAT_BC7_TYPELESS.
- DXGI_FORMAT_BC7_UNORM.
- DXGI_FORMAT_BC7_UNORM_SRGB.
De BC7-indeling kan worden gebruikt voor Texture2D- (inclusief matrices), Texture3D of TextureCube (inclusief matrices) textuurbronnen. Op dezelfde manier is deze indeling van toepassing op eventuele MIP-kaartoppervlakken die aan deze resources zijn gekoppeld.
BC7 gebruikt een vaste blokgrootte van 16 bytes (128 bits) en een vaste tegelgrootte van 4x4 texels. Net als bij eerdere BC-indelingen worden patroonafbeeldingen groter dan de ondersteunde tegelgrootte (4x4) gecomprimeerd met behulp van meerdere blokken. Deze adresseringsidentiteit is ook van toepassing op driedimensionale afbeeldingen en MIP-kaarten, kubuskaarten en patroonmatrices. Alle afbeeldingstegels moeten dezelfde indeling hebben.
BC7 comprimeert zowel RGB-afbeeldingen met drie kanalen (RGB) als met vier kanalen (RGBA) met vaste punten. Brongegevens zijn doorgaans 8 bits per kleuronderdeel (kanaal), hoewel de indeling in staat is om brongegevens te coderen met hogere bits per kleurcomponent. Alle afbeeldingstegels moeten dezelfde indeling hebben.
De BC7-decoder voert decompressie uit voordat patroonfiltering wordt toegepast.
BC7-decompressiehardware moet bit nauwkeurig zijn; Dat wil gezegd, de hardware moet resultaten retourneren die identiek zijn aan de resultaten die worden geretourneerd door de decoder die in dit document wordt beschreven.
BC7-implementatie
Een BC7-implementatie kan een van de 8 modi opgeven, waarbij de modus die is opgegeven in de minst significante bit van het blok 16 byte (128 bits). De modus wordt gecodeerd door nul of meer bits met een waarde van 0 gevolgd door een 1.
Een BC7-blok kan meerdere eindpuntparen bevatten. Voor de doeleinden van deze documentatie kan de set indexen die overeenkomen met een eindpuntpaar worden aangeduid als een subset. In sommige blokmodi wordt de eindpuntweergave ook gecodeerd in een vorm die , voor de doeleinden van deze documentatie , opnieuw wordt aangeduid als 'RGBP', waarbij de 'P'-bit een gedeelde minst significante bit vertegenwoordigt voor de kleuronderdelen van het eindpunt. Als de eindpuntweergave voor de indeling bijvoorbeeld RGB 5.5.5.1 is, wordt het eindpunt geïnterpreteerd als een RGB 6.6.6-waarde, waarbij de status van de P-bit de minst significante bit van elk onderdeel definieert. Als voor brongegevens met een alfakanaal de weergave voor de indeling RGBAP 5.5.5.5.5.1 is, wordt het eindpunt geïnterpreteerd als RGBA 6.6.6.6.6. Afhankelijk van de blokmodus kunt u de gedeelde minst significante bit opgeven voor beide eindpunten van een subset afzonderlijk (2 P-bits per subset) of gedeeld tussen eindpunten van een subset (1 P-bits per subset).
Voor BC7-blokken die het alfa-onderdeel niet expliciet coderen, bestaat een BC7-blok uit modus-bits, partitie-bits, gecomprimeerde eindpunten, gecomprimeerde indexen en een optionele P-bit. In deze blokken hebben de eindpunten een RGB-weergave en wordt het alfa-onderdeel gedecodeerd als 1.0 voor alle texels in de brongegevens.
Voor BC7-blokken met gecombineerde kleur- en alfaonderdelen bestaat een blok uit modus-bits, gecomprimeerde eindpunten, gecomprimeerde indexen en optionele partitie-bits en een P-bit. In deze blokken worden de eindpuntkleuren uitgedrukt in RGBA-indeling en worden alfacomponentwaarden geïnterpoleerd naast de kleurcomponentwaarden.
Voor BC7-blokken met afzonderlijke kleur- en alfaonderdelen bestaat een blok uit modus-bits, rotatie-bits, gecomprimeerde eindpunten, gecomprimeerde indexen en een optionele indexselectorbit. Deze blokken hebben een effectieve RGB-vector [R, G, B] en een scalaire alfakanaal [A] afzonderlijk gecodeerd.
De volgende tabel bevat de onderdelen van elk bloktype.
| BC7-blok bevat... | modus bits | rotatie-bits | indexselector-bit | partitie-bits | gecomprimeerde eindpunten | P-bit | gecomprimeerde indexen |
|---|---|---|---|---|---|---|---|
| alleen kleuronderdelen | Vereist | N.V.T | N.V.T | Vereist | Vereist | facultatief | Vereist |
| color + alpha combined | Vereist | N.V.T | N.V.T | facultatief | Vereist | facultatief | Vereist |
| kleur en alfa gescheiden | Vereist | Vereist | facultatief | N.V.T | Vereist | N.V.T | Vereist |
BC7 definieert een kleurenpalet op een geschatte lijn tussen twee eindpunten. De moduswaarde bepaalt het aantal interpolatie-eindpuntparen per blok. BC7 slaat één paletindex per texel op.
Voor elke subset van indexen die overeenkomen met een paar eindpunten, lost de encoder de status van één bit van de gecomprimeerde indexgegevens voor die subset op. Dit doet u door een eindpuntvolgorde te kiezen waarmee de index voor de aangewezen 'fix-up'-index de belangrijkste bit kan instellen op 0 en vervolgens één bit per subset kan worden verwijderd. Voor blokmodi met slechts één subset is de fix-up-index altijd index 0.
De bc7-indeling decoderen
De volgende pseudocode geeft een overzicht van de stappen voor het decomprimeren van de pixel op (x,y) gegeven het 16 byte BC7-blok.
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);
}
}
De volgende pseudocode bevat een overzicht van de stappen voor het volledig decoderen van de kleur van eindpunten en alfa-onderdelen voor elke subset met een BC7-blok van 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
}
}
}
Als u elk geïnterpoleerd onderdeel voor elke subset wilt genereren, gebruikt u het volgende algoritme: laat 'c' het onderdeel zijn om te genereren; laat 'e0' dat onderdeel van eindpunt 0 van de subset zijn; en laat 'e1' dat onderdeel van eindpunt 1 van de subset zijn.
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);
}
De volgende pseudocode illustreert hoe indexen en bitaantallen voor kleur- en alfaonderdelen worden geëxtraheerd. Blokken met afzonderlijke kleur en alfa hebben ook twee sets indexgegevens: één voor het vectorkanaal en één voor het scalaire kanaal. Voor modus 4 zijn deze indexen van verschillende breedten (2 of 3 bits) en er is een een-bits selector die aangeeft of de vector- of scalaire gegevens de 3-bits indexen gebruiken. (Het extraheren van het aantal alfa-bits is vergelijkbaar met het extraheren van het aantal kleurbits, maar met inverse gedrag op basis van het 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;
}
Verwante onderwerpen