Подтвердить что ты не робот

Упаковка float в vec4 - как работает этот код?

Я пытаюсь изучить теневое отображение в WebGL. Я вижу тот же фрагмент кода шейдера, который копируется в различных библиотеках и примерах, которые достигают этого. Однако нигде я не нашел объяснения, как это работает.

Идея состоит в том, чтобы сохранить значение глубины (один поплавок) в цветовой буфер (vec4). Существует функция пакета, которая сохраняет float в vec4 и распаковывает функцию, которая извлекает float из vec4.

vec4 pack_depth(const in float depth)
{
    const vec4 bit_shift = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);
    const vec4 bit_mask  = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);
    vec4 res = fract(depth * bit_shift);
    res -= res.xxyz * bit_mask;
    return res;
}

float unpack_depth(const in vec4 rgba_depth)
{
    const vec4 bit_shift = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);
    float depth = dot(rgba_depth, bit_shift);
    return depth;
}

Я бы предположил, что упаковка float в vec4 должна быть тривиальной проблемой, просто скопируйте ее в один из 4 слотов vec4 и оставите других неиспользованными. Вот почему логика смещения битов в вышеприведенном коде меня озадачивает.

Может ли кто-нибудь пролить свет?

4b9b3361

Ответ 1

Он не хранит GLSL float в GLSL vec4. Что он делает, это сохранение значения в vec4, которое при записи в фреймбуфер RGBA8 (32-битное значение) может быть прочитано как vec4, а затем восстановлено в тот же float, который был указан ранее.

Если вы делаете то, что вы предлагаете, просто записывая значение с плавающей запятой в красный канал фреймбуфера, вы получите только 8 бит точности. С помощью этого метода вы получаете все 32 бита для вас.

Ответ 2

В дополнение к приведенному выше ответу вам может быть интересен расширение текстуры с плавающей запятой, описанное здесь:

http://www.khronos.org/registry/webgl/extensions/OES_texture_float/

Обратите внимание, что существуют аппаратные/программные настройки там, где это расширение не существует/не выполняется, но если оно действительно является хорошим расширением. Мой опыт в том, что он тоже быстрый. Если вы используете это, вы можете использовать оставшиеся три канала для хранения другой информации, такой как цвет от проецируемой текстуры.

Ответ 3

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

Как вы, вероятно, выяснили, этот код кодирует нормированное значение float для vec4. OpenGL ES 2.0 или WebGL (на момент написания) могли бы использовать эти программы pack/unpack для обеспечения 32-битных точных плавающих точек через текстуры RGBA8 (подробнее об этом в спецификации).

Даже с расширением, размещенным Mikael (OES_texture_float), может потребоваться (для целей отладки, например) сбросить полные 32-битные точные нормализованные плавающие точки и, как описано в спецификации readPixels, в настоящее время ограничено следующим

Принимаются только две комбинации формата и типа. Первый - формат RGBA и тип UNSIGNED_BYTE. Второй - формат, выбранный для реализации.