Procedural Archimedean Spirals in Blender – Part 1: creating the node group

Introduction

This is one of my favorite procedural textures, although I rarely use it. Here is a step by step tutorial describing the technique. The tutorial was prepared using 2.79b but the texture will work in any version of Blender that supports the math node.

The Archimedean Spiral

There are several kinds of spirals, each defined by its own equation. The equation for the Archimedean Spiral, in polar form is

r = a + b * theta

which makes perfect sense to a mathematician but is probably Greek to an artist. Ignore it for now.

Wikipedia describes this as

the locus of points corresponding to the locations over time of a point moving away from a fixed point with a constant speed along a line which rotates with constant angular velocity

a description that I suppose would seem natural to a physics student but is just more Greek to anyone else.

Another way of saying the Wikipedia description is to consider a record player. The locus of points is simply the groove that runs from the inside to the outside of the record. Constant angular velocity means the turntable rotates at a constant speed. For an old LP this is 33 1/3 rotations per minute. If you look straight down on the turntable you will see that the needle moves in a straight line from the edge towards the center. No matter where it is along that line, it is moving at the same speed. This is the constant speed along a line.

Preliminaries

There are two useful helper node groups. The first is a bit of coordinate geometry, the second a bit of logic. The next two subsections describe them, but you can safely skip the description and move to the following section.

Measuring Distance

Blender uses a Cartesian coordinate system to describe where points are on a surface. It takes three numbers to describe where a point is in space, but we’ll be working with a plane, so we only need two.

The distance between the origin and a point is described by the equation

D = square root(x*x + y*y)

we can express this as a procedural material using this node group

From left to right

  • Extracting X and Y:
    • The Object output of a Texture Coordinate node. This will provide the 3d coordinate of each point on the object, in arbitrary blender units. The origin of this coordinate system is the Blender origin of the object.
    • The Vector output of a Mapping node.  For this texture, the mapping node is not used and can be ignored.
    • The X and Y outputs of a Separate XYZ node
  • Calculating the distance
    • Two multiply Math nodes. These compute X*X and Y*Y
    • One add Math node. This adds the two previous results together, giving X*X + Y*Y
    • One power Math node. This extracts the square root, providing the distance.
  • Displaying the result
    • A Diffuse node. This converts the distance value into a gray level.
    • A Material node. Output the result.

Since Blender represents gray values with a number that varies from zero to one, this material will provide an output that is darker near the origin of the plane and becomes lighter the farther away from the plane the point is.

Determining if a number lies between two other numbers

Suppose we want to create a ring using the distance.  A ring would include every point that is farther away from the center than a certain distance, but no farther away than another. The math for this is

d < outer radius AND d > inner radius

We can express this as

The distance formula is now calculated using a node group and we’ve added three more columns of nodes. From left to right, the new nodes are

  • Two Value nodes. These are not strictly necessary because the values can be input directly to the next two nodes.
  • a greater than Math node and a less than Math node.  These give one if their condition is true for their inputs or zero if it is not.
  • A minimum Math node. Blender doesn’t have logic nodes and this is one of several ways to provide the AND logic. If either of its inputs are 0, then the node will give 0.  If both are 1, then the node will give 1. This is the truth table for AND.

Since 0 will display as black and 1 as white, rendering this gives a ring.

Creating a spiral

There are two ways to go about this.  One is to do more complicated math to convert the equation from polar to Cartesian form.  Another is to use a few tricks to accomplish the same thing.  We’ll take the tricky path. How this path works is left as an exercise for the mathematically inclined.

First Trick: Add a radial gradient.

We know what r is: The distance from the center. But what is theta that we use it to know which distance matters? The first thing is to add a radial gradient texture.

The radial gradient, by itself renders as

Adding it to the distance modifies this.

 It is difficult to see what this happens.  Temporarily add the nodes to determine what part of the image is in the range zero to one

The edge of the white area turns out to be a spiral, but only one complete rotation.

Second Trick: add a modulo

The second trick comes from Modular Arithmetic.  Consider time keeping.  The next hour after 12 on a 12 hour clock is not 13 but 1. Without describing the math let’s add a modulo math node

which renders as

giving us a two armed spiral.

Setting the number of arms

Add a multiply before the modulo operator. Now the texture will produce twice as many arms as that number

A value of 2 results in 4 arms

It’s inconvenient to remember to divide the number of arms we want by 2. Here’s a node group that allows us to set the number by changing the value in the value node

With the value set to 1 we get a single arm

Controlling the spacing

So far we’ve accomplished the equivalent of R = theta.  Let’s add in the constant b.  B controls how far apart the turns of the spiral are. A simple trick for doing this is to divide the X and Y coordinates by a constant.

for the value .5 this renders as

Adding limits

Suppose we wanted this pattern to fit in a ring, the way the grooves on a record do.  This is where the range calculation comes into play

There is a subtly here.  We compute the distance twice, once with the division and once without. If we used the output of the division in both cases, the limits would depend on the divisor for the ring.  This keeps them independent.  It now renders as

Setting the “width” of the groove

We have a complete node group that will generate a spiral within a ring. We control the spacing of the spiral and we can control the number of arms.  This is a complete procedural spiral.  There’s one more feature that I’ve found useful.

Look closely at the grooves.  There is a repeated pattern moving outward. The spiral itself is black, but moving outward, it ramps up to white. We can control the way that ramp happens.  We use a color ramp to do this.  In this example, a color ramp that changes the saw tooth pattern into a more symmetric one with a more gentle gradient.

This renders as 

We can add another node group that controls the falloff

rendering as

This doesn’t look any different, but if you adjust the width parameter you can change the curve. The higher the width value, the sharper the falloff, giving greater contrast.

width = .1, you can barely detect the spiral

width = 4, the fall off is much sharper.

Conclusion

We’ve created a procedural material that will generate a spiral. We refined the material, allowing us to

  • control the number of arms generated
  • control the distance covered in one rotation — the spacing
  • limit the range of the spiral to a ring of a given size
  • control the ‘falloff’ from black to white as you move a long a radius — the width

This is a useful enough material that we might turn it into a node group. Part 2 discusses one way to do that.

One thought on “Procedural Archimedean Spirals in Blender – Part 1: creating the node group

  1. Pingback: Procedural Archimedean Spirals in Blender – Part 2: Creating a node group | A Dinosaur Contemplating Asteroids

Leave a Reply