March 28, 2014

Understanding smoothstep

Since I see it used around a lot.

To start off with, here is an image:


Corresponding to this code:
void main(void)
{
vec2 uv = gl_FragCoord.xy / iResolution.xy;
gl_FragColor = vec4(vec3(uv.x),1.0);
}

Pretty self explanatory.  The x value changes consistently throughout the image, from 0.0 to 1.0
And now let's compare that image with the effects of using smoothstep.
Here is using smoothstep in the range of [0.0, 1.0]:

With the code:
void main(void)
{
vec2 uv = gl_FragCoord.xy / iResolution.xy;
float f = (smoothstep( 0.0, 1.0, uv.x) );
gl_FragColor = vec4(vec3(f),1.0);
}

The image is slightly different but it's still pretty even.

But now, let's look at smoothstep in ranges of [0.0, 0.7], [0.0, 0.4], [0.0, 0.1]:


And smoothstep in ranges of [0.3, 1.0], [0.5, 1.0], [0.9, 1.0]

So it's not that smoothstep keeps uv.x within the range of, say, [0.9, 1.0] or the image would be, at its darkest, light grey.  Seems like if uv.x <= 0.9 it'll be set to 0.0 while if uv.x >= 1.0 it'll be set to 1.0.

So this is how you can get a straight line, by interpolating over a very small range of values.
For example, this is smoothstep in range of [0.509, 0.51]:


Here's code that kind of explains it:
void main(void)
{
vec2 uv = gl_FragCoord.xy / iResolution.xy;
float if_below_me_set_to_0 = 0.509;
float if_above_me_set_to_1 = 0.51;
float f = (smoothstep( if_below_me_set_to_0, if_above_me_set_to_1, uv.x) );
gl_FragColor = vec4(vec3(f),1.0);
}

Better variable names would be if_below_me_set_to_0_else_interpolate and if_above_me_set_to_1_else_interpolate but who has time for that