Подтвердить что ты не робот

Лучший способ обнаружить NaN в шейдерах OpenGL

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

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

Во время смешивания NVidia изящно рассматривает NaN как значение 0, но Intel не делает и, похоже, каскадирует NaN, в результате чего появляются черные фрагменты.

И поэтому эта ошибка сохранялась до тех пор, пока я не проверил код на машине Intel.

Интересно, есть ли что-то, что я мог бы сделать, чтобы "заманить" недопустимые значения. Кажется, что так же, как в обычном программировании, единственный верный способ (и даже тогда он не чувствует себя пуленепробиваемым) способ справиться с этим - тщательно рассмотреть все возможные случаи при делении чисел.

Стандартный способ обнаружения NaN состоит в том, чтобы увидеть, не является ли число не равным самому себе. Могу ли я, возможно, создать отладочный шейдер, который проверяет каждый фрагмент, чтобы убедиться, что он не равен самому себе, и если это условие выполнено, установите мерцающий, заметный цвет? Предоставляет ли GLSL возможность обнаружить NaN таким образом или я придерживаюсь поведения undefined, когда значение недействительно?

4b9b3361

Ответ 1

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

Это не то, как работают поплавки. Когда вы делите на ноль, вы получите INF, а не NaN. Если числитель не равен нулю, в этом случае вы получите NaN.

В любом случае GLSL предлагает isinf и isnan, которые выполняют то, что они говорят.

Ответ 2

Отсутствие isnan - проблема для WebGL и Opengl ES 2.0. Polyfill, который работает для всех графических процессоров, у меня была возможность попробовать:

bool isnan( float val )
{
  return ( val < 0.0 || 0.0 < val || val == 0.0 ) ? false : true;
  // important: some nVidias failed to cope with version below.
  // Probably wrong optimization.
  /*return ( val <= 0.0 || 0.0 <= val ) ? false : true;*/
}