decode rgb value to single float without bit-shift

2019-01-18 14:35发布

问题:

I'm currently busy with deferred shading in webgl and i need to decode 3 integer value's (in the range [0..256] = 256^3) to a single 32 bit float and encode it later. because this is for WebGL it has to be done without bitwise operations. precision is not important for me (But can be achieved i think).

this is what i have but i think this is wrong because of the precision of the texture where i store the encoded value.

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;  }

thanks..

回答1:

I know this is an old question, but i had the same problem, and i'll post the solution in case someone needs it in future

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;
}

As long the float packed with packColor is not in the [0, 1] range but in the [0, 16777215] range, you shouldn't have any problem with precision. But if you normalize the float in the [0,1] range, you'll have precision problems!

Note that you can't store alpha too(in this way), since highp floats are 24-bit long, and not 32 as the ones normally used. In vertex shader you can use this code without problems(default precision is highp), but in the fragment shader you must be sure to only use high precision!



回答2:

Like this?

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:

@Makers_F: Thanks for the GLSL code of unpackColor function, but it seems that blue and red components are reversed.

For me, the following code works like a charm:

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;
}