I was hanging out at the Mathworld Superellipse page the
other day and found an interesting function called the superformula.
Since it is really just a generalization of the super-ellipse, I prefer the
name super duper ellipse. It is given in polar coordinates as:
(1)
Shaderization
This is an explicit form of the function and we need it in the implicit form to
use in a shader. If you don't understand what I mean by the implicit
form, check out ImplicitFunction. Maybe I'll write about that
sometime. Anyway, to make Equation (1) implicit, we just have to rearrange it.
(2)
or
(3)
Quick Note: Be very careful of blowing up equations like this when there variables in the denominator that can go to 0. For example, an alternative way of expressing Equation (2) would have
as the denominator instead of the numerator. This would be bad because
near the center.)
The shader code might look like this (for simplicity I'm sticking everything
in one function for now).
Quick Note: From the paper, these examples have
,
and the tuple under each image is
Hey, notice that each of these have a nice gradient on them? That is a product
of their representation with an implicit function. Since they have a nice
gradient, Let's chuck some profiles onto them...
(7, 10, 6)
(5, 4, 4)
(5, 2, 13)
Ci = prof_step(0.8, f);
Ci = prof_filterring(0.6, 0.8, f);
Ci = prof_cos(f);
Ci = prof_round(f);
Alternative View
I know what you're thinking. You're thinking "So now we've got this groovy
unit shape function based on the super duper ellipse, let's stick it in
our shape library". Well, actually, let's not. Based on our discussion in the
last note many interesting shapes can be made from simple coordinate
transformations and simple shapes. From the description of the
super duper ellipse we should already have a good idea of what the
transformations and shape should be. The super duper ellipse is a generalization of
the super-ellipse, which in turn is a generalization of the the ellipse, which
in turn... well you get the idea. This seems to indicate the unit shape should
be a circle. Let's see if we can get there more quantitatively.
Let's start with Equation (3) again. Since we'll eventually want to linearize
the function, let's keep track of
as well. First, get rid of the
nasty
exponent
(4)
and then suck
into the brackets and distribute it to the
resulting terms
(5)
Hey, this is starting to look familiar. Let's pull an arbitrary 2 out of the
exponents.
(6)
Now just make the substitution
(7)
and we get a circle!
(8)
This whole exercise just reiterates what I talked about in the previous note
on Coordinate Transformation. Many complicated, nasty functions can be
represented by a simple shape with coordinate transformations.
Let's implement that super duper ellipse shader again, this time using the unit circle.
This time the super duper ellipse functionality is implemented as a set of coordinate
transformations. Also, we'll need to linearize the function since the results
in the last implementation are linearized. The linearization function can be
found from Equation (7).
(9)
(10)
Since Equation (8) will be implemented with the unit_circle function
we don't have to worry about linearizing it.
12float x_new, y_new;
3 xform_supdupell(s, t, 1, 1, m, n1, n23, n23, x_new, y_new);
4float r_new = unit_circle(x_new, y_new);
5Ci = xform_supdupell_lin(r_new, a, b, m, n1, n2, n3);
(3, 5, 10)
(4, 12, 15)
(7, 10, 6)
(5, 4, 4)
(5, 2, 13)
Super Shapes
Yes, splitting up the transformation into two portions is really ugly. Maybe
I'll come up with a better way of expressing this later. For now, though, let
me point out that we could put any shape through this transformation, not
just the circle.
12float x_new, y_new;
3 xform_supdupell(s, t, 1, 1, m, n1, n23, n23, x_new, y_new);
4float r_new = func(x_new, y_new);
5float g = xform_supdupell_lin(r_new, 1, 1, m, n1, n23, n23);
Ci = prof_step(0.8, g);
Ci = prof_filterring(0.6, 0.8, g);
Ci = prof_cos(g);
Ci = prof_round(g);
circle
box
stripe
Whoa, That's crazy! We went from the superformula which is a generic
form for a super-ellipse, into a form that gives us arbitrary generic
super-shapes. That, my friends, is a thing of beauty.