GLSL atan on iPhone 6 Plus gives the wrong result

Consider the following fragment shader. When I run it on Simulator or iPhone 5 (8.3), it shows the expected color (red). If I launched it on the iPhone 6 Plus (8.2), it will go to the second point if (green), which is clearly wrong, since the correct calculation result should be around 1.22. If I give atan parameters directly as compile time constants, the calculation will be performed.

I tried on both the latest Xcode 6.2 and the latest version 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; } 

UPDATE: The plot is thickening.

If I change the shader as follows, the error will disappear and atan will return the correct value. It seems that everything I put in x and y should be something other than compile-time constants. This also fixed the problem in my production code, where I don't have compile time constants. By the way, the same problem affects acos and 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; } 

Another example. This is how I actually use this.

If I make this calculation, it does not work on 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); 

If I do this, it works:

 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); 
+5
source share
1 answer

It looks like a compile-time constant propagation error.

Your suggestion if (x == x) looks like it can be resolved by the compiler, but since this is an fp value, this is really a test for NaN .

those. comparing anything for equality with NaN is always false, even when you make a value against yourself.

This test seems to prevent the compiler from distributing your constant values, this should be obvious if you are requesting a compiler from your compilers.

+1
source

Source: https://habr.com/ru/post/1216533/


All Articles