Я пытался разработать некоторый код затенения для рендеринга атмосферных эффектов на устройствах iOS. Этот код GLSL в значительной степени зависит от сферы лучей пересечения исчисления, я реализовал этот путь, основанный на http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersectionПерекресток Sphere-Ray на GLSL. Различное поведение в зависимости от устройства
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 как работает прошивкой 10,0 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);
не должен возвращать никаких перекрестков вообще, но он делает.
Я немного новичок в программировании шейдеров, и любая помощь будет оценена по достоинству.
Спасибо за быстрый ответ. Определенно вы были во что-то там, pow (x, 2.0) определенно не совпадает с x * x, и это, по-видимому, является частью моей проблемы. –
Однако, похоже, что разрешение vec3 на highp float на старых машинах не позволяет с достаточной точностью вычислить пересечения со сферами. –
Запустится ли он на шейдере фрагмента? К сожалению, устройства GLES2 не должны поддерживать highp на флеш-шейдерах и могут просто использовать mediump (в терминах процессора, почти половинной точности вместо одиночной точности) – Columbo