Я пытаюсь реализовать 64-битную арифметику c в шейдерах WebGL или WebGL2 на основе 32-битных операций с плавающей запятой. Одной из необходимых базовых c функций является функция, которая разбивает любое число с плавающей точкой на два «не перекрывающихся» числа с плавающей точкой. Первый поплавок содержит первую половину битов дроби исходного поплавка, а второй поплавок содержит вторую половину. Вот реализация этой функции:
precision highp float;
...
...
vec2 split(const float a)
{
const float split = 4097.0; // 2^12 + 1
vec2 result;
float t = a * split; // almost 4097 * a
float diff = t - a; // almost 4096 * a
result.x = t - diff; // almost a
result.y = a - result.x; //very small number
return result;
}
Эта функция работает, как и ожидалось, если я передам ей аргументы, определенные в шейдере:
precision highp float;
...
...
float number = 0.1;
vec2 splittedNumber = split(number);
if (splittedNumber.y != 0.0)
{
// color with white
// we step here and see the white screen
}
else
{
//color with black
}
Но всякий раз, когда число зависит от в любой униформе все начинает вести себя по-разному:
precision highp float;
uniform float uniformNumber;
...
...
float number = 0.2;
if (uniformNumber > 0.0)
{
// uniform number is positive,
// so we step here
number = 0.1;
}
vec2 splittedNumber = split(number);
if (splittedNumber.y != 0.0)
{
// color with white
}
else
{
//color with black
// we step here and see the black screen
}
Так что во второй ситуации, когда «число» зависит от униформы, функция разбиения каким-то образом оптимизируется и возвращает обратно vec2 со значением ноль y.
Существует аналогичный вопрос о переполнении стека для аналогичной проблемы в OpenGL Различное поведение с плавающей запятой между униформой и константами в GLSL Было предложено использовать модификатор "точный" внутри функции "split" ». К сожалению, в шейдерах WebGL / WebGL2 такого модификатора нет.
Есть ли у вас какие-либо предложения, как избавиться от оптимизаций в моем случае и реализовать функцию «split»?