Let’s continue our journey into the wonderful world of shaders using the `Metal Shading Language (MSL)` by picking up where we left off in Part 10. Using the same playground we worked on last time, we will next try to get close to making art using `MSL` math functions such as `sin`, `cos`, `pow`, `abs`, `fmod`, `clamp`, `mix`, `step` and `smoothstep`.

First, let’s look at our “sun eclipse” code from last time. Strangely enough, we start from the end of the functions list above because `smoothstep` is the function we need to fix an issue we had last time and we did not pay attention to it – our output image has jaggies (is aliased) as you can see below if we zoom in enough to make it visible:

The smoothstep function depends on a `left edge` being smaller than a `right edge`. The function takes a real number `x` as input and outputs `0` if `x` is less than or equal to the left edge, `1` if `x` is greater than or equal to the right edge, and smoothly interpolates between `0` and `1` otherwise. The difference between the `step` and the `smoothstep` function is that `step` makes a sudden jump from `0` to `1` at the edge. The `smoothstep` function implements cubic `Hermite` interpolation after doing a clamp. An improved version, named `smootherstep`, has zero `1st` and `2nd` order derivatives at `x=0` and `x=1`:

Let’s implement the smootherstep() function:

The clamp() function moves the point to the nearest available value, given a `min` and `max` value. The input takes the value of `min` if less than it, the value of `max` if greater than it, and keeps its value if in between. Our compute kernel should now look like this:

The last function we look at before moving on, is `mix`. The mix() function performs a linear interpolation between `x` and `y` using `a` to weight between them. The return value is computed as `x * (1 - w) + y * w`. In this case, the `planet` color and `sun` color are interpolated using `smootherstep` as weight. If you execute the playground, the output image now has anti-aliasing and the jaggies are all gone:

The next functions we look at are `abs` and `fmod`. The abs() function simply returns the absolute value, or the distance of a number from `0`. In other words, any value loses its sign and always returns a non-negative value. The fmod() function returns the remainder fractional part of a float (the equivalent of the modulo operator `%` for integers). Let’s apply these two functions to some values and see what we can get:

The output image should look like this:

First, we drew a grid of blue lines spaced out at 0.1 between them and with a thickness of 0.005. Next, we normalized the screen coordinates so we can work with the [-1, 1] interval, and then drew the `X` and `Y` axes in red with a thickness of 0.02. Finally, we drew the two diagonals in green with the same thickness, keeping in mind that x - y gives us the decreasing slope (diagonal) while x + y gives us the increasing one.

Finally, let’s use sin(), cos(), fract(), dot() and pow() together with other functions we already discussed:

The `sin()` function is just the `sine` of an angle, the `cos()` function is obviously the `cosine` of an angle, the `fract()` function returns the fractional part of a value, the `dot()` function returns the scalar product of two vectors and finally, the `pow()` function returns the value of a number raised to the power of another number. This code generates a beautiful fractal, a true piece of art courtesy of `Inigo Quilez`. The output image should look like this:

Your assignment is to try to understand how the `magic` works here. If you have any questions, feel free to contact me using the Contact form on this blog. The source code is posted on Github as usual.

Until next time!