Shader Time Uniform - время усечения clock_gettime - PullRequest
2 голосов
/ 01 марта 2012

Возьмите эту функцию, получая время как двойное, используя clock_gettime:

// return current time in milliseconds
static double time_get_ms(void)
{
    struct timespec res;

#ifdef ANDROID
    clock_gettime(CLOCK_REALTIME_HR, &res);
#else
    clock_gettime(CLOCK_REALTIME, &res);
#endif
    return (double)(1000.0*res.tv_sec + res.tv_nsec/1e6);
}

Для отправки в шейдер требуется преобразование в плавающее. Мантисса переполняется и усекается по пути к шейдеру.

Пример:

как двойной = 1330579093642.441895

в виде числа с плавающей запятой = 1330579111936.000000

Значение с плавающей запятой застревает в одном числе на длительный период времени из-за усечения.

Также кажется, что даже значение секунд в res.tv_sec слишком велико для числа с плавающей запятой, оно также усекается по пути к графическому процессору.

Попытка измерить время с момента запуска приложения, и я довольно быстро сталкиваюсь с той же проблемой.

Так, каков наилучший способ получить значение времени работы в шейдер? Что-то кроссплатформенное в мире Linux (например, IOS, Android, Linux).

1 Ответ

4 голосов
/ 01 марта 2012

Вы исчерпали 32-битную точность с плавающей точкой в ​​вашей мантиссе. Шейдер не сможет лучше справиться с этим недостатком точности, потому что если вы не используете GL 4.x с поддержкой двойной точности, шейдеры могут обрабатывать только 32-разрядные операции с плавающей точкой.

Если вы запускаете приложение так долго, что точность с плавающей точкой переполняется в миллисекундах (что потребует ~ 10 7 миллисекунд или около 2,7 часов или около того), то вам нужно найти способ, чтобы изящно справиться с этой ситуацией. Как именно вы это сделаете, зависит от того, для чего ваш шейдер использует это значение времени.

Большинству шейдеров не требуется фактическое время в миллисекундах. Подавляющее большинство шейдерных процессов, которым требуется время (или что-то вроде времени), являются циклическими. В этом случае вы можете просто передать им значение, говорящее о том, как далеко они проходят через определенный цикл. Это значение в диапазоне [0, 1) равно 0 в начале цикла, 0,5 в середине и достигает 1 в конце.

Если ваш шейдерный процесс не может быть параметризован, если ему действительно нужно абсолютное время, тогда ваша следующая ставка должна передать два параметра с плавающей запятой. По сути, вам нужно сохранить биты переполнения. Это усложнит всю вашу математику, включая время на графическом процессоре, так как вам нужно использовать два значения и знать, как собрать их вместе для обновления времени. Опять же, как вы это сделаете, зависит от того, что вы делаете в своем шейдере.

Кроме того, вы можете отправить свое время в 32-разрядных целых числах без знака, если ваше оборудование поддерживает GL 3.x +. Это даст вам еще несколько битов точности, так что это удержит проблему дольше. Если вы отправите свое время в десятых долях миллисекунды, то вы сможете получить около 5 дней или около того времени, прежде чем оно переполнится. Опять же, это усложнит всю вашу математику с графическим процессором, поскольку вы не можете просто выполнить преобразование типа int-to-float.

...