Home > Shaders

Gumball

The "gumball" is the fruit of the sweetgum tree. Fruits are spiky green balls that turn brown with age. They are a little over an inch wide, and dangle on a long stalk . Each ball has prickly points that open to let seeds out. Two winged seeds come from each hole. My goal was to replicate the shape of the sweetgum fruit using only displacement. This is probably the most complicated shader I've written so far, involving hex mapping, 3D displacement, fractal brownian motion, and cellular rotation. Be patient, this write up will be rather lengthy.

To begin with, I tried simlpy creating a grid with spikes on it. The spikes were created by calculating the center of each grid square and measuring the length from the current point to the center. This gave the radius of the current point. I used the radius to determine the height of the spike with the following formula:

height = 1 / radius

This creates a graph that looks like this:

Which is perfect for spikes. Note that this graph approaches infinity when x approaches 0, so I had to add 1 to the radius before calculating the height. This resulted in a spike value ranging from 1 to 0. The next step was to stagger the rows. Gumballs are fairly organic, so having the spikes in perfect grids would appear far too artificial. So, I used the following code to adjust the position of the spikes, effectively shifting all the even rows over half a square.

 float ss = s * freq;
 float tt = t * freq;
 float scell = floor(ss);
 float tcell = floor(tt);
 
 if (mod(scell,2) == 0)
 {
 		tt += 0.5;
 		tcell = floor(tt);
 }
 

Lastly, I noticed that the spikes of the gumball do no go straight up and down, but rather a pretty curly. So, to fix this, I used displacement along dPdu and dPdv to shift the spike as it traveled up away from the surface. dPdu and dPdv are tangent vectors which are perpindicular to N, the surface normal. Using them, points may be displaced not out from the surface, but also sideways as well.

Below is the first generation of the gumball shader.

Obviously, there are plenty of problems with this output. There are a number of artifacts, including breaks in the seam between thorns, thorns which are cut in half, and creases at thorn edges. However, after I thought about this for a while, I realized the underlying problem. The natural forms of the gumball are arranged in a hexagonal pattern instead of a grid. A transformation function was needed to convert the s and t space into hexagonal array space. This returns the x and y coordinates of the hex array as well as the distance to the edge, distance from the center and the radial angle. This allowed for geometric shapes to be defined with had a radial appearance. Here is an image showing cell ID.

Beginning with this grid, I created a simple shader which used the distance from the center of a hex to determine the spike height. I also added a crown around each spike by measuring the distance to the edge within a smoothstep function.

However, the spikes really appear to be more like beaks rather than spike. There is a large hole in the middle of each section. To accomplish this, I used some boolean techniques to build up geometry. First, a cylinder was created with a smaller one cut out of the middle. This created a hollow tube. Then, a slice was taken out of the sides of the cylinder based on the radial measurement. This radial cut increased in size as the radius of the cylinder increased, creating sharp curves which came to points.

The last step would be to have the spikes wiggle as the protuded away from the surface. Normally, displacement occurs along the vector N, which is the surface normal. Many people have told me that displacement can only occur along one direction and that forms which double back on themselves are impossible. However, we can accomplish true 3D displacement by adding in two other axes. Renderman conventiently provides these in the form of surface tangents. Tangents are represented mathematically as first derivatives. These are accessed in shading language through the variables dPdu and dPdv. If these are normalized they form a coordinate system consisting of N,U, and V. N points away from the surface and U and V run along it similar to how X and Z in cartesian space.

Also, rotation was added to each spike to create a more natural appearance. The crowns were modulated around the axial coordinate to create small beads of nutty material. A hole was cut down into the surface at the middle of each beak.

So, voila! It almost looks like a gumball.