2011-01-26 10 views
9

Sto scrivendo uno shader (HLSL) e ho bisogno di comprimere un valore di colore nel formato R32. Ho trovato vari pezzi di codice per l'imballaggio di un float nel formato R8G8B8A8, ma nessuno di essi sembra funzionare al contrario. Mi rivolgo a SM3.0, quindi le operazioni di bit (afaik) non sono un'opzione.Confezione quattro byte in virgola mobile

Per riassumere, ho bisogno di essere in grado di fare questo:

float4 color = ...; // Where color ranges from 0 -> 1 
float packedValue = pack(color); 

qualcuno sa come fare questo?

UPDATE
ho ottenuto un po 'di progressi ... forse ciò contribuirà a chiarire la questione.
La mia soluzione temporanea in quanto tale:

const int PRECISION = 64; 

float4 unpack(float value) 
{ 
    float4 color; 

    color.a = value % PRECISION; 
    value = floor(value/PRECISION); 

    color.b = value % PRECISION; 
    value = floor(value/PRECISION); 

    color.g = value % PRECISION; 
    value = floor(value/PRECISION); 

    color.r = value; 

    return color/(PRECISION - 1); 
} 

float pack(float4 color) 
{ 
    int4 iVal = floor(color * (PRECISION - 1)); 

    float output = 0; 

    output += iVal.r * PRECISION * PRECISION * PRECISION; 
    output += iVal.g * PRECISION * PRECISION; 
    output += iVal.b * PRECISION; 
    output += iVal.a; 

    return output; 
} 

Sono fondamentalmente ... finta Sto usando tipi interi: s
Attraverso indovinare e verificare, 64 era il numero più alto ho potuto usare, pur mantenendo un intervallo [0 ... 1]. Sfortunatamente, questo significa anche che sto perdendo un po 'di precisione - 6 bit invece di 8.

+2

Alla fine verrà richiesto, quindi è meglio farla finita :) perché devi usare R32 invece di un formato intero? – eodabash

+0

Heh ... sapevo che stava arrivando, ma ancora ... In realtà, sto usando R32G32B32A32, ho solo detto R32 per semplificare. Sto solo cercando di capire come posso spingere quante più informazioni possibili in un singolo obiettivo di rendering. Certo, ho ancora bisogno di fare alcune misurazioni, ma immagino che spingere tutti i miei dati in un singolo obiettivo di rendering sia un po 'più economico rispetto all'utilizzo di quattro tramite MRT. – YellPika

+0

Non vedo l'ora di vedere quali risposte le persone possono trovare per questa domanda. – Olhovsky

risposta

1

Date un'occhiata a: http://diaryofagraphicsprogrammer.blogspot.com/2009/10/bitmasks-packing-data-into-fp-render.html

La risposta breve è che non è possibile fare un imballaggio senza perdita di 4 carri in 1 galleggiante.

Anche se si trova un modo per imballare 4 galleggianti, memorizzando il loro esponente e significato, il processo di imballaggio e disimballaggio potrebbe essere proibitivo.

+1

Beh, in realtà (e come dice il titolo) sto provando a comprimere quattro byte, non quattro float. Ho visto quel post prima però. Sfortunatamente il codice usa gli operatori di bit - non succederà con SM3.0 ... :( – YellPika

+0

È possibile sostituire i bitshift con multipli. Ad esempio 'x << 16' è la stessa cosa di' x * = 2^16' – Olhovsky

+0

Oh anche se usa le maschere di bit e non è possibile utilizzarli in SM3.0 – Olhovsky

1

Fai come il tuo codice di esempio per 3 componenti per comprimerli in s = significand, e fai exp2 (color.g) (1 + s) per impacchettare l'altro componente nell'esponente. Perderai comunque la precisione, ma non sarà così male come se provassi a mettere tutto nel significato e sembra che tu stia facendo.

Sfortunatamente non c'è modo di evitare di perdere precisione, in quanto ci sono un sacco di valori fluttuanti NaN e Inf che sono entrambi indistinguibili l'uno dall'altro e difficili da lavorare (e forse nemmeno supportati dalla GPU, a seconda di quanti anni è).