条件数学和 GLSL

Conditional math and GLSL

我目前正在使用 pixijs 学习 GLSL,我在一个超级简单的脚本中看到这个简单条件的奇怪行为。基本上,代码会询问 x 坐标的绝对值是否 <= 1、大于 1 或其他……并且“其他”分支会触发!

澄清一下,一个数字将小于或等于1,或大于1,应该没有其他可能性(除非我有脑放屁:-))

更多上下文:分辨率是统一的,值为 [10.0,10.0]。

谁能解释一下这怎么可能?我唯一能想到的是 x 坐标不是浮点数。这可能吗?

precision mediump float;

uniform vec2 resolution;


void main()
{
    vec2 uv = ( gl_FragCoord.xy / resolution.xy ) * 2.0 - 1.225;
    uv.y *= resolution.y/resolution.x;
    

   if (abs(uv.x) <= 1.0) {
     gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
   } else if (abs(uv.x) > 1.0) {
     gl_FragColor = vec4(0.5, 0.5, 0.5, 1.0);
   } else {
      /// this fires - WTF?
     gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
   }
}

更新:这看起来像是一个 pixijs 问题,因为当我在 GLSL 代码中手动指定 resolution 时它起作用了。这是设置着色器的代码:

 const uniforms = {
    time: 0,
    resolution: new Point(10.0, 10.0),
 }
 const filter = new Filter(undefined, fragment, {
      ...uniforms
    });

 comp.filters = [filter];

 app.ticker.add((delta) => {
    filter.uniforms.resolution = new Point(10.0, 10.0);
});

看起来pixi.js不喜欢resolution作为制服名称。当我将名称更改为 u_resolution 时,它开始工作了。 :耸肩:

大多数 GLSL 实现使用 IEEE 浮点的一些变体进行计算,并且具有 NaN (not-a-number) 值的概念。 NaN 值是持久的——每当您执行涉及一个的操作时,结果都是 NaN,而当您将 NaN 与另一个浮点值进行比较时,结果始终为 false。所以你可以轻松拥有:

if (abs(uv.x) <= 1.0) {
    // less than or equal to 1
} else if (abs(uv.x) > 1.0) {
    // greater than 1
} else {
    // uv.x must be NaN!

有多种方法可以获得 NaN,但最简单的方法是计算 0/0。所以在你的情况下,如果你同时拥有 gl_FragCooord.x == 0 和 resolution.x == 0,你会得到 NaN