smoothstep() returns "identical" 个参数的不同值

smoothstep() returns different values for "identical" arguments

运行 一台配备 Intel® Iris® Plus 显卡的 Surface Laptop 3(驱动程序版本 30.0.101.1191)。也许我正面临英特尔着色器编译器中的错误。虽然,我对着色器的总体经验有限,所以可能会出现以下行为。

前往 https://www.shadertoy.com/new 并尝试下面的着色器。出于某种原因,与 1.0.

的编译时常量相比,定义 float d = 1.0 似乎会产生不同的结果
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    float d = 1.0;
    
    // WHY this returns 1?
#if 1
    float x = smoothstep(0.0, 0.0, d);
#else
    // Whereas this returns 0?
    float x = smoothstep(0.0, 0.0, 1.0);
    // OR this for that matter:
    // float x = smoothstep(0.000000000000001, 0.0, d);
#endif
        
    fragColor = vec4(1.0, 0.0, 1.0, 1.0) * x;
}

因此,smoothstep(0.0, 0.0, 1.0) returns 0 但等价于 smoothstep(0.0, 0.0, d) returns 1。为什么?

smoothstep要求第一个参数edge0严格小于第二个参数edge1edge0 >= edge1.

时结果未定义

这背后的原因很简单。来自 GL 文档 (https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/smoothstep.xhtml)

代码看起来像这样:

genType t;  /* Or genDType t; */
t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);

记下分母,

(edge1 - edge0)

如果这些值相等,则为零除。因此,您的实现返回 01 因为它不能抛出异常,因为它是 C.

编辑:

关于“为什么返回 0 或 1”的问题:GL 文档中的示例实现将结果从 0 钳位到 1。如果 edge0 > edge1,生成的负值将钳位到 0。如果 edge0 == edge1,除以零会产生正无穷大,它被限定为 1

但是,这都是推测,因为您系统的 GL 实现中的实际实现 是一个黑盒子。对于 edge0 >= edge1 的情况,结果未定义,应忽略。