2011-08-01 13 views
6

Jestem obecnie zajęty z odroczonym cieniowaniem w webgl i muszę rozszyfrować 3 wartości całkowite (w zakresie [0..256] = 256^3) do jeden 32-bitowy float i zakodować go później. ponieważ jest to dla WebGL, trzeba to zrobić bez operacji bitowych. precyzja nie jest dla mnie ważna (ale można to osiągnąć, myślę).dekodowanie wartości rgb do pojedynczego float bez przesunięcia bitowego w glsl

To jest to, co mam, ale myślę, że to jest złe ze względu na precyzję tekstury, w której przechowuję zakodowaną wartość.

float packColor(vec3 color) { return (color.r + (color.g*256.) + (color.b*256.*256.))/(256.*256.*256.); } 

vec3 decodeColor(float f) { 
float b = floor(f * 256.0); 
float g = floor(f * 65536.0) - (b*256.); 
float r = (floor(f * 16777216.0) - (b*65536.)) - (g*256.); 
return vec3(r, g, b)/ 256.0;//vec3(r, g, b)/256.0; } 

dzięki ..

+0

myślę, że mieszają się znaczenia słowa „kodują” i „dekodowania” ... – Tara

Odpowiedz

18

wiem, że to jest stare pytanie, ale miałem ten sam problem i będę pisać rozwiązanie w przypadku, gdy ktoś potrzebuje go w przyszłości

float packColor(vec3 color) { 
    return color.r + color.g * 256.0 + color.b * 256.0 * 256.0; 
} 

vec3 unpackColor(float f) { 
    vec3 color; 
    color.b = floor(f/256.0/256.0); 
    color.g = floor((f - color.b * 256.0 * 256.0)/256.0); 
    color.r = floor(f - color.b * 256.0 * 256.0 - color.g * 256.0); 
    // now we have a vec3 with the 3 components in range [0..255]. Let's normalize it! 
    return color/255.0; 
} 

Dopóki pływak wypełnioną packColor nie znajduje się w zakresie [0, 1], ale w zakresie [0, 16777215], nie powinieneś mieć problemu z precyzją. Ale jeśli znormalizujesz pływak w zakresie [0,1], będziesz miał problemy z precyzją!

Należy pamiętać, że nie można również zapisać alfa (w ten sposób), ponieważ zmiennoprzecinkowe highp mają długość 24-bitową, a nie 32, jak zwykle używane. W vertex shaderze możesz używać tego kodu bez problemów (domyślna precyzja to highp), ale w shaderów fragmentów musisz być pewien, że używasz tylko wysokiej precyzji!

+0

Dziękuję za komentarz na temat zasięgu, miałem problemy z precyzją! – Griffork

2

Jak to?

function pack(color) { return color.r + color.g * 256 + color.b * 256 * 256; } 

function unpack(f) { 
    var b = Math.floor(f/(256 * 256)); 
    var g = Math.floor((f - b * 256 * 256)/256); 
    var r = Math.floor(f % 256); 
    return vec3(r, g, b); 
} 
+3

który wygląda jak to działa, ale algorytmicznie Myślę, że pytający chciał tego w GLSL. – andrewmu

0

@Makers_F: Dzięki za kod GLSL z unpackColor funkcję, ale wydaje się, że niebieski i czerwone elementy są odwrócone.

Dla mnie następujący kod działa jak czar:

vec3 unpackColor(float f) 
{ 
    vec3 color; 

    color.r = floor(f/256.0/256.0); 
    color.g = floor((f - color.r * 256.0 * 256.0)/256.0); 
    color.b = floor(f - color.r * 256.0 * 256.0 - color.g * 256.0); 

    // now we have a vec3 with the 3 components in range [0..256]. Let's normalize it! 
    return color/256.0; 
} 
+0

Zauważ, że to nie zadziała dla kodu pakietu PackColor OP - zakłada, że ​​spakowałeś R i B również w odwrotny sposób. – meetar