Exploding Coffee » Parametric Blob

(This is one of some older posts of mine, originally written on 2012-11-03.)

Parametric surfaces are neat things. In mathematics they allow you to make calculations on arbitrary surfaces which is useful, but maybe not always interesting. But combine them with some 3D graphics and they allow you to render arbitrary objects procedurally, complete with normals for lighting them.

In the following WebGL demo the shape, normals and lighting of a strange, moving and mostly orange blob is computed entirely by the graphics card.

Instead of containing hard-coded mesh data or even CPU generated data, the code now simple renders a 2D plane covering $(\theta,\phi)\in[0,\pi]\times[0,2\pi]$.

These parametric coordinates are then used to generate a sphere using the standard equations:

$$ x_S = \cos(\phi) \sin(\theta) $$
$$ y_S = \cos(\theta) $$
$$ z_S = \sin(\phi) \sin(\theta) $$

The radius of this sphere is then computed as a function $r(x_S,y_S,z_S,t)$ of the point on the unit sphere and the time t. In my case r is calculated as one plus some smooth noise computed using the 3D perlin noise implementation of webgl-noise.

We now have our final vertex position in the world space.

\[P = r(x_S,y_S,z_S,t) (x_S; y_S; z_S)\]

After this the normals need to be calculated in a clever way.

Note again how the noise above is calculated using the point’s position as projected onto the unit sphere. We will exploit this by offsetting this position by some small amount \epsilon in the direction of each of the two tangents

$$ \Delta_\phi = \epsilon (-\sin(\phi);0;\cos(\phi)) $$
$$ \Delta_\theta = \epsilon (\cos(\phi) \cos(\theta);-\sin(\theta);\sin(\phi) \cos(\theta)) $$
$$ P_{S1} = (x_S; y_S; z_S) + \Delta_\phi \quad,\quad P_{S2} = (x_S; y_S; z_S) + \Delta_\theta $$

and normalizing the result

$$ \hat P_{S1} = \frac{P_{S1}}{|P_{S1}|} \quad,\quad \hat P_{S2} = \frac{P_{S2}}{|P_{S2}|} $$

These are now two points on the unit sphere and may be offset as above

$$ P_1 = r(\hat P_{S1},t) \hat P_{S1} \quad,\quad P_2 = r(\hat P_{S2},t) \hat P_{S2} $$

We now have two points on the blob’s surface that, together with the original point, form a nice triangle. And most importantly: the triangle is not degenerate, even on the poles of the sphere. This means that, finally, the normal can be calculated simply as

$$ N = (P_1 - P) \times (P_2 - P) $$