Glsl 在WebGL中故意创建NaN

Glsl 在WebGL中故意创建NaN,glsl,webgl,nan,Glsl,Webgl,Nan,我有一个GLSL着色器,它应该在满足条件时输出NAN。我真的很难做到这一点 基本上我想这样做: float result = condition ? NaN : whatever; 但GLSL似乎没有一个NaN常量,因此无法编译如何制作NaN? 我试着让自己保持恒定: float NaN = 0.0/0.0; // doesn't work 这在我测试的一台机器上有效,但在另一台机器上无效。在编译着色器时,它还会导致警告 考虑到我尝试的其中一台机器上显然无法进行计算,我觉得正确地进行计算相

我有一个GLSL着色器,它应该在满足条件时输出NAN。我真的很难做到这一点

基本上我想这样做:

float result = condition ? NaN : whatever;
但GLSL似乎没有一个NaN常量,因此无法编译如何制作NaN?


我试着让自己保持恒定:

float NaN = 0.0/0.0; // doesn't work
这在我测试的一台机器上有效,但在另一台机器上无效。在编译着色器时,它还会导致警告


考虑到我尝试的其中一台机器上显然无法进行计算,我觉得正确地进行计算相当棘手,需要了解许多关于各种类型GPU之间不一致的真实事实。

愚弄优化器

问题似乎是着色器编译器执行了不正确的优化。基本上,它将
NaN
表达式替换为
0.0
。我不知道为什么会这样。。。但确实如此。也许规范允许未定义的行为

基于这个假设,我尝试创建一个模糊的方法,生成一个
NaN

float makeNaN(float nonneg) {
    return sqrt(-nonneg-1.0);
}

...
    float NaN = makeNaN(some_variable_I_know_isnt_negative);
这是因为优化器不够聪明,无法看穿这一点。 而且,在失败的测试机器上,这是可行的!我还试图简化函数,使其只返回
sqrt(-1.0)
,但这导致了失败(进一步强化了我对优化器出错的信念)

这是一种变通方法,而不是解决方案

  • 一个足够聪明的优化器可以看穿这种混淆,并再次开始破坏东西
  • 我只在几台机器上进行了测试,这显然是一个变化很大的问题

  • 不要在此处使用NAN。

    第2.3.4.1节,从

    特殊值Inf和−Inf编码的数值太大,无法表示;特殊值NaN对未定义的算术运算(如0/0)产生的“非数字”值进行编码。允许实现(但不是必需的)在浮点计算中支持Inf和NaN


    因此,这似乎真的取决于实施。您应该输出另一个值,而不是NaN

    将其作为统一值传入

    与其尝试在glsl中生成NaN,不如在javascript中生成NaN,然后传入:

    shader = ...
        uniform float u_NaN
        ...
    
    call shader with "u_NaN" set to NaN
    

    为什么要生成NaN值?着色器管道的每个阶段都应为其目标生成有效的结果stage@ibesora我用webgl来模拟量子电路,NaN是我在聚合步骤中发出错误信号的方式。也许是NaN提供的制服?@TamasHegedus实际上我正要补充这一点作为可能的答案。如果你知道它可以跨多个GPU工作,那我就这么说。不幸的是,我手头只有一个nvidia 840m,无法在多个设备上测试它。你可以把它贴出来作为答案。嗯,那太不方便了。不过,了解这一点非常有用。这与WebGL无关。WebGL不是基于OpenGL的。它是基于OpenGLES的。如果你引用了一个规范,请引用正确的规范。你是对的@gman,虽然两个规范描述了相同的行为,但我将规范链接更改为OpenGL ES one。