Smooth Minimum Function

Eren Dere -- 28 February, 2023
 5 min read
headImage

Introduction

While studying SDFs, I have learned that we combine different elements in the scene using min function. But sometimes, we might want to blend those objects for artistic purposes. I saw that they do it a lot with volumetric rendering.


I have learned how it is implemented by reading the article of Inigo Quilez about smooth min function. In this article, he gives implementations of different smooth min functions and clearly explains how they work. He also explains the derivation of polynomial smooth min 2 function that he gave as an example. To learn better, I would like to explain what I understood and document it in this blog post. This topic has already been explained by lots of programmers but here, my intention is only to document what I have understood.

Polynomial Smooth Min

In the article, the code for the smooth minimum function is the following:

float smin( float a, float b, float k )
{
    float h = max( k-abs(a-b), 0.0 )/k;
    return min( a, b ) - h*h*k*(1.0/4.0);
}

So, in this code, a and b are some function values and k determines how smooth their minimum will be. For example, let's think like this:

  • let a be f(x)
  • let b be g(x)
f(x)=log2xg(x)=x+5{\scriptsize \begin{align} f(x) = \log_2x \\ g(x) = -x + 5 \end{align} }%

These two functions look like the following:


smooth_min_1

f(x) and g(x)


In the above figure, we can see what f(x) (purple) and g(x) (green) look like. If we want to take the minimum of these two functions, we would get the function below:


smooth_min_2

min(f(x), g(x))


We see that the minimum of these two functions is the red curve. This is the ordinary minimum function. But, if we look closely at the intersection point, we see that the transition from left to right is not smooth. According to what I understood, this means that the first and second derivatives of the curve right at the left and the right of the intersection point are not equal. If we want smoothness, they have to be equal.


So, we have to subtract another function from the min(f(x), g(x)) we can name it w(x,k). This function has its peaks at the intersection points of both functions and values start decreasing while moving away from the intersection point. In the article, Inigo Quilez says that w is:

w=hhk1.04.0{\scriptsize \begin{align} w = h*h*k*\frac{1.0}{4.0} \end{align} }%

In the equation above, we see that there is another function called h. This function is associated with the absolute value of the difference between both functions. Moreover, we see k which is the smoothness factor. Higher the k value, w(x,k) increases so intersection points are smoothed even further. h function formula is like the following:

h(x,k)=max(kabs(f(x)g(x),0))k{\scriptsize \begin{align} h(x,k) = \frac{\max(k - abs(f(x) - g(x), 0))}{k} \end{align} }%

And let's look at h visually:


smooth_min_3

h(x,k)


As it is seen, values of h are clamped between 0 and 1. As k grows, the triangular shape we see here becomes wider, so we get a smoother-looking minimum. The two (left and right) edges of this triangular shape determine where smoothing starts.


And let's now look at the w(x,k) function its formula was

w=hnk1.02.0n{\scriptsize \begin{align} w = h^{n}*k*\frac{1.0}{2.0*n} \end{align} }%

For n=2, let's look at what smoothed-min looks like:


smooth_min_4

smooth-min


The curve with black dots shows that we have now a smooth min. But why do we have k/2.0*n as the denominator? This comes from the derivates of the left and right parts of the min function. In the article, Inigo Quilez divides w(x,k) function to two parts left and right. He calls them wl(x,k) and wr(x,k). They are divided because of h(x,k) function. Because of the absolute value in h. For explanation, let's write wl(x,k) and wr(x,k) like the following:

wl(x,k)=s(1+f(x)g(x)k)wr(x,k)=s(1f(x)g(x)k){\scriptsize \begin{align} w_l(x,k) = s*(1 + \frac{f(x) - g(x)}{k}) \\ w_r(x,k) = s*(1 - \frac{f(x) - g(x)}{k}) \end{align} }%

So, we have to find s here. And we need to check the equation below. To ensure continuity, derivatives must be equal to each other when coming from both sides of the intersection point:

f(c)wl(c,k)=g(c)wr(c,k){\scriptsize \begin{align} f^\prime(c) - w_{l}^\prime(c,k) = g^\prime(c) - w_{r}^\prime(c,k) \end{align} }%

Here, c point is the intersection point of the two functions. So when x=c, f(x) - g(x) will always be zero. Let's take the derivatives and look again:

wl(c,k)=sn(1+f(c)g(c)k)n1(f(c)g(c)k)wr(c,k)=sn(1+f(c)+g(c)k)n1(f(c)+g(c)k){\scriptsize \begin{align} w_{l}^\prime(c,k) = sn(1 + \cancel{\frac{f(c) - g(c)}{k}})^{n-1}(\frac{f^\prime(c) - g^\prime(c)}{k}) \\ w_{r}^\prime(c,k) = sn(1 + \cancel{\frac{-f(c) + g(c)}{k}})^{n-1}(\frac{-f^\prime(c) + g^\prime(c)}{k}) \end{align} }%

If we plug those into the equation, we have this:

f(c)g(c)=2sn(f(c)g(c))ks=k2n{\scriptsize \begin{align} \cancel{f^\prime(c) - g^\prime(c)} = \frac{2*s*n*(\cancel{f^\prime(c) - g^\prime(c)})}{k} \\ s = \frac{k}{2*n} \end{align} }%

So, smooth min becomes

min(f,g)k2n(max(0,kabs(fg)k))n{\scriptsize \begin{align} min(f,g) - \frac{k}{2*n}*(max(0, \frac{k - abs(f-g)}{k}))^n \end{align} }%

This is what it looks like if we use it on SDFs:


smooth_min_smooth_min

smooth-min


If we had used the ordinary minimum function instead of smooth min, two objects would look like the following:


smooth_min_normal_min

ordinary minimum function


Conclusion

So, this is what I understood from smooth minimum function. It looks like a very powerful tool.

Copyright © 2024 --- Eren Dere