GLSL - сжатие/упаковка нескольких цветов 0-1 (var4) в одну переменную var4

Я пытаюсь сделать следующее в GLSL 2 es:

Учитывая количество (например, 4) нормализованных переменных var4 (RGBA), уменьшите их разрядность и упакуйте результаты в один зажатый 0-1 var4. Это будет храниться как 8-битная (на канал) текстура, а затем распаковываться. Я понимаю, что это приведет к потере качества, но это допустимо.

Итак, в этом примере:

8-битная RGBA
-> преобразована в 2-битную RGBA
-> упакована с 3 другими 2-битными RGBA var4s
-> сохранена как одна 8-битная текстура RGBA
-> распакована обратно в 4 x RGBA 2 битовые переменные
-> уменьшены до уменьшенной версии оригинала.

Я понимаю, что не могу выполнять побитовые сдвиги в GLSL, поэтому мне пришлось бы делать какой-то набор умножений, волшебная комбинация которых до сих пор ускользала от меня! Другие говорили об упаковке поплавков в vec4s, но моя проблема немного отличается.

Спасибо!


person Child    schedule 14.05.2015    source источник
comment
Или, может быть, проще сказать, что это просто втиснуть четыре 8-битных канала в пространство одного 8-битного канала.   -  person Child    schedule 14.05.2015
comment
Вы имеете в виду vec4, когда пишете var4?   -  person derhass    schedule 15.05.2015
comment
Ага, глупая ошибка. Я имел в виду vec4   -  person Child    schedule 18.05.2015


Ответы (1)


Битовый сдвиг может быть представлен умножением (для сдвигов влево) или делением (для сдвигов вправо) со степенью двойки. Вам просто нужно принять во внимание, что числа с плавающей запятой будут строить дробные части, которые обычно сдвигаются «вне» в обычных целочисленных битовых сдвигах.

Таким образом, чтобы упаковать 4 нормализованных числа с плавающей запятой a,b,c,d в нормализованное число с плавающей запятой x, вы можете просто использовать

x = 1.0/255.0 * (floor(a*255.0/64.0)*64.0 + floor(b*255.0/64.0)*16.0 + floor(c*255.0/64.0)*4.0 + floor(d*255.0/64.0));

Распаковка немного сложнее, потому что вы не можете просто замаскировать отдельные биты. Вместо этого вы можете вычесть самые значащие биты по мере их восстановления, например, так:

a = floor(x*255.0/64.0)*64.0/255.0;
x -= a;
b = floor(x*255.0/16.0)*16.0/255.0;
x -= b;
b *= 4.0;
c = floor(x*255.0/4.0)*4.0/255.0;
x -= c;
c *= 16.0;
d = x*255.0 * 64.0 / 255.0; // scan be simplified to just x*64.0
person derhass    schedule 16.05.2015
comment
Спасибо за ответ. Однако я думаю, что что-то здесь немного не так в коде упаковки: если числа с плавающей запятой a, b, c и d нормализуются и выравниваются после деления на 64, они всегда равны 0. Предполагает ли этот код упаковки, что эти переменные находятся в диапазоне 0- 255? - person Child; 18.05.2015
comment
@Child: Вы правы, я имел в виду ненормализованный диапазон [0,255], почему я пытался имитировать сдвиг битов, который можно было бы сделать с целыми числами. Я обновил свой ответ. - person derhass; 18.05.2015
comment
Спасибо, я все равно внес изменения в свой код, и он работает хорошо! Спасибо еще раз. - person Child; 19.05.2015
comment
Я думаю, что все еще может быть что-то не так с кодом распаковки - рассчитанные значения находятся в диапазоне 0-0,75, а не 0-1. Если мы возьмем, например, a - если x имеет значение 1,0, мы получим a=0,75 из первой строки. Я не думаю, что это имеет значение, так как это достаточно легко исправить, но я упоминаю об этом для интереса и помощи всем, кто использует код. - person Child; 20.05.2015