Я передаю время Unix своему шейдеру из кода Java:
gl.uniform1f(shader, System.currentTimeMillis());
Шейдер выглядит так (простая форма, просто для исследования проблемы):
#ifdef GLES
precision highp float;
#endif
uniform float u_time;
void main() {
int d = 1000;
float result = floor(u_time / d) * d;
if (result > u_time) {
s = 1.0;
} else {
s = 0.5;
}
gl_FragColor = vec4(s, 0, 0, 1.0);
}
Я ожидаю, что result никогда не будет больше, чем u_time. Удивительно, но это ЕСТЬ (шейдер дает ярко-красный цвет).
Более того, если заменить значение d, например, на 100, оно будет работать, как и ожидалось, — отрисовывается темно-красным цветом.
Пытался заменить d на float значение 100,0, но безрезультатно.
Это работает, даже если я заменю u_time в выражении на прямую константу с плавающей запятой, например 1563854457241.0 - это примерно то же самое, что Java помещает в шейдер.
В чем может быть проблема? Я подозреваю, что это связано с точностью, но не понимаю, как это исправить.
P.S. Ведь я получил ИСТИНА (ярко-красный цвет), если заменить выражение условия на
1000000123,0 * 1000 == 1000000123456,0
- сказал Нуф.





В коде шейдера вы превысили предел точности 32-битного числа с плавающей запятой.
См. ИЭЭЭ 754 и GLSL ES — точность и квалификаторы точности.
Когда вы используете квалификатор точности highp, то количество значащих битов равно 23 (+1 для знака), поэтому число, подобное 1000000123456.0, не может быть представлено с полной точностью, потому что приблизительное количество десятичных цифр равно 7,22.