Running a Surface Laptop 3 with Intel® Iris® Plus Graphics (driver version 30.0.101.1191). Perhaps I'm facing a bug in Intel's shader compiler. Though, I have limited experience of shaders in general, so perhaps the behavior below is expected.
Head over to https://www.shadertoy.com/new and try the shader below. For some reason, defining a float d = 1.0
seems to produce different results compared to a compile-time constant of 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;
}
Thus, smoothstep(0.0, 0.0, 1.0)
returns 0 but the equivalent smoothstep(0.0, 0.0, d)
returns 1. Why?
smoothstep
requires that the first parameter edge0
is strictly less than the second parameter edge1
. The results are undefined when edge0 >= edge1
.
The reason behind this is pretty simple. From the GL docs (https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/smoothstep.xhtml)
The code looks something like this:
genType t; /* Or genDType t; */
t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
Note the denominator,
(edge1 - edge0)
If those values are equal, there's a divide-by-zero. So, your implementation is returning a 0
or a 1
since it can't throw an exception, because it's C.
Edit:
On the question of "why is it returning 0 or 1:" The sample implementation from the GL docs clamps the result from 0 to 1. If edge0 > edge1
, the resulting negative value will be clamped to 0
. If edge0 == edge1
, divide-by-zero results in positive infinity, which is clamped to 1
.
But, that's all speculation, since the actual implmentation in your system's GL implementation is a black box. For cases where edge0 >= edge1
, the result is undefined and should be ignored.