Rozważ następujące cieniowanie fragmentów. Gdy uruchomię go na symulatorze lub iPhonie 5 (8.3), pokazuje oczekiwany kolor (czerwony). Jeśli uruchomię go na iPhonie 6 Plus (8.2), przechodzi do drugiej klauzuli if (zielonej), która jest wyraźnie błędna, ponieważ poprawny wynik obliczeń powinien wynosić około 1,22. Jeśli dostarczę parametry atan bezpośrednio jako stałe czasu kompilacji, wówczas obliczenie działa.GLSL atan na iPhone 6 Plus daje zły wynik
Próbowałem zarówno na najnowszym Xcode 6.2 i najnowszej wersji 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;
}
AKTUALIZACJA: Fabuła pogrubia.
Jeśli zmieniam moduł cieniujący w następujący sposób, błąd zniknie, a atan zwróci prawidłową wartość. Wygląda na to, że cokolwiek dodam do x i y musi być czymś innym niż kompilacja stałych czasowych. Rozwiązało to problem w moim kodzie produkcyjnym, w którym nie mam żadnych stałych czasowych kompilacji. BTW ten sam problem dotyczy również acos i 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;
}
Inny przykład. Tak właśnie to używam.
Gdybym wykonać obliczenia takiego, to nie działa na 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);
Jeśli zrobić to w ten sposób, to działa:
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);
Poza obszarem zainteresowania pi/2 - tan (x, y) daje oczekiwany efekt (ilekroć x
Nie, daje dokładnie taki sam (nieprawidłowy) wynik. – Seppo