website articles
smooth minimum

Intro



One of the basic building blocks of impicit procedural modeling (such when building a distance field for raymarching based on basic primitives) is the union operator.
float opU( float d1, float d2 )
{
    return min( d1, d2 );
}
This operator works great, but has the problem that the resulting shape has discontinuities in its derivatives. Or in other words, the resulting surface of unifying two smooth objects is not a smooth surface anymore. This is often inconvenient from a looks perspective, such as when trying to model organic shapes.


Regular min() based primitive union

smooth-min() based primitive union

The images above are a zoom into a procedurally modelled creature (which you can see in realtime online here: https://www.shadertoy.com/view/Mss3zM), where the legs are made of (deformed) cylinders and the body of a (deformed) sphere. When using the regular min() based primitive union, shown in the image to the let, the intersection between the legs and the body becomes apparent. In the right side image, the smooth-min based union explained in this article is used instead, resulting in a much more organic and visually pleasing connection between the parts.


Several implementations



The way to smoothly blend the shapes is to get rid of the discontinuity of the min() function, of course. But we want our smooth-min function to behave quite like min() when one of the two primitives is way further that the other. It's only in the area where the two values get similar that we want to apply the smoothness.
// exponential smooth min (k = 32);
float smin( float a, float b, float k )
{
    float res = exp( -k*a ) + exp( -k*b );
    return -log( res )/k;
}
// polynomial smooth min (k = 0.1);
float smin( float a, float b, float k )
{
    float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
    return mix( b, a, h ) - k*h*(1.0-h);
}
// power smooth min (k = 8);
float smin( float a, float b, float k )
{
    a = pow( a, k ); b = pow( b, k );
    return pow( (a*b)/(a+b), 1.0/k );
}
These three functions produce smooth results, with different qualities. The three accept a paramter k that controls the radious/distance of the smoothness. From these three, probably the polynomial is the fastest, and also the easiest to control, for k maps directly to a blending band size/distance. Unlike the other two, it probably suffers from second order discontinuities (derivatives), but visually is pleasing enough for most applications.

As a curiosity, it might be worth noting that the exponential and power based smooth-min functions, both generalize to more than two distances, so they are probably better suited for computing minimun distances to big sets of points beyond 2, for example when you want to compute smooth voronoi patterns or interpolate pointclouds. In the case of the power based smooth-min function, the expression a*b/(a+b) generalizes with the same formula as when computing the global resistance of N parallel resistors: 1/ ( 1/a + 1/b + 1/c + ... ), or in other words. For example, for three distances, you get a*b*c / (b*c + c+a + a*b).


Two functions

The polynomial smooth min of the two funcitons


Results



In general, the polynomial smooth-min function works very well, predictably and fast. It can be used to make surfaces connect, such as snow and archnitecture in the images below.


Regular min() based primitive union

Polynomial smooth-min() based primitive union

It obviously becomes very handy for connecting the different pieces of one same character, such as the fingers, hands, arms and body (wich in this case are made of cylinder/cones for the fingers and arms and a sphere for the body). The image bellow is interactive, and you can click and move the mouse over it to see the effect of the polynomial smooth-min function compared to the regular min function.




And finally, this is the result under animation of the body parts that are blended (note that texture coordinates are not fixed so the textures swim, but that's a different problem unrelated to the smooth-min, which works beautifully also with moving objects):