简体   繁体   English

如何在GLSL / WebGL的浮点数中存储状态标志

[英]How to store state flags in floating point numbers for GLSL / WebGL

I have recently learned about storing boolean flags in integers using bitmasks . 我最近了解了有关使用位掩码将布尔标志存储为整数的信息 I'm wondering how you can do this to store and retrieve boolean flags to/from JavaScript, and store and retrieve flags to/from GLSL. 我想知道如何执行此操作以将布尔标志存储到JavaScript中或从JavaScript中检索布尔标志,以及将标志存储到GLSL中或从中检索标志。 This requires floating point bitmasks I think, as opposed to integer bitmasks. 我认为这需要浮点位掩码 ,而不是整数位掩码。 This way I can encode in a texture some state flags in JavaScript, and then unpack them in GLSL. 这样,我可以在JavaScript中对某些状态标志进行纹理编码,然后在GLSL中解压缩它们。 Likewise, if I write data to pixels in GLSL as state flags, I can read them out in JavaScript. 同样,如果我将数据作为状态标志写入GLSL中的像素,则可以在JavaScript中读取它们。

In GLSL ES 3.0 in WebGL2 there are bit operations just like most languages 在WebGL2的GLSL ES 3.0中,就像大多数语言一样,也有位操作

uint flags = ??;

...

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

In WebGL1 you can mod out values up to some limit 在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.;

This should work for the first 23 bits as long as flags is a highp value and is an positive integer value. 只要flagshighp值并且是正整数,就应该对前23位有效。

Of course it depends on where flags comes from. 当然,这取决于flags来源。 For example if you store your flags as UNSIGNED_BYTE in a texture or in an attribute then you'd be pulling them out as an 8bit value per channel (red, green, blue, alpha). 例如,如果您在纹理或属性中将标志存储为UNSIGNED_BYTE ,则将其作为每个通道的8位值(红色,绿色,蓝色,alpha)拉出。 8bits is less than the 23 bit limit so for example 8位小于23位限制,例如

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

now flags.r or flags[0] is the first 8 bits, flags.g is the next 8 bits etc. 现在flags.rflags[0]是前8位, flags.g是后8位, flags.g

or 要么

attribute vec4 flags;

where you setup the attribute with UNSIGNED_BYTE values and normalize = false then just like above each channel of flags is your 8 bits from the original data 在其中使用UNSIGNED_BYTE值设置属性并进行normalize = false的设置,就像在每个标志通道上方都是原始数据的8位一样

branching is discouraged in GLSL. GLSL不建议分支。 In general if you want to do 2 or more different things, instead of adding flags, write or generate shaders for each variation. 通常,如果您想做2个或更多不同的事情,而不是添加标志,请为每个变体编写或生成着色器。 This is what most 3D engines do including Unity, Unreal, Three.js, etc... 这是大多数3D引擎所做的工作,包括Unity,Unreal,Three.js等。

On the other hand, rather than branch, sometimes, when appropriate, you can do things like use step and mix . 另一方面,有时可以在适当时执行诸如stepmix类的事情,而不是分支。 For example 例如

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

No branching in the code above. 上面的代码中没有分支。

In the same way this 用同样的方式

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

can be translated to 可以翻译成

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM