В 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));