将我的位标志发送到片段着色器以使其能够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程序时,您仅附加了与所需行为匹配的这些块之一。

10-06 13:36