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

Opengl es GLSL优化:检查变量是否在范围内,opengl-es,glsl,webgl,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 &&am

在我的着色器中,我有变量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;
    }
float a=const1;
如果(b>=2.0&&b<4.0){
a=常数2;
}否则如果(b>=4.0&&b<6.0){
a=常数3;
}否则如果(b>=6.0&&b<8.0){
a=常数4;
}如果(b>=8.0),则为else{
a=常数5;
}

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

您可以通过创建一种查找表来避免分支:

float table[5] = {const1, const2, const3, const4, const5};
float a = table[int(clamp(b, 0.0, 8.0) / 2)];

但是性能将取决于是否必须在每个着色器中创建查找表,或者它是否是某种统一的。。。一如既往,首先测量…

您可以通过创建一种查找表来避免分支:

float table[5] = {const1, const2, const3, const4, const5};
float a = table[int(clamp(b, 0.0, 8.0) / 2)];

但是性能将取决于是否必须在每个着色器中创建查找表,或者它是否是某种统一的。。。像往常一样,首先测量…

事实证明Jaa cs Answare对我来说是不可行的,因为我的目标是WebGL,它不允许变量作为索引(除非它是循环索引)。不过,他的解决方案可能对其他OpenGL实现非常有用

我使用混合和分步函数提出了这个解决方案:

//Outside of main function:
uniform vec3 constArray[5]; // Values are sent in to shader

//Inside main function:
float a = constArray[0];
a = mix(a, constArray[1], step(2.0, b));
a = mix(a, constArray[2], step(4.0, b));
a = mix(a, constArray[3], step(6.0, b));
a = mix(a, constArray[4], step(8.0, b));
但经过一些测试,它并没有给任何明显的性能提升。我最终得出了这个解决方案:

float a = constArray[0];

if (b >= 2.0)
    a = constArray[1];
if (b >= 4.0)
    a = constArray[2];
if (b >= 6.0)
    a = constArray[3];
if (b >= 8.0)
    a = constArray[4];

它既紧凑又易于阅读。在我的例子中,这些替代方案和我的原始代码的性能相同,但至少这里有一些选项可以尝试。

结果表明,Jaa cs Answare对我来说是不可行的,因为我的目标是WebGL,它不允许变量作为索引(除非它是循环索引)。不过,他的解决方案可能对其他OpenGL实现非常有用

我使用混合和分步函数提出了这个解决方案:

//Outside of main function:
uniform vec3 constArray[5]; // Values are sent in to shader

//Inside main function:
float a = constArray[0];
a = mix(a, constArray[1], step(2.0, b));
a = mix(a, constArray[2], step(4.0, b));
a = mix(a, constArray[3], step(6.0, b));
a = mix(a, constArray[4], step(8.0, b));
但经过一些测试,它并没有给任何明显的性能提升。我最终得出了这个解决方案:

float a = constArray[0];

if (b >= 2.0)
    a = constArray[1];
if (b >= 4.0)
    a = constArray[2];
if (b >= 6.0)
    a = constArray[3];
if (b >= 8.0)
    a = constArray[4];

它既紧凑又易于阅读。在我的例子中,这些替代方案和我的原始代码的性能相同,但至少这里有一些选项可以尝试。

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


[a,b]中的x作为
步骤(a,x)*步骤(x,b)
(注意x和b的倒数,得到x=8.0)*(常数5-const4)

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


[a,b]中的x作为
步骤(a,x)*步骤(x,b)
(注意x和b的倒数,得到x=8.0)*(常数5-const4)

这是一个好主意,我将尝试一下!无需在每个着色器中创建表,它将在整个应用程序中保留其值。使用统一比在诸如const float table[5]={const1,const2,const3,const4,const5}这样的主函数之外创建一个const更好吗@约翰:我希望制服会更好。你可以阅读这个相关的答案:这个链接比较了主函数外部或内部的变量,而我的问题更多的是关于常量和统一的。在这方面,正如这个答案中所建议的那样,似乎没有什么不同:我将把你的答案标记为已接受,因为它回答了我的原始问题,尽管在测试时这实际上不起作用,显然你不能有可变索引(我得到错误“索引表达式必须是常量”)。这是在浏览器OpenGL ES中运行的。这是一个好主意,我将尝试一下!无需在每个着色器中创建表,它将在整个应用程序中保留其值。使用统一比在诸如const float table[5]={const1,const2,const3,const4,const5}这样的主函数之外创建一个const更好吗@约翰:我希望制服会更好。你可以阅读这个相关的答案:这个链接比较了主函数外部或内部的变量,而我的问题更多的是关于常量和统一的。在这方面,正如这个答案中所建议的那样,似乎没有什么不同:我将把你的答案标记为已接受,因为它回答了我的原始问题,尽管在测试时这实际上不起作用,显然你不能有可变索引(我得到错误“索引表达式必须是常量”)。这是在浏览器OpenGL ES中运行时发生的。