декодировать значение rgb в одиночное значение с плавающей запятой без сдвига битов в glsl - PullRequest
6 голосов
/ 01 августа 2011

В настоящее время я занят отложенным затенением в webgl, и мне нужно декодировать 3 целочисленных значения (в диапазоне [0..256] = 256 ^ 3) в один 32-разрядный код с плавающей запятой и кодировать его позже. потому что это для WebGL, это должно быть сделано без побитовых операций. точность не важна для меня (но я думаю, что ее можно достичь).

это то, что у меня есть, но я думаю, что это неправильно из-за точности текстуры, в которой я храню закодированное значение.

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

спасибо ..

Ответы [ 3 ]

20 голосов
/ 23 сентября 2012

Я знаю, что это старый вопрос, но у меня была та же проблема, и я опубликую решение на случай, если кому-то понадобится это в будущем

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

Пока поплавок, упакованный с packColor, не являетсяв диапазоне [0, 1], но в диапазоне [0, 16777215] у вас не должно быть проблем с точностью.Но если вы нормализуете число с плавающей точкой в ​​диапазоне [0,1], у вас возникнут проблемы с точностью!

Обратите внимание, что вы не можете хранить альфа (таким образом), так как плавающие числа highp являются 24-битнымидлинный, а не 32, как обычно используемые.В вершинном шейдере вы можете использовать этот код без проблем (точность по умолчанию - highp), но в фрагментном шейдере вы должны быть уверены, что используете только высокую точность!

2 голосов
/ 01 августа 2011

Как это?

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);
}
0 голосов
/ 28 июля 2015

@ Makers_F: Спасибо за GLSL-код функции unpackColor , но кажется, что компоненты blue и red поменялись местами.

Для меня следующий код работает как шарм:

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