Как работать с NaN или inf в шейдерах OpenGL ES 2.0

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

Стандартный GLSL определяет функции isnan() и isinf() для обнаружения. Язык затенения OpenGL ES 2.0 этого не делает. Как мне все же справиться с NaN и Infs?


person rsp1984    schedule 04.08.2012    source источник


Ответы (3)


Вы можете проверить наличие NaN с помощью условия, которое будет верным только для NaN:

bool isNan(float val)
{
  return (val <= 0.0 || 0.0 <= val) ? false : true;
}

isinf немного сложнее. Не существует механизма для преобразования числа с плавающей запятой в его целочисленное представление и игры с битами. Поэтому вам придется сравнить его с достаточно большим числом.

person Nicol Bolas    schedule 04.08.2012
comment
Спасибо! Почему этого нет в официальной спецификации? Есть ли платформы, на которых это не работает? - person rsp1984; 05.08.2012
comment
@RafaelSpring Может быть. Общеизвестно, что большинство аппаратных средств графического процессора используют ярлыки по сравнению с другими. поплавки, которые приводят к несовместимым поплавкам IEEE 754. Таким образом, я сомневаюсь, что ваше требуемое поведение гарантировано. Итак, как предлагает Николь, лучше всего, вероятно, иметь хорошее представление о минимальном и максимальном значениях, которые вы ожидаете при обычных операциях, и проверять, находится ли ваше значение в этом диапазоне. В противном случае это, вероятно, либо Inf, либо NaN. - person Nicu Stiurca; 13.12.2012
comment
@SchighSchagh Даже результаты операторов сравнения могут быть не гарантированы, если задействованы NaN, если компилятор и/или графический процессор несовместимы с IEEE-754. Я сталкивался с ситуациями, когда нестрогий компилятор создает код для <, который всегда оценивается как true, если любой из аргументов равен NaN. Самый безопасный подход — вообще предотвратить создание NaN. - person Sean; 14.05.2014

Та же проблема с WebGL. Ответ Никола Боласа хорошо работает для большинства графических процессоров, но не для некоторых nVidia. Эта версия хорошо работает для всех графических процессоров, которые мне довелось попробовать:

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;*/
}
person Kos    schedule 14.12.2015

Не проверено, поэтому не уверен, что это сработает (из-за оптимизации), но должно работать как для Inf, так и для -Inf.

  bool isinf(float val) {
    return (val != 0.0 && val * 2.0 == val) ? true : false;
  }
person RedHog    schedule 08.12.2016