我最近了解了storing boolean flags in integers using bitmasks。我想知道如何执行此操作以将布尔标志存储到JavaScript中或从JavaScript中检索布尔标志,以及将标志存储到GLSL中或从中检索标志。我认为这需要浮点位掩码,而不是整数位掩码。这样,我可以在JavaScript中对某些状态标志进行纹理编码,然后在GLSL中解压缩它们。同样,如果我将数据作为状态标志写入GLSL中的像素,则可以在JavaScript中读取它们。
答案 0 :(得分:1)
在WebGL2的GLSL ES 3.0中,就像大多数语言一样,还有位操作
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.;
只要flags
是一个highp
值并且是一个正整数值,这应该适用于前23位。
当然,这取决于flags
的来源。例如,如果您将标志存储为UNSIGNED_BYTE
在纹理或属性中,则将其作为每个通道的8位值(红色,绿色,蓝色,alpha)拉出。 8位小于23位限制,例如
vec4 flags = texture2D(textureWithFlags, someUV) * 255.0;
现在flags.r
或flags[0]
是前8位,flags.g
是后8位,等等。
或
attribute vec4 flags;
在其中用UNSIGNED_BYTE值设置属性,然后将normalize = false设置为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));