我正在为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));
我尝试用
mix
和step
的组合替换三元运算符,以查看是否可以用较少的分支复制上述逻辑。不幸的是,这在模拟器中有效,但在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);
特别是,在模拟器中正确绘制的屏幕的某些白色区域被错误地绘制为设备上的黑色区域。其他一切看起来都很好。
上述
step
和mix
的组合不能重现与使用三元运算符的方法相同的结果的原因有哪些?
最佳答案
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;
上面的代码将comp设置为v1或v2,具体取决于vTest的当前值。一定要测试此显式实现与编译器生成的三元隐式测试,以查看哪种更快。
关于ios - iOS上的片段着色器行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38862059/