GLSL 优化:检查变量是否在范围内

Joh*_*han 4 opengl-es glsl webgl

在我的着色器中,我有变量 b,需要确定它位于哪个范围内,然后将正确的值分配给变量 a。我最终得到了很多 if 语句:

    float a = const1;

    if (b >= 2.0 && b < 4.0) {
        a = const2;
    } else if (b >= 4.0 && b < 6.0) {
        a = const3;
    } else if (b >= 6.0 && b < 8.0) {
        a = const4;
    } else if (b >= 8.0) {
        a = const5;
    }
Run Code Online (Sandbox Code Playgroud)

我的问题是这是否会导致性能问题(分支)以及如何优化它?我已经研究了 step 和 smoothstep 函数,但还没有找到实现此目的的好方法。

And*_*oom 5

为了解决所描述的问题并避免分支,常用的技术是找到一系列数学函数,每个条件一个,对于除变量满足的条件之外的所有条件,其计算结果为 0。我们可以使用这些函数作为增益来构建每次计算出正确值的总和。在这种情况下,条件是简单的间隔,因此使用阶跃函数我们可以编写:

x in [a,b] as step(a,x)*step(x,b)(注意 x 和 b 的反转以获得 x<=b)

或者

x in [a,b[ 如step(a,x)-step(x,b)另一篇文章中所述:GLSL point inside box test

使用这种技术我们获得:

float a = (step(x,2.0)-((step(2.0,x)*step(x,2.0)))*const1 + 
                (step(2.0,x)-step(4.0,x))*const2 + 
                (step(4.0,x)-step(6.0,x))*const3 + 
                (step(6.0,x)-step(8.0,x))*const4 + 
                step(8.0,x)*const5
Run Code Online (Sandbox Code Playgroud)

这适用于一般的不相交间隔,但在本问题中的阶梯或阶梯函数的情况下,我们可以将其简化为:

float a = const1 + step(2.0,x)*(const2-const1) +
                   step(4.0,x)*(const3-const2) +
                   step(6.0,x)*(const4-const3) +
                   step(8.0,x)*(const5-const4)
Run Code Online (Sandbox Code Playgroud)

我们还可以使用“bool conversion to float”作为表达条件的方法,因此作为示例step(8.0,x)*(const5-const4)相当于float(x>=8.0)*(const5-const4)