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 BC6H-indeling is een structuurcompressie-indeling die is ontworpen ter ondersteuning van HDR-kleurruimten (High-Dynamic Range) in brongegevens.
- Over BC6H/DXGI_FORMAT_BC6H
- BC6H-implementatie
- de BC6H-indeling decoderen
- bc6h gecomprimeerde eindpuntindeling
- -extensie voor eindpuntwaarden
- Inversion transformeren voor eindpuntwaarden
- de van kleureindpunten opheffen
- Verwante onderwerpen
Over BC6H/DXGI_FORMAT_BC6H
De BC6H-indeling biedt hoogwaardige compressie voor afbeeldingen die gebruikmaken van drie HDR-kleurkanalen, met een 16-bits waarde voor elk kleurkanaal van de waarde (16:16:16:16). Er is geen ondersteuning voor een alfakanaal.
BC6H wordt opgegeven door de volgende DXGI_FORMAT opsommingswaarden:
- DXGI_FORMAT_BC6H_TYPELESS.
- DXGI_FORMAT_BC6H_UF16. Deze BC6H-indeling maakt geen gebruik van een teken-bit in de 16-bits waarden voor het drijvendekommakleurkanaal.
- DXGI_FORMAT_BC6H_SF16. Deze BC6H-indeling maakt gebruik van een teken-bit in de 16-bits waarden voor het drijvendekommakanaal.
Notitie
De 16-bits drijvendekomma-indeling voor kleurkanalen wordt vaak aangeduid als een 'halve' drijvendekomma-indeling. Deze indeling heeft de volgende bitindeling:
| Formatteren | Bitindeling |
|---|---|
| UF16 (niet-ondertekende float) | 5 exponent bits + 11 mantissa bits |
| SF16 (ondertekende float) | 1 teken bit + 5 exponent bits + 10 mantissa bits |
De BC6H-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.
BC6H 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, MIP-kaarten, kubuskaarten en patroonmatrices. Alle afbeeldingstegels moeten dezelfde indeling hebben.
Enkele belangrijke opmerkingen over de BC6H-indeling:
- BC6H ondersteunt denormalisatie van drijvende komma, maar biedt geen ondersteuning voor INF (oneindig) en NaN (geen getal). De uitzondering is de ondertekende modus van BC6H (DXGI_FORMAT_BC6H_SF16), die ondersteuning biedt voor -INF (negatieve oneindigheid). Houd er rekening mee dat deze ondersteuning voor -INF slechts een artefact van de indeling zelf is en niet specifiek wordt ondersteund door encoders voor deze indeling. In het algemeen moeten ze, wanneer encoders INF-invoergegevens (positief of negatief) of NaN-invoergegevens tegenkomen, deze gegevens converteren naar de maximaal toegestane niet-INF-weergavewaarde en NaN toewijzen aan 0 vóór compressie.
- BC6H biedt geen ondersteuning voor een alfakanaal.
- De BC6H-decoder voert decompressie uit voordat het patroonfiltering uitvoert.
- BC6H-decompressie moet bit nauwkeurig zijn; Dat wil gezegd, de hardware moet resultaten retourneren die identiek zijn aan de decoder die in deze documentatie wordt beschreven.
BC6H-implementatie
Een BC6H-blok bestaat uit modus-bits, gecomprimeerde eindpunten, gecomprimeerde indexen en een optionele partitieindex. Met deze indeling worden 14 verschillende modi opgegeven.
Een eindpuntkleur wordt opgeslagen als een RGB-triplet. BC6H definieert een palet met kleuren op een geschatte lijn over een aantal gedefinieerde kleureindpunten. Afhankelijk van de modus kan een tegel ook worden onderverdeeld in twee regio's of worden behandeld als één regio, waarbij een tegel met twee regio's een afzonderlijke set kleureindpunten voor elke regio heeft. BC6H slaat één paletindex per texel op.
In het geval van twee regio's zijn er 32 mogelijke partities.
De BC6H-indeling decoderen
De pseudocode hieronder toont de stappen om de pixel op (x,y) te decomprimeren op basis van het 16 byte BC6H-blok.
decompress_bc6h(x, y, block)
{
mode = extract_mode(block);
endpoints;
index;
if(mode.type == ONE)
{
endpoints = extract_compressed_endpoints(mode, block);
index = extract_index_ONE(x, y, block);
}
else //mode.type == TWO
{
partition = extract_partition(block);
region = get_region(partition, x, y);
endpoints = extract_compressed_endpoints(mode, region, block);
index = extract_index_TWO(x, y, partition, block);
}
unquantize(endpoints);
color = interpolate(index, endpoints);
finish_unquantize(color);
}
De volgende tabel bevat het aantal bits en waarden voor elk van de 14 mogelijke indelingen voor BC6H-blokken.
| Wijze | Partitieindexen | Verdelen | Kleureindpunten | Modus-bits |
|---|---|---|---|---|
| 1 | 46 bits | 5 bits | 75 bits (10,555, 10,555, 10,555) | 2 bits (00) |
| 2 | 46 bits | 5 bits | 75 bits (7666, 7666, 7666) | 2 bits (01) |
| 3 | 46 bits | 5 bits | 72 bits (11.555, 11.444, 11.444) | 5 bits (00010) |
| 4 | 46 bits | 5 bits | 72 bits (11.444, 11.555, 11.444) | 5 bits (00110) |
| 5 | 46 bits | 5 bits | 72 bits (11.444, 11.444, 11,555) | 5 bits (01010) |
| 6 | 46 bits | 5 bits | 72 bits (9555, 9555, 9555) | 5 bits (01110) |
| 7 | 46 bits | 5 bits | 72 bits (8666, 8555, 8555) | 5 bits (10010) |
| 8 | 46 bits | 5 bits | 72 bits (8555, 8666, 8555) | 5 bits (10110) |
| 9 | 46 bits | 5 bits | 72 bits (8555, 8555, 8666) | 5 bits (11010) |
| 10 | 46 bits | 5 bits | 72 bits (6666, 6666, 6666) | 5 bits (11110) |
| 11 | 63 bits | 0 bits | 60 bits (10.10, 10.10, 10.10) | 5 bits (00011) |
| 12 | 63 bits | 0 bits | 60 bits (11.9, 11.9, 11,9) | 5 bits (00111) |
| 13 | 63 bits | 0 bits | 60 bits (12.8, 12.8, 12.8) | 5 bits (01011) |
| 14 | 63 bits | 0 bits | 60 bits (16.4, 16.4, 16.4) | 5 bits (01111) |
Elke indeling in deze tabel kan uniek worden geïdentificeerd door de modus-bits. De eerste tien modi worden gebruikt voor tegels in twee regio's en het modus-bitveld kan twee of vijf bits lang zijn. Deze blokken bevatten ook velden voor de gecomprimeerde kleureindpunten (72 of 75 bits), de partitie (5 bits) en de partitieindexen (46 bits).
Voor de gecomprimeerde kleureindpunten noteren de waarden in de voorgaande tabel de precisie van de opgeslagen RGB-eindpunten en het aantal bits dat voor elke kleurwaarde wordt gebruikt. In modus 3 wordt bijvoorbeeld het precisieniveau van het kleureindpunt van 11 opgegeven en het aantal bits dat wordt gebruikt om de deltawaarden van de getransformeerde eindpunten op te slaan voor respectievelijk de rode, blauwe en groene kleuren (respectievelijk 5, 4 en 4). Modus 10 maakt geen gebruik van deltacompressie en slaat in plaats daarvan alle vier de kleureindpunten expliciet op.
De laatste vier blokmodi worden gebruikt voor tegels met één regio, waarbij het modusveld 5 bits is. Deze blokken bevatten velden voor de eindpunten (60 bits) en de gecomprimeerde indexen (63 bits). Modus 11 (zoals modus 10) maakt geen gebruik van deltacompressie en slaat in plaats daarvan beide kleureindpunten expliciet op.
Modi 10011, 10111, 11011 en 11111 (niet weergegeven) zijn gereserveerd. Gebruik deze niet in uw encoder. Als de hardware wordt doorgegeven met een van deze modi opgegeven, moet het resulterende gedecomprimeerde blok alle nullen in alle kanalen bevatten, met uitzondering van het alfakanaal.
Voor BC6H moet het alfakanaal altijd 1,0 retourneren, ongeacht de modus.
BC6H-partitieset
Er zijn 32 mogelijke partitiesets voor een tegel met twee regio's en die zijn gedefinieerd in de onderstaande tabel. Elk 4x4-blok vertegenwoordigt één vorm.
In deze tabel met partitiesets is de vetgedrukte en onderstreepte vermelding de locatie van de fix-upindex voor subset 1 (die is opgegeven met een minder bit). De fix-upindex voor subset 0 is altijd index 0, omdat de partitionering altijd zodanig is gerangschikt dat index 0 zich altijd in subset 0 bevindt. Partitievolgorde gaat van linksboven naar rechtsonder, van links naar rechts en vervolgens van boven naar beneden.
Indeling van gecomprimeerde BC6H-eindpunten
In deze tabel ziet u de bitvelden voor de gecomprimeerde eindpunten als een functie van de eindpuntindeling, waarbij elke kolom een codering opgeeft en elke rij een bitveld opgeeft. Deze aanpak neemt 82 bits in beslag voor tegels met twee regio's en 65 bits voor tegels met één regio. Als voorbeeld zijn de eerste 5 bits voor de ene regio [16 4] codering hierboven (met name de meest rechtse kolom) bits m[4:0], de volgende 10 bits zijn bits rw[9:0], enzovoort met de laatste 6 bits met bw[10:15].
De veldnamen in de bovenstaande tabel zijn als volgt gedefinieerd:
| Veld | Veranderlijk |
|---|---|
| m | wijze |
| d | shape-index |
| Rw | endpt[0]. A[0] |
| Rx | endpt[0]. B[0] |
| Ry | endpt[1]. A[0] |
| rz | endpt[1]. B[0] |
| Gw | endpt[0]. A[1] |
| gx | endpt[0]. B[1] |
| Gy | endpt[1]. A[1] |
| gz | endpt[1]. B[1] |
| Bw | endpt[0]. A[2] |
| Bx | endpt[0]. B[2] |
| bij | endpt[1]. A[2] |
| bz | endpt[1]. B[2] |
Endpt[i], waarbij i 0 of 1 is, verwijst respectievelijk naar de 0e of 1e set eindpunten.
Extensie ondertekenen voor eindpuntwaarden
Voor tegels met twee regio's zijn er vier eindpuntwaarden die kunnen worden uitgebreid. Endpt[0]. A is alleen ondertekend als de indeling een ondertekende indeling is; de andere eindpunten zijn alleen ondertekend als het eindpunt is getransformeerd of als de indeling een ondertekende indeling is. De onderstaande code laat het algoritme zien voor het uitbreiden van het teken van eindpuntwaarden in twee regio's.
static void sign_extend_two_region(Pattern &p, IntEndpts endpts[NREGIONS_TWO])
{
for (int i=0; i<NCHANNELS; ++i)
{
if (BC6H::FORMAT == SIGNED_F16)
endpts[0].A[i] = SIGN_EXTEND(endpts[0].A[i], p.chan[i].prec);
if (p.transformed || BC6H::FORMAT == SIGNED_F16)
{
endpts[0].B[i] = SIGN_EXTEND(endpts[0].B[i], p.chan[i].delta[0]);
endpts[1].A[i] = SIGN_EXTEND(endpts[1].A[i], p.chan[i].delta[1]);
endpts[1].B[i] = SIGN_EXTEND(endpts[1].B[i], p.chan[i].delta[2]);
}
}
}
Voor tegels in één regio is het gedrag hetzelfde, alleen wanneer endpt[1] is verwijderd.
static void sign_extend_one_region(Pattern &p, IntEndpts endpts[NREGIONS_ONE])
{
for (int i=0; i<NCHANNELS; ++i)
{
if (BC6H::FORMAT == SIGNED_F16)
endpts[0].A[i] = SIGN_EXTEND(endpts[0].A[i], p.chan[i].prec);
if (p.transformed || BC6H::FORMAT == SIGNED_F16)
endpts[0].B[i] = SIGN_EXTEND(endpts[0].B[i], p.chan[i].delta[0]);
}
}
Inversion transformeren voor eindpuntwaarden
Voor tegels met twee regio's past de transformatie de inverse van de verschilcodering toe, waarbij de basiswaarde wordt toegevoegd aan endpt[0]. Een aan de drie andere vermeldingen voor in totaal 9 extra bewerkingen. In de onderstaande afbeelding wordt de basiswaarde weergegeven als 'A0' en heeft de hoogste drijvendekommaprecisie. 'A1', 'B0' en 'B1' zijn allemaal delta's die worden berekend op basis van de ankerwaarde en deze deltawaarden worden met lagere precisie weergegeven. (A0 komt overeen met endpt[0]. A, B0 komt overeen met endpt[0]. B, A1 komt overeen met endpt[1]. A en B1 komt overeen met endpt[1].B.)
Voor tegels met één regio is er slechts één deltaverschil en dus slechts 3 extra bewerkingen.
De decompressor moet ervoor zorgen dat de resultaten van de inverse transformatie niet de precisie van endpt[0].a overlopen. In het geval van een overloop moeten de waarden die voortvloeien uit de inverse transformatie binnen hetzelfde aantal bits worden verpakt. Als de precisie van A0 'p' bits is, is het transformatie-algoritme:
B0 = (B0 + A0) & ((1 << p) - 1)
Voor ondertekende indelingen moeten de resultaten van de deltaberekening ook worden uitgebreid. Als de tekenuitbreidingsbewerking van oordeel is dat beide tekens worden uitgebreid, waarbij 0 positief is en 1 negatief is, zorgt de tekenuitbreiding van 0 voor de bovenstaande klem. Bovendien moet na de klem erboven slechts een waarde van 1 (negatief) worden uitgeschoven.
Het aantal kleureindpunten opheffen
Gezien de niet-gecomprimeerde eindpunten, is de volgende stap het uitvoeren van een eerste niet-kwantisatie van de kleureindpunten. Dit omvat drie stappen:
- Een niet-kwantisatie van de kleurenpalletten
- Interpolatie van de paletten
- Voltooien van de blokkering ongedaan maken
Door het niet-kwantisatieproces te scheiden in twee delen (kleurenpalet unquantization vóór interpolatie en uiteindelijke onquantisatie na interpolatie) vermindert u het aantal vermenigvuldigende bewerkingen dat nodig is in vergelijking met een volledig niet-kwantisatieproces voordat paletinterpolatie wordt uitgevoerd.
De onderstaande code illustreert het proces voor het ophalen van schattingen van de oorspronkelijke 16-bits kleurwaarden en vervolgens het gebruik van de opgegeven gewichtswaarden om 6 extra kleurwaarden toe te voegen aan het palet. Dezelfde bewerking wordt op elk kanaal uitgevoerd.
int aWeight3[] = {0, 9, 18, 27, 37, 46, 55, 64};
int aWeight4[] = {0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64};
// c1, c2: endpoints of a component
void generate_palette_unquantized(UINT8 uNumIndices, int c1, int c2, int prec, UINT16 palette[NINDICES])
{
int* aWeights;
if(uNumIndices == 8)
aWeights = aWeight3;
else // uNumIndices == 16
aWeights = aWeight4;
int a = unquantize(c1, prec);
int b = unquantize(c2, prec);
// interpolate
for(int i = 0; i < uNumIndices; ++i)
palette[i] = finish_unquantize((a * (64 - aWeights[i]) + b * aWeights[i] + 32) >> 6);
}
In het volgende codevoorbeeld ziet u het interpolatieproces, met de volgende waarnemingen:
- Omdat het volledige bereik van kleurwaarden voor de de functie (hieronder) van -32768 tot 65535 is, wordt de interpolator geïmplementeerd met behulp van 17-bits ondertekende rekenkundige tekens.
- Na interpolatie worden de waarden doorgegeven aan de finish_unquantize functie (beschreven in het derde voorbeeld in deze sectie), waarmee de uiteindelijke schaalaanpassing wordt toegepast.
- Alle hardwaredecompressies zijn vereist om bit-nauwkeurige resultaten met deze functies te retourneren.
int unquantize(int comp, int uBitsPerComp)
{
int unq, s = 0;
switch(BC6H::FORMAT)
{
case UNSIGNED_F16:
if(uBitsPerComp >= 15)
unq = comp;
else if(comp == 0)
unq = 0;
else if(comp == ((1 << uBitsPerComp) - 1))
unq = 0xFFFF;
else
unq = ((comp << 16) + 0x8000) >> uBitsPerComp;
break;
case SIGNED_F16:
if(uBitsPerComp >= 16)
unq = comp;
else
{
if(comp < 0)
{
s = 1;
comp = -comp;
}
if(comp == 0)
unq = 0;
else if(comp >= ((1 << (uBitsPerComp - 1)) - 1))
unq = 0x7FFF;
else
unq = ((comp << 15) + 0x4000) >> (uBitsPerComp-1);
if(s)
unq = -unq;
}
break;
}
return unq;
}
finish_unquantize wordt aangeroepen na paletinterpolatie. Met de functie wordt het schalen uitgesteld met 31/32 voor ondertekend, 31/64 voor niet-ondertekend. Dit gedrag is vereist om de uiteindelijke waarde op te halen in een geldig half bereik(-0x7BFF ~ 0x7BFF) nadat de interpolatie van het palet is voltooid om het aantal benodigde vermenigvuldigingen te verminderen. finish_unquantize de uiteindelijke schaalaanpassing toepast en een niet-ondertekende korte waarde retourneert die opnieuw wordt geïnterpreteerd in helft.
unsigned short finish_unquantize(int comp)
{
if(BC6H::FORMAT == UNSIGNED_F16)
{
comp = (comp * 31) >> 6; // scale the magnitude by 31/64
return (unsigned short) comp;
}
else // (BC6H::FORMAT == SIGNED_F16)
{
comp = (comp < 0) ? -(((-comp) * 31) >> 5) : (comp * 31) >> 5; // scale the magnitude by 31/32
int s = 0;
if(comp < 0)
{
s = 0x8000;
comp = -comp;
}
return (unsigned short) (s | comp);
}
}
Verwante onderwerpen