opengl-es - 没有if-else分支如何实现这个功能? (GLSL)

标签 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)
);

最佳答案

这里有一个“消除”分支的技巧。但它所做的更重要的事情是将您的代码矢量化。毕竟,编译器可能会为您消除该分支;它意识到自己可以做到这一点的可能性要小得多:

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 基于第三个参数在两个参数之间执行线性插值。但由于转换为 floatbool 恰好是 1.0 或 0.0,因此实际上只需选择 side1side2 >。此选择是由组件级 greaterThan 操作的结果定义的。

关于opengl-es - 没有if-else分支如何实现这个功能? (GLSL),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39440594/

相关文章:

javascript - 在WebGL程序中使用uniform[1234][uif]设置制服: is the vector version [v] better in any regard?

ios - GLSL 程序在某些 iOS 硬件上间歇性失败

opengl-es - 着色器 MAD 优化和精度问题

Android 7 GraphicBuffer 替代方案,用于直接访问 OpenGL 纹理内存

c++ - 在 OpenGL 中绘制扭曲平面的正确方法是什么?

java - Android OpenGL ES 2.0,为每个三角形计算法线

opengl - 为什么我的纹理在使用 Sampler2D 将其渲染到表面上后进行插值

c++ - OpenGL GLSL - 投影矩阵不工作

opengl-es - GLSL 将片段着色器蒙版拟合到顶点坐标中

android - 优化掉的 GLSL 属性