Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Затык с упаковкой данных. (Opengl / glsl)

Затык с упаковкой данных. (Opengl / glsl)

Advanced: Тема повышенной сложности или важная.
Страницы: 1 2 3 Следующая »
vindastПостоялецwww6 ноя. 20180:51#0
Пытаюсь упаковать два флоата [0.0f, 1.0f] в один канал текстуры rgb8 / uchar, пожав их до 4-х бит на штуку. Текстура - rt.

Код код упаковки / распаковки:

//упаковка
vec3 puck(vec3 target)
{
  float x;

  uint a = uint((target.y * 16.0f)); //перевод y в диапозон 0..15 (4 бита), наверное лучше округлить 
  uint b = uint((target.z * 16.0f)); //перевод z в диапозон 0..15 (4 бита)

  //а смещается на 4 бита влево
  a = (a << 4) & uint(0x000000f0); //& uint(0x000000f0) тут в принципе, лишний. 

  //тут получается некое целое число от 0 до 255
  uint c = a | b;

  //X - без изменений, z пустой, с / 256.0f что бы попасть в диапазон 0.0f..1.0f
  return vec3(target.x, float(c) / 256.0f, 0.0f); 
}

vec3 unpuck(vec3 target)
{
  //получаю число от 0 до 255
  uint x = uint(target.y * 256.0f);

  //вторые четре бита числа это а
  uint a = (x & uint(0x000000f0)) >> 4;

  //первые четре бита числа это b
  uint b =  x & uint(0x0000000f);
 
  return vec3(target.x, float(a) / 16.0f, float(b) / 16.0f);
}

Сам код проверил на с++, все работает как ожидается, но без записи в текстуру ( внезапно). Не думаю что дело в текстуре.
Затык в том что на гпу не работает и я не понимаю почему. В логике ошибок не вижу.

Я исхожу из того, что в восьмибитной текстуре цвет имеет 256 градаций от нуля до одного.

Помогите.

Правка: 6 ноя. 2018 1:41

DanilwПользовательwww6 ноя. 20181:32#1
не понимаю что ты делаешь
https://www.khronos.org/opengl/wiki/Pixel_Transfer
у тебя текстура с gl_float? это 4 байт на канал(а не 0..1)

vindastПостоялецwww6 ноя. 20181:33#2

Danilw
> gl_float
vindast
> uchar

vindastПостоялецwww6 ноя. 20182:05#3
upd.
vindast
> uint a = uint((target.y * 16.0f));
Везде должно быть 15 а не 16, но проблему это не решает.
0r@ngEУчастникwww6 ноя. 20182:08#4
А что конкретно не работает? Какие получаются результаты? Не работает запаковка или распаковка?

vindastПостоялецwww6 ноя. 20182:15#6
MrShoor
Там пакуют один флоат в 4 байта. А мне надо два флота в один байт, порезав точность до 4-х бит.
vindastПостоялецwww6 ноя. 20182:18#7
0r@ngE
А вот не пойму.
Я все проверил, не вижу ошибок в логике.
Вот скрин (пилю YCoCg):

Изображение

Слева нет упаковки, справа есть.

Ну и скрин, слева дифуз из текстуры, справа с конвератцией в YCoCg (без сжатия):
Изображение

Правка: 6 ноя. 2018 2:26

MrShoorУчастникwww6 ноя. 20182:19#8
vindast
> порезав точность до 4-х бит.
Зачем? В чем твоя проблема?
vindastПостоялецwww6 ноя. 20182:19#9
MrShoor
> Зачем?
Хочется, вон крузис так делает.
vindastПостоялецwww6 ноя. 20182:20#10
Проблема в том, что не ясно в чем проблема, должно же работать.
vindastПостоялецwww6 ноя. 20182:26#11
Обновленный код:
vec3 puck(vec3 target)
{
  float x;

  uint a = uint(round(target.y * 15.0f));
  uint b = uint(round(target.z * 15.0f));

  a = (a << 4) & uint(0x000000f0);
  b = b & uint(0x0000000f);

  uint c = a | b;

  return vec3(target.x, float(c) / 255.0f, 0.0f);

}


vec3 unpuck(vec3 target)
{
  uint x = uint(round(target.y * 255.0f));

  uint a = uint((x & uint(0x000000f0)) >> 4);
  uint b = uint( x & uint(0x0000000f));
 
  return vec3(target.x, float(a) / 15.0f, float(b) / 15.0f);
}

Но он все равно не работает.
Я точно проверил, что данные, которые поступают, верные.
И я взял на бумажке все пересчитал. Все верно. Я не понимаю ничего. Где-то наверное ошибка в логике, но блин. На с++ все работает ровно так как ожидается.

MrShoorУчастникwww6 ноя. 20182:30#12
vindast
> Хочется, вон крузис так делает.
Глянул еще раз на твои скрины. Ну примерно то, что и хочешь. 16 цветов на канал. Какого качества ты ожидал?

Ну и ошибки конечно у тебя есть, например:
target.y * 16.0f
даст тебе значение в диапазоне [0;16], а это потерявшийся бит.
Правильно будет:
target.y * 15.0f

Далее в делении:
return vec3(target.x, float(c) / 256.0f, 0.0f);
Ты делишь на 256, но 256 впринципе не может быть в c. Там будет максимум 255, а значит и делить надо на 255:
return vec3(target.x, float(c) / 255.0f, 0.0f);

Теперь по распаковке. У тебя:
uint x = uint(target.y * 256.0f);
А умножать надо на 255. И округлять round-ом:
uint x = round(target.y * 255.0f);

И делить соотвественно не на 16:
return vec3(target.x, float(a) / 16.0f, float(b) / 16.0f);
А на 15:
return vec3(target.x, float(a) / 16.0f, float(b) / 16.0f);

Ах, да, еще:
vec3 unpuck(vec3 target)

унпук пишется как unpack

vindastПостоялецwww6 ноя. 20182:41#13


MrShoor
> унпук пишется как unpack
Опять я опазорился.
Я исправил все кроме пука в сообщении выше)

Проблема на первом скрине. Там не просто потеря точности.

MrShoorУчастникwww6 ноя. 20182:49#14
vindast
> Опять я опазорился.
опозорился

> Проблема на первом скрине. Там не просто потеря точности.
Как скажешь. Я в krita смотрел по каналам, и видел проблему точности. Ну кроме вываливающегося синего.
Кстати перед упаковкой советую еще сделать вот так:
target = clamp(target, 0.0, 1.0)

Страницы: 1 2 3 Следующая »

/ Форум / Программирование игр / Графика

2001—2018 © GameDev.ru — Разработка игр