2016-10-20 20 views
1

Я пытался разработать некоторый код затенения для рендеринга атмосферных эффектов на устройствах 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); 

не должен возвращать никаких перекрестков вообще, но он делает.

Я немного новичок в программировании шейдеров, и любая помощь будет оценена по достоинству.

ответ

0

Проверьте свои функции питания. pow (x, y) не определено, если x отрицательно.

Я хотел бы думать, что компилятор достаточно умен, чтобы превратить pow (x, 2.0) в x * x, но я не хотел бы на него рассчитывать.

Где показатель экспоненты является постоянным целым числом, как в вашем случае, вы могли бы просто выполнить умножения самостоятельно. Где это переменная, вы должны сделать что-то вроде pow (max (0.0, x), y).

Не уверен, что это проблема.

Авария в glDrawArray, вероятно, будет отдельной проблемой полностью и не связана с шейдерным кодом, гораздо более вероятно, что она пытается потреблять вершины из некоторого недействительного буфера или ячейки памяти.

+0

Спасибо за быстрый ответ. Определенно вы были во что-то там, pow (x, 2.0) определенно не совпадает с x * x, и это, по-видимому, является частью моей проблемы. –

+0

Однако, похоже, что разрешение vec3 на highp float на старых машинах не позволяет с достаточной точностью вычислить пересечения со сферами. –

+0

Запустится ли он на шейдере фрагмента? К сожалению, устройства GLES2 не должны поддерживать highp на флеш-шейдерах и могут просто использовать mediump (в терминах процессора, почти половинной точности вместо одиночной точности) – Columbo