2012-03-27 5 views
19

Sto cercando di studiare il mapping shadow in WebGL. Vedo lo stesso pezzo di codice shader copiato in varie librerie ed esempi che raggiungono questo obiettivo. Comunque da nessuna parte ho trovato la spiegazione di come funziona.Confezione fluttuante in vec4: come funziona questo codice?

L'idea è di salvare un valore di profondità (un singolo float) nel buffer dei colori (vec4). Esiste una funzione pack che salva float in vec4 e decomprime la funzione che recupera il float da vec4.

vec4 pack_depth(const in float depth) 
{ 
    const vec4 bit_shift = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0); 
    const vec4 bit_mask = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0); 
    vec4 res = fract(depth * bit_shift); 
    res -= res.xxyz * bit_mask; 
    return res; 
} 

float unpack_depth(const in vec4 rgba_depth) 
{ 
    const vec4 bit_shift = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0); 
    float depth = dot(rgba_depth, bit_shift); 
    return depth; 
} 

avrei immaginato che l'imballaggio di un galleggiante in vec4 dovrebbe essere un problema banale, basta copiarlo in uno dei 4 slot di vec4 e lasciare gli altri non utilizzati. Ecco perché la logica del cambio di bit nel codice di cui sopra mi lascia perplessi.

Qualcuno può far luce?

risposta

12

Non memorizza un GLSL float in un GLSL vec4. Quello che sta facendo è memorizzare un valore in un vec4 che, quando viene scritto su un framebuffer RGBA8 (valore a 32 bit) può essere letto come vec4 e quindi ricostituito nello stesso float precedentemente assegnato.

Se hai fatto ciò che suggerisci, semplicemente scrivendo il valore in virgola mobile sul canale rosso del framebuffer, otterresti solo 8 bit di precisione. Con questo metodo, tutti i 32 bit funzionano per te.

+0

Vedo. Non è stato chiaro per me che il buffer di colore memorizza internamente il valore del colore come 4 numeri interi anche se lo alimentiamo con un vec4. Se è così, allora il codice di cui sopra ha senso. Grazie. – Jayesh

+0

In senso stretto la conversione è un numero a virgola fissa a 32 bit, non un numero a virgola mobile. – Mortennobel

3

In aggiunta alla risposta di cui sopra, si potrebbe essere interessato al prolungamento tessitura virgola mobile descritto qui:

http://www.khronos.org/registry/webgl/extensions/OES_texture_float/

noti che ci sono hardware/software messe a punto fuori là dove questa estensione non esiste/run, ma se lo fa è sicuramente una buona estensione. La mia esperienza è che è anche veloce. Se si utilizza questo, è possibile utilizzare i restanti tre canali per memorizzare altre informazioni, ad esempio il colore da una trama proiettata.

2

Se ti interessano i dettagli nitidi di come funzionano queste routine ti suggerisco di leggere my blog post. Aggiungo alcuni dettagli qui su come funziona quel codice e per risolvere alcuni possibili casi d'uso.

Come probabilmente avete capito, quel codice sta codificando un valore float normalizzato a vec4. OpenGL ES 2.0 o WebGL (al momento della scrittura), potrebbero utilizzare le routine di pack/unpack per fornire punti mobili di precisione a 32 bit tramite le trame RGBA8 (more on this in the spec).

Anche con l'estensione inviato da Mikael (OES_texture_float) potrebbe essere necessario (per il debugging per esempio) per scaricare piena precisione 32 bit normalizzata punti flottanti e come descritto nelle specifiche readPixels è attualmente limitata dal seguente

Sono accettate solo due combinazioni di formato e tipo. Il primo è formato RGBA e digita UNSIGNED_BYTE. Il secondo è un formato scelto per l'implementazione.