Я пытался разработать код затенения для рендеринга атмосферных эффектов на устройствах iOS. Этот код GLSL в значительной степени опирается на исчисление пересечения сфер-лучей, которое я реализовал таким образом на основе http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering.-simple-shapes/ray-sphere-intersection
highp vec2 intersectionsWithSphere(highp vec3 o,
highp vec3 d,
highp float r){
highp float a = dot(d,d);
highp float b = 2.0 * dot(o,d);
highp float c = dot(o,o) - pow(r, 2.0);
highp float q = pow(b,2.0) - 4.0 * a * c;
if (q < 0.0){
return vec2(-1.0, -1.0);
}
highp float sq = sqrt(q);
highp float t1 = (-b - sq) / (2.0*a);
highp float t2 = (-b + sq) / (2.0*a);
if (t1 > t2){
highp float a = t2;
t2 = t1;
t1 = a;
}
return vec2(t1,t2);
}
Код отлично работал на моем iPad Pro 9,7 и на iPhone 6 под управлением iOS 10.0.2.
Однако попытка на iPad 2 (iOS 9.3) и iPad 4 (iOS 10) не дает таких же (ожидаемых) результатов. На пути к решению я также столкнулся с очень странным поведением команды glDrawArray() OpenGL, которая, казалось, иногда давала сбой с, казалось бы, совершенно корректным и компилируемым кодом затенения.
Я проверил, что обе платформы имеют одинаковую точность для высоких чисел с плавающей запятой (27 бит), а также проверил с помощью сфер малого масштаба. Например:
intersectionsWithSphere(vec3(0.0,0.0,2.0),vec3(0.0,1.0,-1.0), 1.0);
не должен возвращать никаких пересечений, но это так.
Я немного новичок в программировании шейдеров, и любая помощь будет оценена по достоинству.