битовые флаги c ++ в шейдерах opengl (glsl) - PullRequest
1 голос
/ 09 марта 2011

Каков наилучший способ отправки моего битового флага во фрагментный шейдер, чтобы можно было использовать if () против него?

У меня есть следующий битовый флаг (enum):

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 в таблице ([бит как int])

[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

и пропустите (в шейдере) остальные опции, которые отключены. Однако в идеальном случае я хотел бы упростить это до того, как это делается на процессоре с использованием битовых флагов. Поэтому в моем шейдере я хотел бы иметь что-то вроде:

if ( (options & PHOTOREALISTIC) & (options & ON)) // true
    // do stuff

Возможно ли достичь чего-то подобного. Может быть, не совсем то же самое, но что-то более элегантное, чем просто "if () - ing" для всех возможных целых чисел, полученных в результате битового флага? (например: if (1 + 16 + 256), if (1 + 16 + 512), ... if (8 + 128 + 2048))

Ответы [ 2 ]

3 голосов
/ 09 марта 2011

Не будет никакого смысла в элегантном перечислении ваших флагов из-за различных путей кода, которые вы хотите использовать. В C ++ вы могли бы сделать что-то вроде таблицы функций перехода, но в GLSL вы не можете этого сделать (и поверьте мне - вы не хотите). Поэтому проверяйте регулярно:

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

В качестве альтернативы, если вы не связаны с подходом Uber-shader - рассмотрите возможность создания программы GLSL из отдельных функциональных блоков, реализованных в объектах GLSL.

Например, один блок может реализовывать обычный рендер, а второй - фотореалистичным способом. Обе функции должны иметь одинаковое имя функции, которое внешне связано в главном шейдере и вызывается оттуда. При связывании программы GLSL вы присоединяете только один из этих блоков, который соответствует желаемому поведению.

0 голосов
/ 09 марта 2011

Вы можете использовать это?

if ((options & (PHOTOREALISTIC | ON)) == (PHOTOREALISTIC | ON))
...