【问题标题】:Best way to detect NaN's in OpenGL shaders在 OpenGL 着色器中检测 NaN 的最佳方法
【发布时间】:2012-03-15 20:32:17
【问题描述】:

今天早上我遇到了一个看似神秘的错误,我很幸运能够很快找到解决方案。

我用一个计数器除以在片段着色器中产生一个平均值,当然当计数器为零时,生成的颜色值变为 NaN。

在混合过程中,NVidia 优雅地将 NaN 视为 0 值,但 Intel 不会并且似乎将 NaN 级联,从而产生黑色片段。

所以这个错误一直存在,直到我在英特尔机器上测试代码。

我想知道是否可以采取一些措施来“捕获”无效值。似乎,就像在常规编程中一样,处理这个问题的唯一可靠(即使这样也不是万无一失)的方法是在除数时仔细考虑所有可能的情况。

检测 NaN 的标准方法是查看数字是否不等于自身。我是否可以构建一个调试着色器来检查每个片段以查看它是否不等于自身,如果满足该条件,则设置一个闪烁的显眼颜色? GLSL 是否允许我以这种方式检测 NaN,或者每当值无效时我是否会陷入未定义的行为?

【问题讨论】:

  • 为什么要除以 0?你不能抓住计数器为 0 或改变你的算法吗?
  • 程序员总是检查潜在分母是否为零是合理的,但检查可能会产生性能成本。我的问题与事后检测不良值有关。

标签: opengl glsl nan


【解决方案1】:

我用一个计数器除以在片段着色器中产生平均值,当然当计数器为零时,生成的颜色值变为 NaN。

花车不是这样工作的。当你除以零时,你得到 INF,而不是 NaN。除非分子也为零,否则你会得到 NaN。

在任何情况下,GLSL 都提供了isinfisnan 函数,它们按照他们所说的去做。

【讨论】:

  • 啊。这很方便。原来它们是 NaN,因为如果分母是,分子总是为零。
【解决方案2】:

缺少 isnan 是 WebGL 和 Opengl ES 2.0 的问题。适用于我有机会尝试的所有 GPU 的 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;*/
}

【讨论】:

  • NVIDIA 无法解决这个问题,因为它的优化器非常激进。
  • FWIW Java 将其定义为 boolean isNaN(float f) {return f != f;},
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-19
相关资源
最近更新 更多