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

Опитвам се да направя следното в GLSL 2 es:

Като се има предвид брой (например 4) нормализирани var4 променливи (RGBA), намалете тяхната битова дълбочина и опаковайте резултатите в един 0-1 фиксиран var4. Това ще бъде съхранено като 8-битова (на канал) текстура и по-късно разопаковано. Осъзнавам, че това ще доведе до загуба на качество, но това е приемливо.

Така че в този пример:

RGBA 8 бита
-> намален до RGBA 2 бита
-> пакетиран с 3 други RGBA 2 бита 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 нормализирани float a,b,c,d в нормализиран float 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] защо a се опита да имитира изместването на битове, което би направило върху цели числа. Актуализирах отговора си. - 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