请考虑以下片段着色器.当我在模拟器或iPhone 5(8.3)上运行时,它会显示预期的颜色(红色).如果我在iPhone 6 Plus(8.2)上运行它会转到第二个if子句(绿色),这显然是错误的,因为正确的计算结果应该在1.22左右.如果我直接将atan参数作为编译时常量提供,则计算有效.
我已经尝试了最新的Xcode 6.2和最新的6.3 Beta.
void main()
{
highp float y = 0.57;
highp float x = 0.21;
highp float a = atan(y, x);
// works if changed to atan(0.57, 0.21);
// does not work if changed to atan(y / x);
if (a > 1.2 && a < 1.25)
{
// Should always come here
// Works on Simulator, iPhone 5
gl_FragColor = vec4(1, 0, 0, 1);
}
else if (a > 1.5 && a < 1.55)
{
// Comes here on iPhone 6 Plus
gl_FragColor = vec4(0, 1, 0, 1);
}
return;
}
Run Code Online (Sandbox Code Playgroud)
更新:情节变粗.
如果我以下列方式更改着色器,则错误消失并且atan返回正确的值.似乎无论我对x和y放置什么都必须是编译时间常量.这解决了我的生产代码中的问题以及根本没有编译时常量的问题.BTW同样的问题影响acos和asin.
highp float y = texCoord.x;
highp float x = texCoord.x;
if (x == x) // Removing this line makes error return
{
x = 0.21;
}
if (y == y) // Removing this line makes error return
{
y = 0.57;
}
Run Code Online (Sandbox Code Playgroud)
另一个例子.这就是我实际使用它的方式.
如果我这样计算,它在iPhone 6上失败了:
float y = sin(lon2 - lon1) * cos(lat2);
float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon2 - lon1);
float bearing = atan(y, x) + 2.0 * pi;
return mod(bearing, 2.0 * pi);
Run Code Online (Sandbox Code Playgroud)
如果我这样做,它的工作原理:
float y = texCoord.y;
float x = texCoord.x;
if (y == y)
{
y = sin(lon2 - lon1) * cos(lat2);
}
if (x == x)
{
x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon2 - lon1);
}
float bearing = atan(y, x) + 2.0 * pi;
return mod(bearing, 2.0 * pi);
Run Code Online (Sandbox Code Playgroud)
小智 1
这看起来像是编译时常量传播错误。
您的if (x == x)子句看起来可以被编译器消除,但由于它是一个 fp 值,因此它实际上是对NaN.
即,将任何内容与 NaN 进行比较总是错误的,即使您将值与其自身进行比较也是如此。
看起来这个测试正在阻止编译器传播您的常量值,如果您要求从编译中获得汇编程序输出,这应该是显而易见的。
| 归档时间: |
|
| 查看次数: |
336 次 |
| 最近记录: |