如何在没有 if-else 分支的情况下实现这个功能? (GLSL)
How to implement this function without an if-else branch? (GLSL)
我正在开发一款游戏,使用 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)
);
这里有一个"eliminates"分支的技巧。但它做的更重要的事情是矢量化你的代码。毕竟,编译器可能会为您删除该分支;它意识到它可以做到这一点的可能性要小得多:
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
转换为 float
将恰好是 1.0 或 0.0,它实际上只是选择 side1
或 side2
。此选择由组件方式 greaterThan
操作的结果定义。
我正在开发一款游戏,使用 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)
);
这里有一个"eliminates"分支的技巧。但它做的更重要的事情是矢量化你的代码。毕竟,编译器可能会为您删除该分支;它意识到它可以做到这一点的可能性要小得多:
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
转换为 float
将恰好是 1.0 或 0.0,它实际上只是选择 side1
或 side2
。此选择由组件方式 greaterThan
操作的结果定义。