Упаковка с плавающей точкой в ​​vec4 - как работает этот код? - PullRequest
19 голосов
/ 27 марта 2012

Я пытаюсь изучить отображение теней в 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;
}

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

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

Ответы [ 3 ]

12 голосов
/ 27 марта 2012

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

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

3 голосов
/ 27 марта 2012

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

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

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

2 голосов
/ 22 января 2016

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

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

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

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

...