如何在没有if-else分支的情况下实现此功能? (GLSL)

时间:2016-09-11 20:58:31

标签: opengl-es glsl glsles

我正在使用OpenGL ES 2.0

开展游戏

如果可能的话,我想在片段着色器中消除分支。但是有一个我无法改进的功能:

float HS(in float p, in float c) {

    float ap = abs(p);

    if( ap > (c*1.5) ) {
        return ap - c ;
    } else {
        return mod(ap+0.5*c,c)-0.5*c;
    }

}

c在大多数情况下是常数,如果它在这种情况下有帮助的话。我使用这个函数:

vec3 op = sign(p1)*vec3(
    HS(p1.x, cc),
    HS(p1.y, cc),
    HS(p1.z, cc)
);

1 个答案:

答案 0 :(得分:2)

这是一个"消除"分支。但它更重要的是矢量化你的代码。毕竟,编译器可能已经为你删除了分支;它意识到它可以做到这一点的可能性要小得多:

vec3 HSvec(in vec3 p, in const float c)
{
  vec3 ap = abs(p);
  vec3 side1 = ap - c;
  const float val = 0.5 * c;
  vec3 side2 = mod(ap + val, vec3(c)) - val;

  bvec3 tests = greaterThan(ap, vec3(c*1.5));
  return mix(side2, side1, vec3(tests));
}

这消除了大量冗余计算,并同时进行了大量计算。

这里的关键是mix功能。 mix基于第三个参数在两个参数之间执行线性插值。但由于转换为bool的{​​{1}}正好是1.0或0.0,所以它实际上只选择floatside1。此选择由组件式side2操作的结果定义。