【问题标题】:Fragment shader behavior on iOSiOS 上的片段着色器行为
【发布时间】:2016-08-09 23:36:01
【问题描述】:

我正在为 iOS 应用程序的片段着色器做一些基本的优化。我想将几种颜色中的一种分配给gl_FragColor。我的第一次尝试使用了三元运算符。这会在模拟器和 iPhone 5C 上正确显示:

lowp float maxC = max(color.r, max(color.g, color.b);
lowp float minC = min(color.r, min(color.g, color.b);
gl_FragColor.rgb = (maxC > 1.0 ? result0 : (minC < 0.0 ? result1 : result2));

我尝试用mixstep 的组合替换三元运算符,看看我是否可以用更少的分支复制上述逻辑。不幸的是,这在模拟器中有效,但在 iOS 设备上无效:

  lowp float step0 = step(0.0, minC);
  lowp float step1 = step(1.001, maxC);
  lowp vec3 mix0 = mix(result1, result2, step0);
  gl_FragColor.rgb = mix(mix0, result0, step1);

具体来说,在模拟器中正确绘制的屏幕的某些白色区域在设备上被错误地绘制为黑色区域。其他一切看起来都很好。

stepmix 的上述组合无法重现与使用三元运算符的方法相同的结果是什么原因?

【问题讨论】:

    标签: ios opengl-es fragment-shader glsles


    【解决方案1】:

    OpenGL 着色器中浮点运算的确切细节可能很难理解。可能发生的情况是,GLSL 编译器正在将三元运算符优化为乘以零运算。查看avoiding-shader-conditionals 了解有关如何将条件折叠为乘法或其他简单操作的信息。最有用的效用函数是:

    float when_eq(float x, float y) {
      return 1.0 - abs(sign(x - y));
    }
    

    一个使用示例是:

    float comp = 0.0;
    comp += when_eq(vTest, 0.0) * v1;
    comp += when_eq(vTest, 1.0) * v2;
    

    上面的代码将根据 vTest 的当前值将 comp 设置为 v1 或 v2。请务必将此显式实现与编译器生成的三元 impl 进行测试,看看哪个更快。

    【讨论】:

      猜你喜欢
      • 2021-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-01
      • 1970-01-01
      • 2013-09-17
      • 1970-01-01
      相关资源
      最近更新 更多