有没有办法在GLSL中使用联合?

时间:2016-10-09 01:47:18

标签: glsl shader union

我想知道是否有办法在GLSL中使用联合。我还没有看到任何关于此的文档。如果没有,使用联合是否有一个干净的解决方法。

我基本上想要一些东西。而且这可能是两件事之一,因此我想用一个联合来定义它。

谢谢!

P.S。可能有一些奇怪的铸造技巧可以做到这一点,我不知道,随时建议一个更好的方法。

修改

代码示例(因为union不可用而无法编译):

struct A{
    bool isA;
    float value;
};
struct B{
    bool isA;
    int value;
};

/* union */
union AandB {
    A a;
    B b;
}

void main()
{
    AandB foo;
    if(foo.a.isA)
        /* process on A */

    else
        /* process on B */
}

另外,想象A和B很大,你不想复制它们。

编辑2:

这里有更多信息,希望有所帮助:

这些数据来自"外部"并且是特定于顶点的。必须根据类型(A或B)区别对待。他们可能是从VBO访问的。

2 个答案:

答案 0 :(得分:1)

根据GLSL specification,关键字union 保留供将来使用,确实会导致编译错误。

GLSL支持一种方法,因为它们鼓励你使用简单的数据结构(没有邪恶的指针分配或奇怪的转换技巧),将使用带有标志的struct数组。

struct AandB {
   A a;
   B b;
   bool isA;
};

然后,你可以使用它有这样的东西:

AandB foo;

if (a.isA) {
   /* a process */
}
else {
   /* b process */
}

但是,如果某个项目可能不包含任何类型,那么您应该注意这样一个事实,即该标志最初将为false并假设为B类型。在这种情况下,解决方法是使用两个标志和设置正确的。

<强>更新

如果内存使用是一个问题,仍然有办法,但它需要一个更有趣的数据结构。想到的一种方法是拥有一个包含索引和标志的项目定义数组。让我们想象一下这个数据结构:

struct Item {
   bool isA;
   int index;
};

Item items[5];
A a[5];
B b[5];

Item firstAItem;
firstItem.isA = true;
firstItem.index = 0;
items[0] = firstAItem;

Item firstBItem;
firstBItem.isA = false;
firstBItem.index = 0;
items[1] = firstBItem;

迭代时,您可以检查标志并转到相关索引,如下所示,假设N_items是您拥有的项目数:

for (int i=0; i<N_items; i++) {
   Item currentItem = items[i];
   if (currentItem.isA) {
      A foo = a[currentItem.index];
      /* do some stuff with foo */
   } else {
      B bar = b[currentItem.index];
      /* do some stuff with bar */
   }
}

答案 1 :(得分:1)

由于我们讨论的是顶点属性,你可以这样做:

layout(location = 0) vec4 floatVal;
layout(location = 0) ivec4 intVal;

OpenGL将此作为属性别名引用,并且明确允许,具有以下警告。要么只访问其中一个别名属性,要么通过着色器的每个代码路径只访问其中一个属性。因此,如果你使用布尔条件保护访问和值计算,你会没事的:

//Don't use either variable yet

if(isFloat)
{
  //Do something with `floatVal`
}
else
{
  //Do something with `intVal`
}

//Don't use either variable again.

嗯,理论上你会很好 。属性别名是一个非常奇怪的角落,并且使用OpenGL的任何主程序实际上都不太可能这样做。这意味着实现支持可能会出错(未使用的代码是未经过测试的代码)。因此,如果您希望确保您的代码在各个平台上实际正常工作

,我建议您切换程序。