1

将我的位标志发送到片段着色器以便能够 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放在表中([bit as int])

[1]   [2]   [4]    [8]
[16]  [32]  [64]   [128]
[256] [512] [1024] [2048]

因此,当在我的实际表中的每一行中选择所有第一个选项时,我的位标志(选项)的可能值将给我一个值 273。在每一行中,只能选择一个选项。

现在,当我想使用 bitflag 检查 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))

4

2 回答 2

3

由于您要使用不同的代码路径,因此优雅地枚举标志是没有意义的。在 C++ 中,您可以执行跳转函数表之类的操作,但在 GLSL 中您不能这样做(相信我 - 您不想这样做)。所以定期检查:

if (options & (ON | PHOTOREALISTIC)) {  /*do something*/ }

如果您不受 Uber-shader 方法的约束,作为替代方案 - 考虑从 GLSL 对象中实现的单独功能块构建 GLSL 程序。

例如,一个块可以实现常规渲染器,而第二个块则以逼真的方式进行。两者应该具有相同的函数名称,即在主着色器中外部链接并从那里调用。链接 GLSL 程序时,您只附加与所需行为匹配的这些块之一。

于 2011-03-09T16:41:38.077 回答
0

你能用这个吗?

if ((options & (PHOTOREALISTIC | ON)) == (PHOTOREALISTIC | ON))
于 2011-03-09T15:31:06.430 回答