Как хранить флаги состояния в числах с плавающей запятой для GLSL / WebGL - PullRequest
0 голосов
/ 15 марта 2019

Недавно я узнал о хранении логических флагов в целых числах с использованием битовых масок .Мне интересно, как вы можете сделать это для хранения и получения логических флагов в / из JavaScript, а также для хранения и получения флагов в / из GLSL.Это требует битовых масок с плавающей точкой Я думаю, в отличие от целочисленных битовых масок.Таким образом, я могу закодировать в текстуре некоторые флаги состояния в JavaScript, а затем распаковать их в GLSL.Аналогично, если я записываю данные в пиксели в GLSL в качестве флагов состояния, я могу прочитать их в JavaScript.

1 Ответ

1 голос
/ 15 марта 2019

В GLSL ES 3.0 в WebGL2 есть битовые операции, как и в большинстве языков

uint flags = ??;

...

bool flag1 = (flags & 0x1) > 0;
bool flag2 = (flags & 0x2) > 0;
bool flag3 = (flags & 0x4) > 0;

В WebGL1 вы можете изменять значения до некоторого предела

float flags = ??;

bool flag1 = mod(flags, 2.0) > 0.;
bool flag2 = mod(floor(flags / 2.0), 2.0) > 0.;
bool flag3 = mod(floor(flags / 4.0), 2.0) > 0.;

Это должно работать дляпервые 23 бита, если flags - это значение highp и положительное целочисленное значение.

Конечно, это зависит от того, откуда берется flags.Например, если вы сохраняете свои флаги как UNSIGNED_BYTE в текстуре или атрибуте, вы будете извлекать их как 8-битное значение на канал (красный, зеленый, синий, альфа).8 бит меньше 23-битного предела, поэтому, например,

vec4 flags = texture2D(textureWithFlags, someUV) * 255.0;

сейчас flags.r или flags[0] - это первые 8 бит, flags.g - следующие 8 бит и т. Д.

или

attribute vec4 flags;

, где вы устанавливаете атрибут со значениями UNSIGNED_BYTE и normalize = false, тогда точно так же, как и над каждым каналом флагов, ваши 8 битов от исходных данных

ветвление не рекомендуется в GLSL.В общем, если вы хотите сделать 2 или более разных вещи, вместо добавления флагов, пишите или генерируйте шейдеры для каждого варианта.Это то, что делают большинство 3D-движков, включая Unity, Unreal, Three.js и т.д ...

С другой стороны, вместо ветвления, иногда, когда это уместно, вы можете делать такие вещи, как использование step иmix.Например,

vec4 color1 = ??
vec4 color2 = ??
float useColor2 = mod(flags, 2.0);  // will be 0.0 or 1.0
vec4 color = mix(color1, color2, useColor2);

В приведенном выше коде нет разветвлений.

Таким же образом это

vec4 color;
if (x < 100.0)
  color = color1;
} else {
  color = color2;
}

можно перевести на

vec4 color = mix(color1, color2, step(100.0, x));
...