将我的位标志发送到片段着色器以使其能够if()的最佳方法是什么?
我有以下位标记(枚举):
uint32_t options;
enum Options {
ON = 1 << 0, /// row 1 | enable or disable
OFF = 1 << 1,
DUMMY1 = 1 << 2,
DUMMY2 = 1 << 3,
NONE = 1 << 4, /// row 2 | contours
SILHOUETTE = 1 << 5,
SUGGESTIVE = 1 << 6,
APPARENTRIDGES = 1 << 7,
PHOTOREALISTIC = 1 << 8, /// row 3 | shading
TONE = 1 << 9,
TONESPLASHBACK = 1 << 10,
EXAGGERATED = 1 << 11
};
对应于表[] =将i,j放置在表中([位为整数])
[1] [2] [4] [8]
[16] [32] [64] [128]
[256] [512] [1024] [2048]
因此,当在我的实际表中的每一行中选择所有第一个选项时,我的位标志(选项)的可能值将为我提供273的值。在每一行中,只能选择一个选项。
现在,当我想检查使用位标志在CPU上启用了哪些选项时,我可以简单地执行以下操作(对于选择第一列的示例情况):
if (options & ON) {} // true
if (options & OFF) {} // false
if (options & PHOTOREALISTIC) // true
这个想法是基于位标志中显示的选择,执行着色器的不同部分。为此,我需要执行以下操作:
if( options == 273)
// do enable object, render with no contours and in a photorealistic manner
并跳过(在着色器中)禁用的其余选项。但是,在理想情况下,我想使用位标志将其简化为如何在CPU上完成。因此,在我的着色器中,我想要一些类似的东西:
if ( (options & PHOTOREALISTIC) & (options & ON)) // true
// do stuff
是否有可能实现这样的目标。可能不是完全相同的东西,而是比对位标志产生的所有可能整数简单地“if()-ing”更为优雅的东西? (例如:if(1 + 16 + 256),if(1 + 16 + 512),... if(8 + 128 + 2048))
最佳答案
由于要使用不同的代码路径,因此优雅地枚举标记毫无意义。在C++中,您可以执行跳转功能表之类的操作,但是在GLSL中,您不能做到这一点(相信我-您不想这样做)。因此,请定期检查:
if (options & (ON | PHOTOREALISTIC)) { /*do something*/ }
如果您不受限于Uber-shader方法,则可以选择-考虑从GLSL对象中实现的单独功能块构建GLSL程序。
例如,一个块可以实现常规渲染器,而第二个块可以以逼真的方式实现。两者应具有相同的功能名称,该名称在主着色器中外部链接并从那里进行调用。链接GLSL程序时,您仅附加了与所需行为匹配的这些块之一。