The Fractal Flame Algorithm
Scott Draves
Spotworks, NYC, USA

Erik Reckase
Berthoud, CO, USA

September 2003, Last revised November 2008
Abstract
The Fractal Flame algorithm is a member of the Iterated Function
System (IFS) class of fractal algorithms. A two-dimensional IFS creates
images by plotting the output of a chaotic attractor directly on the image
plane. The fractal flame algorithm is distinguished by three innovations
over text-book IFS: non-linear functions, log-density display, and structural coloring. In combination with standard techniques of anti-aliasing
and motion blur the result is striking image variety and quality.
The guiding principle of the design of the algorithm is to expose andpreserve as much of the information content of the attractor as possible.
We found that preserving information maximizes aesthetics.

1

Overview

Some examples appear in Figure 1. The paper begins by defining classic, linear
iterated function systems and hence grounding our notation and terminology.
The classic formulation is then extended with non-linear variations in Section 3,
and then further extended with post transforms and final transforms in Section 3.1. Section 4 describes how log-density display works and its importance,
and Section 5 covers the coloring algorithm. These three sections cover the core
innovations. Sections 6 and 8 explain other important properties of the implementation, and Section 7 shows how to create symmetric flames. The appendix
is a catalog of the variations including formulas and examples.

2

Classic Iterated Function Systems

A two-dimensional Iterated Function System (IFS) is a finite collection of nfunctions Fi from R2 to R2 . The solution of the system is the set S in R2 (andhence an image) that is the fixed point of Hutchinson’s recursive set equation
[3]:
S=

n−1
[
i=0

1

Fi (S)

a

b

c

d

Figure 1: Example fractal flame images. The names of these flames are: a) 206,b) 191, c) 4000, and d) 29140. These images were selected for their aesthetic
properties.

2

Figure 2: Sierpinski’s Gasket, a simple IFS. X and y increase towards the lower
right. The recursive structure is visible as the whole image is made up of threecopies of itself, one for each function.
As implemented and popularized by Barnsley [1] the functions Fi are linear(technically they are affine as each is a two by three matrix capable of expressing
scale, rotation, translation, and shear):Fi (x, y) = (ai x + bi y + ci , di x + ei y + fi )For example, if the functions are
F0 (x, y) = ( x2 , y2 )yF1 (x, y) = ( x+1
2 , 2)F2 (x, y) = ( x2 , y+1
2 )then the fixed-point S is Sierpinski’s Gasket, as seen in Figure 2.
In order to facilitate the proofs and guarantee convergence of the algorithms,
the functions are normally constrained to be contractive, that is, to bring points
closer together. In fact, the normal algorithm works under the much weakercondition that the whole system is contractive on average. Useful guaranteesof this become difficult to provide when the functions are non-linear. Instead
we recommend using a numerically robust implementation, and simply accept
that some parameter sets result in better images than others, and some result
in degenerate images.
The normal algorithm for solving for S is called the chaos game. In pseudocode it is:(x, y)= a random point in the bi-unit square
iterate {i = a random integer from 0 to n − 1 inclusive(x, y) = Fi (x, y)plot(x, y) except during the first 20 iterations}
The bi-unit square are those points where x and y are both in [-1,1]. The
chaos game works because if (x, y) ∈ S then Fi (x, y) ∈ S too. Though we start3

out with a random point, because the functions are on average contractive thedistance between the solution set and the point decreases exponentially. After
20 iterations with a typical contraction factor of 0.5 the point will be within
10−6 of the solution, much less than a pixel’s width. Every point of the solution
set will be generated eventually because an infinite string of random symbols(the choices for i) contains every finite substring of symbols. This is explainedin more formally in Section 4.8 of [1].
No sufficient number of iterations is given by the algorithm. Because thechaos game operates by stochastic sampling, the more iterations one makes thecloser the result will be to the exact solution. The judgement of how close isclose enough remains for the user.
In fractal flames, the number of samples is specified with the more abstract
parameter quality, or samples per output pixel. That way the image quality(in the sense of lack of noise) remains constant in face of changes to the image
resolution and the camera.
It is useful to be able to weight the functions so they are not chosen withequal frequency in line 3 of the chaos game. We assign a weight, or relative
probability wi to each function Fi . This allows interpolation between function
systems with different numbers of functions: the additional functions can bephased in by starting their weights at zero. Differently weighted functions arealso necessary to draw symmetric flames as shown in Section 7.
Some implementations of the chaos game make each function’s weight proportional to its contraction factor. When drawing one-bit per pixel images
this has the advantage of converging faster than equal weighting because it
avoids redrawing pixels. But in our context with mutiple bits per pixel andnon-linear functions (where the contraction factor is not constant) this device
is best avoided.

3

Variations

We now generalize this algorithm. The first step is to use a larger class offunctions than just affine functions. Start by composing a non-linear function
Vj from R2 to R2 with the affine functions:Fi (x, y) = Vj (ai x + bi y + ci , di x + ei y + fi )We call each such function Vj a variation, and each one changes the shapeand character of the solution in a recognizable way. The initial variations were
simple remappings of the plane. They were followed by dependent variations,where the coefficients of the affine transform define the behaviour of the variation. More recently, parametric variations have been introduced, which arevariations controlled by additional parameters independent of the affine transform.
Appendix A documents 49 variations. Variation 0 is the identity function.
It and six more examples are:4

V0 (x, y)
V1 (x, y)
V2 (x, y)V3 (x, y)
V4 (x, y)
V17 (x, y)
V24 (x, y)

=
=
=
=
=
=
=

(x, y)(sin x, sin y)1
r 2 · (x, y)x sin(r2 ) − y cos(r2 ), x cos(r2 ) + y sin(r2 )1
r · ((x − y)(x + y), 2xy)
(x + c sin(tan 3y), y + f sin(tan 3x))(sin(p1 y) − cos(p2 x), sin(p3 x) − cos(p4 y))linearsinusoidal
spherical
swirl
horseshoe
popcorn
pdj

where
r

=

p

x2 + y 2

An example of a dependent variation is Popcorn, V17 , which is dependent
on the c and f coefficients of the affine transform.
The PDJ variation, V24 , is an example of a parametric variation. PDJ relies
on four external parameters (p1 , p2 , p3 , p4 ) to fully characterize its behaviour.
Variations can be further generalized by replacing the integer parameter jwith a blending vector vij with one coefficient per variation. ThenX
Fi (x, y) =vij Vj (ai x + bi y + ci , di x + ei y + fi )jWith this generalization, if are n functions, then there are 87n parametersthat specify it. The parameters consist of 49n variational coefficients vij , 31n
parametric coefficients, 6n matrix coefficients ai through fi , and n weights wi .
Significantly fewer parameters are required, however, if unused parameters are
assumed to be 0.

3.1

Post Transforms

To this point, applying a transform to a set of coordinates involves first applying
an affine transformation to the coordinates, and then applying a non-linear variation function to the result of the affine transformation. We further generalize
this with the addition of a secondary affine transformation, a post transform, tobe applied after the non-linear function. This provides the ability to change thecoordinate systems of the variations. If the post transform is
Pi (x, y) = (αi x + βi y + γi , δi x + ǫi y + ζi )then we redefine the Fi as follows:X
Fi (x, y) = Pi (vij Vj (ai x + bi y + ci , di x + ei y + fi ))
j

5

3.2

Final Transforms

We can now introduce the concept of a final transform, which is an additional
function Ff inal (x, y) that is always applied regardless of the value of i in theiteration loop. The final transform is like a non-linear camera. The result of
the application of the final transform function is not ‘in the loop’, and there
can be only one final transform per flame. The final transform can have a posttransform associated with it. In pseudocode, we now have:(x, y)= a random point in the bi-unit square
iterate {i = a random integer from 0 to n − 1 inclusive(x, y) = Fi (x, y)(xf , yf ) = Ff inal (x, y)plot (xf , yf ) except during the first 20 iterations}
Adding the post transforms to the earlier parameter count, we now have 93nparameters necessary to fully specify n functions. If a final transform is desired,
then the total number of parameters necessary is 93(n + 1).

4

Log-Density Display

The chaos game produces a series of (x, y) points which are plotted on the image
plane. The collection of these points approximates the solution S to the iteratedfunction system. S is a subset of the plane, and hence membership is a binary
function, and the image is therefore black and white, lacking even shades ofgray. See Figure 3a for an example.
Information is lost every time we plot a point that has already been plotted.
A more interesting image can be produced if we render a histogram of thechaotic process, that is, increment a counter at each pixel instead of merely
plotting. These counters can be visualized by mapping them to shades of grayor by using a color-map that represents different densities (larger count values
are more dense) with different colors. A linear mapping of counters to grayvalues results in Figure 3b.
The result is unsatisfying because of the large dynamic range of densities.
Like many natural systems, the densities are often distributed according to a
power law (frequency is proportional to an exponent of the value). Figure 4 has
two histograms demonstrating this. The densest points are much denser than
the average density, hence with a linear map most of the image is very dark,
and information is lost.
The flame algorithm addresses the problem by using a logarithmic map fromdensity to brightness. See Figure 3c for the result. The logarithm allows one
to visually distinguish between, for example, densities of 3,000 and 5,000 in one
part of the image and 30 and 50 in another part.
6

a

b

c

d

e

f

Figure 3: Successive refinements of the rendering technique starting with a)binary membership, then b) linear, c) logarithmic, d) with color, e) with gamma
factor, and finally f) with vibrant colors. The parameters to create this image
are given in Appendix B.

7

1e+07composite
single
1e+06

100000

10000

1000

100

10

1
1

10

100

1000

10000

100000Figure 4: Plots showing that the distribution of densities in an IFS follows thepower law. The density (on the horizontal axis) is the number of hits by thesystem in a pixel, the frequency (on the vertical axis) is the number of pixels
with that density (or up to the next power of two). The line is from the image
in Figure 3, the other is the composite of 19 old, favorite systems including
Figure 3. In each case, after a plateau the graph is nearly a straight line in
log-log space. This is the definitive characteristic of a power law distribution.
Each image was computed with 9.2e6 samples on a 900x900 grid.

8

The display of high dynamic range images like these by tone mapping isstudied in computer graphics [4]. The logarithm used here (combined with the
gamma factor, described below) is just an ad-hoc tone-map.
This log-density mapping is the source of a 3D illusion. On sight people
often guess that fractal flames are rendered in 3D, but as just described thealgorithm works strictly with a 2D buffer. However, where one branch of thefractal crosses another, one may appear to occlude the other if their densities
are different enough because the lesser density is inconsequential in sum. For
example branches of densities 1000 and 100 might have brightnesses of 30 and
20. Where they cross the density is 1100, whose brightness is 30.4, which ishardly distinguishable from 30.

5

Coloring

There is more information to be wrung from the attractor. In particular, whichparts of the attractor come from which functions? The flame algorithm uses
color to convey this. The result is a substantial aesthetic improvement. Color
could be assigned according to the density map and although the result is increased visibility of the densities relative to grayscale, the internal structure of
the fractal remains opaque. Furthermore, for animation the eye prefers that thecolor of each part of the attractor remain unchanged over time, otherwise theillusion of an object in motion is compromised. The fractal flame algorithm uses
an original means to accomplish this: adding a third coordinate to the iteration.
Naturally we want to use a palette or color-map which we define as a function
from [0,1] to (r,g,b) where r, g, and b are in [0,1]. A palette is classically specified
with an array of 256 triples of bytes.
To achieve this we assign a color ci to each function Fi (and a corresponding
cf inal if a final transform is present) and add an independent coordinate to thechaos game:(x, y)= a random point in the bi-unit squarec = a random point in [0,1]iterate {i = a random integer from 0 to n − 1 inclusive(x, y) = Fi (x, y)c = (c + ci )/2(xf , yf ) = Ff inal (x, y)
cf = (c + cf inal )/2
plot (xf , yf , cf ) except during the first 20 iterations}
This has the important property that the most recently applied function
makes the largest difference in the color index and also in spatial location.
Indices make less difference as they recede in time. Hence colors are continuous
in the final image.
9

Color plotting is naturally implemented by keeping three counters per pixel
instead of one, and adding the current color to the three of them instead of incrementing a single density counter. That is not enough information for proper logdensity display, however. Taking the logarithm of each channel independently
grossly alters the colors. Instead one must add a fourth channel of so-calledalpha (α), or transparency values.
So then to plot a point the color is added to the three color channels, and
1 is added to the alpha channel. After all the samples have been accumulated
each channel is scaled by log α/α. See Figure 3d for the result. The resulting
alpha values can be output with the image if the file format supports them, orthey can be used for compositing the fractal with a background immediately, or
they can be discarded.

6

The Gamma Factor

Accurate display of any digital image on a Cathode Ray Tube (CRT) requires
gamma correction to account for the non-linear response of screen phosphors tovoltage. Without correction the darker parts of an image appear too dark. If
the brightness b of a pixel is a value between 0 and 1, the corrected brightness
is simply: bcorrected = b1/γ where γ normally about 2.2.
But depending on the specific image, gamma values as large as 4 improve visibility of fine structure in the attractor. Large gamma values also substantially
increase the visible noise, and so require longer rendering times to compensate.
The parameter is therefor left to the user to set according to taste and circumstance. See Figure 3e for the result of applying gamma 4 to our running
example.
Because the red, green, and blue phosphors respond independently, gamma
correction is normally applied to each color channel independently. However
if the gamma value is unnaturally large this has the effect of washing out thecolors of the image (it becomes pastel or ghostly off-white). This is because
saturated colors occur due to large difference between channel values. But
gamma correction boosts any small values towards one, leaving less difference,and hence less saturation.
While one may desire this effect, to preserve bright colors the gamma correction may be applied the same way the logarithm is: by calculating a scale
factor on the alpha channel, and then applying it to the three color channels.
The name of the parameter that selects this is called vibrancy, and it can takeany value from 0, meaning to apply gamma to channels independently, to 1,
meaning to apply gamma from the alpha channel to each channel.

7

Symmetry

The human mind responds to symmetric designs at a fundamental level. Whenthe matrix coefficients are chosen at random, the chances of a symmetric design10appearing are vanishingly small. We can easily inject such functions intentionally, however. The result appears in Figure 5.
There are two kinds of symmetries: rotational and dihedral. First we coverrotations. Adding a function to the system that rotates by 180 degrees makes a
2-way rotational symmetry appear. The weight of this function should be equal
to the sum of the weights of all other functions in the system. That way halfof the jumps in the chaos game are between the two halves, and hence the two
halves will have equal density. If the rotation function is given the same weightas the other functions, then one of the two halves will only be a shadow of theother.
Adding a rotation by 120 degrees does make a 3-way symmetry appear.
The three branches do not have equal density however, and no weighting would
balance them. That’s because in order to get into the 240-degree branch in thechaos game, one has to pick the rotational function twice in a row, which is only
25% probable, but the 120-degree branch is 50% probable. Instead one must
introduce two transforms, one by 120 degrees and one by 240, and give themboth weight equal to the sum of the others. Then all three branches will havethe same probability. In general, to produce n-way symmetry, n-1 additionaltransforms are necessary to balance the densities.
A dihedral symmetry is created by adding a function that inverts the x coordinate only (producing bilateral symmetry). Again it is given weight equal to thesum of all the other weights combined. Combining this function with rotation
functions gives all the dihedral symmetries. Dihedral symmetries are namedwith negative integers, so the simple bilateral symmetry is -1, and snowflake
symmetry is -6. This just follows the isomorphism between multiplication on
integers and composition of symmetries.
It is also possible to introduce symmetries by modifying the chaos game tosupport them directly instead of adding symmetric functions. For example, one
can just add an integer symmetry parameter, and then after picking a function
at random, pick a rotation at random. But then how to interpolate between
symmetries without discontinuities is problematic.
Getting good colors with the symmetry functions requires special treatment.
The problem is the symmetry functions can bring a point back onto itself after
two or more applications. If the color is modified by these functions and thenplotted at its original location, different colors get averaged, and the image loses
color diversity. The solution is to not change the color coordinate when applying
symmetry functions. This also makes the colors symmetric as well as the shape.

8FilteringAliasing in spatial and temporal directions is visually disturbing and also indicates information loss because one cannot tell if an artifact in the image is an
original or an alias. With anti-aliasing, there is no ambiguity.
The chaos game lends itself to anti-aliasing. Consider spatial aliasing first,
that is the elimination of the jaggie edges. The normal technique is to draw

11

a

b

c

d

Figure 5: Examples of symmetry. Image d shows how the colors wash out
without special treatment of the color coordinate for symmetry transforms.
the desired image at high resolution, and then filter it down to display resolution. This is known as supersampling, and its cost is linear in time and memory(though the sampling is normally applied in two dimensions, so 3 by 3 supersampling means 9x). With the chaos game however we can achieve this effectby just increasing the number of buckets used in the histogram without increasing the number of iterations. There is a small, sublinear cost in time thoughbecause the time spent filtering is significant, and the increased memory usage
also means increased cache misses during iteration. The effect on visual quality,
however, is dramatic. Gamma correction should be done at this filtering step,when the maximum number of bits of precision is still available.
Despite this filtering, the logarithm and gamma factor may cause low-density
parts of an image to appear dotted or noisy. A wider filter would solve this, but
at the expense of making the well-sampled parts of the image blurry. This canbe addressed with a form of Density Estimation [5]. We have implemented a
dynamic filter where a blur kernel of width inversely proportional to the densityof points in the histogram is applied to the samples [6]. The blur kernel is scaled
based on the supersampling level, and is applied after the log density scaling.
This variable width filter allows higher density areas to remain in focus, while
lower density areas are significantly smoothed. Figure 6 illustrates the effect ofdensity estimation.

12

a

b

c

Figure 6: Demonstration of density estimation: (a) a low-resolution, low-quality,
zoomed image rendered without density estimation, and (b) with density estimation, and (c) a high quality render at high resolution with density estimation.

9

Motion Blur

Motion blur, or temporal anti-aliasing, is not so easy to do correctly. Supersampling can be achieved by varying the parameters over time while runningthe chaos game. That is, if 5M samples are used to draw the frame at time t,
to instead use 1M samples at time t-0.5, 1M samples at t-0.25, 1M at t, 1M at
t+0.25 and 1M at t+0.5, all the while accumulating into the same buffer. Thatwould be 5x supersampling for free! With linear density display, this would
work exactly.
The non-linearity of the logarithm complicates things. Consider a pixel
with density 8. Assume for simplicity the logarithm is base 2, so its assigned
brightness is 3. Now put the fractal in motion so it blurs across two pixels, eachshould get brightness 1.5. But if the motion takes place before the logarithm
then the 8 samples would be divided into two pixels of density 4 each, whose
logarithm is 2, not 1.5. Objects in motion would appear unnaturally bright.
A proper solution requires the use of an extra buffer: the first buffer islinear and accumulates the histogram. After each temporal sample, take thelogarithm of this buffer and accumulate it into the second one, applying thedensity estimation filter in the process. After all samples are completed, thesecond buffer is filtered down into the final image.
The drawback of this approach, however, is the computational effort required
to apply the density estimation filter repeatedly to the linear buffer; multiple
applications of the filter can easily double the rendering time.
After experiments with a single buffer yielded acceptable results, we decided
to default to single buffer renders, while retaining the option of using the extra
buffer.

9.1

Directional Motion Blur

Uniformly distributing the samples among time steps works well for an animatedseries of frames, but the illusion of motion of an individual frame animation may
be improved by providing a sense of direction. Early attempts at directional
13

a

b

Figure 7: (a) motion blur and (b) directional motion blur.
motion varied the number of samples used at each time step, but since thedensity estimation filter was more aggressive during less dense time steps, theresult appeared unnatural.
Instead, the color of points accumulated during earlier time steps are scaled
in intensity, with the scaling constant approaching 1.0 as the time steps progress.
A rendering parameter can be supplied to the renderer to change how aggressively the blending varies throughout the time steps. See the effects of directionalmotion blur in Figure 7.

10

History and Acknowledgements

In 1987 at Brown University Bill Poirier showed Scott Draves what he called‘Recursive Pictures’ a kind of two-dimensional IFS. Poirier used a formulationthat included perspective transforms, but lacked a software implementation. In
response Draves created the first of many IFS algorithms. It was written in
Postscript and ran on the Laserwriter, producing high resolution line drawings.
Draves reimplemented this idea in a variety of ways over the three years hespent in the Computer Graphics Research Group at while still at Brown.
The first implementation to include all three definitive characteristics offractal flames (non-linear variations, log-density display, and structural coloring)
was created in the summer of 1991 while Draves was an intern at the NTT-Data
Corporation in Tokyo, Japan and was generously allowed to pursue his own
projects.
That version was released on the then-nascent world wide web in 1992 under
the General Public License (GPL), making it the first open-source art. It has
since been incorporated into and ported to many environments, including theGimp, Photoshop (as Kai’s Power Tools FraxFlame), After Effects, Digital Fusion, Ultra Fractal 3, screensavers for Macintosh, Windows, and Linux, as well14

as stand-alone programs (Apophysis, Oxidizer, and Qosmic).
The combined-channel gamma feature and the vibrancy parameter that controls it were introduced in 2001. The symmetries were introduced in 2003. Variations 7 to 12 were developed by Ronald Hordijk for his screen-saver version of
the flame algorithm, then ported to the Ultra Fractal version by Erik Reckase,and adopted into the original version (with some modifications) by Draves in
2003.
In 2004, Mark Townsend released Apophysis, a translation of Draves’ Ccode into Delphi Pascal, with the addition of a GUI for interactive design. Erik
Reckase became more involved with the flame algorithm after the release of
Apophysis, and became an official developer and maintainer in 2005. Reckase’scontributions have focused on improved image quality, code optimization, andkeeping up with the wealth of variations being developed in the Apophysis
community.
In 2006 Peter Sdobnov added final transforms to Apophysis and they weresoon after adopted by our implementation to maintain compatibility.
Thanks to Hector Yee for suggesting tone mapping as the general solution to
the dynamic range problem, and David Hart for suggesting density estimation
as an improved filter technique.
The fractal flame algorithm is also the seed that spawned the Electric Sheep
distributed screen-saver [2], a follow-on art project by Draves. In this system,
thousands of idle computers from all over the world are harnessed into rendering(and evolving) fractal flames. The work of all participating clients is sharedalike.

References[1] Michael Barnsley: Fractals Everywhere. Academic Press, San Diego, 1988.
[2] Scott Draves. The Electric Sheep Screen-Saver: A Case Study in Aesthetic
Evolution. Applications of Evolutionary Computing, LNCS 3449, 2005.
[3] Hutchinson, J. Fractals and Self-Similarity. Indiana University Journal of
Mathematics. 30, 713-747, 1981.
[4] Jack Tumblin, Holly Rushmeier. Tone Reproduction for Realistic Images.
IEEE Computer Graphics and Applications. November/December 1993
(Vol. 13, No. 6) pp. 42-48.
[5] B. W. Silverman, Density Estimation for Statistics and Data Analysis,
Chapman and Hall, London, 1986.
[6] F. Suykens and Y. D. Willems. Adaptive filtering for progressive Monte
Carlo image rendering. In Eighth International Conference in Central Europe on Computer Graphics, Visualization and Interactive Digital Media(WSCG 2000), Plzen, Czech Republic, February 2000.

15

Appendix: Catalog of Variations
For each variation we give its formula and its name, and provide a list of parameters for parametric variations. Variables used in these formulas are:pr =x2 + y 2
θ = arctan(x/y)φ = arctan(y/x)(a, b, c, d, e, f ) are considered to be the affine transform coefficients for avariation, and are used in dependent variations. Ω is a random variable that iseither 0 or π. Λ is a random variable that is either -1 or 1. Ψ is a random variableuniformally distributed on the interval [0, 1]. The ’trunc’ function returns theinteger part of a floating-point value.
A visualization of the distorted coordinate grid and a representative flameusing this variation are also supplied. As in Figure 2, x and y increase towards
the lower right, to match the coordinate system of the output image. Note thatthese sample flames are selected based on their characteristic shape and not
for any aesthetic qualities. The representative images attempt to use a single
variation, but in general, variations can be mixed when creating flames. For
random-based variations, a scatterplot is substituted for the coordinate grid.

Linear (Variation 0)
V0 (x, y) = (x, y)16

Sinusoidal (Variation 1)
V1 (x, y) = (sin x, sin y)

Spherical (Variation 2)
V2 (x, y) =1
· (x, y)r2

17

Swirl (Variation 3)V3 (x, y) = x sin(r2 ) − y cos(r2 ), x cos(r2 ) + y sin(r2 )Horseshoe (Variation 4)
V4 (x, y) =1
· ((x − y)(x + y), 2xy)r

18

Polar (Variation 5)
V5 (x, y) =θ,r − 1π

Handkerchief (Variation 6)
V6 (x, y) = r · (sin(θ + r), cos(θ − r))

19

Heart (Variation 7)
V7 (x, y) = r · (sin(θr), − cos(θr))

Disc (Variation 8)
V8 (x, y) =θ· (sin(πr), cos(πr))π

20Spiral (Variation 9)
V9 (x, y) =1(cos θ + sin r, sin θ − cos r)rHyperbolic (Variation 10)
V10 (x, y) =



sin θ
, r cos θr21Diamond (Variation 11)
V11 (x, y) = (sin θ cos r, cos θ sin r)

Ex (Variation 12)
p0 = sin(θ + r), p1 = cos(θ − r)

V12 (x, y) = r · (p30 + p31 , p30 − p31 )22

Julia (Variation 13)
V13 (x, y) =√r · (cos(θ/2 + Ω), sin(θ/2 + Ω)(Note: The grid visualization for the julia variation only includes data forΩ = 0.)

Bent (Variation 14)
(x, y)

(2x, y)V14 (x, y) =(x, y/2)(2x, y/2)23x ≥ 0, y ≥ 0
x < 0, y ≥ 0
x ≥ 0, y < 0
x < 0, y < 0Waves (Variation 15) - dependent
V15 (x, y) =

x + b sinyc2

, y + e sin

Fisheye (Variation 16)
Note the reversed order of x and y in the formula.
V16 (x, y) =2
· (y, x)
r+1

24



x
f2



Popcorn (Variation 17) - dependent
V17 (x, y) = (x + c sin(tan 3y), y + f sin(tan 3x))Exponential (Variation 18)
V18 (x, y) = exp(x − 1) · (cos(πy), sin(πy))

25Power (Variation 19)
V19 (x, y) = rsin θ · (cos θ, sin θ)

Cosine (Variation 20)
V20 (x, y) = (cos(πx) cosh(y), − sin(πx) sinh(y))

26Rings (Variation 21) - dependentV21 (x, y) = (r + c2 ) mod (2c2 ) − c2 + r(1 − c2 ) · (cos θ, sin θ)

Fan (Variation 22) - dependentt = πc2
V22 (x, y) =r · (cos(θ − t/2), sin(θ − t/2))
r · (cos(θ + t/2), sin(θ + t/2))27(θ + f ) mod t > t/2(θ + f ) mod t ≤ t/2

Blob (Variation 23) - parametricp1 = blob.high, p2 = blob.low, p3 = blob.wavesp1 − p2(sin(p3 θ) + 1) · (cos θ, sin θ)
V23 (x, y) = r · p2 +2

PDJ (Variation 24) - parametricp1 = pdj.a, p2 = pdj.b, p3 = pdj.c, p4 = pdj.d
V24 (x, y) = (sin(p1 y) − cos(p2 x), sin(p3 x) − cos(p4 y))28

Fan2 (Variation 25) - parametric
Fan2 was created as a parametric alternative to Fan.
p1 = π(fan2.x)2 , p2 = fan2.yt = θ + p2 − p1 trunc(
V25 (x, y) =



2θp2
)
p1

r · (sin (θ − p1 /2) , cos (θ − p1 /2))r · (sin (θ + p1 /2) , cos (θ + p1 /2))

29

t > p1 /2t ≤ p1 /2

Rings2 (Variation 26) - parametric
Rings2 was created as a parametric alternative to Rings.
p = (rings2.val)2
r+p
t = r − 2ptrunc+ r(1 − p)
2p
V26 (x, y) = t · (sin θ, cos θ)Eyefish (Variation 27)
Eyefish was created to correct the order of x and y in Fisheye.
V27 (x, y) =2
· (x, y)r+1

30

Bubble (Variation 28)
V28 (x, y) =4
r2 + 4· (x, y)Cylinder (Variation 29)
V29 (x, y) = (sin x, y)31Perspective (Variation 30) - parametricp1 = perspective.angle, p2 = perspective.distp2· (x, y cos p1 )V30 (x, y) =p2 − y sin p1

Noise (Variation 31)
V31 (x, y) = Ψ1 · (x cos(2πΨ2 ), y sin(2πΨ2 ))32

JuliaN (Variation 32) - parametricp1 = juliaN.power, p2 = juliaN.dist
p3 = trunc(|p1 |Ψ)t = (φ + 2πp3 )/p1
p2

V32 (x, y) = r p1 · (cos t, sin t)

JuliaScope (Variation 33) - parametricp1 = juliaScope.power, p2 = juliaScope.dist
p3 = trunc(|p1 |Ψ)t = (Λφ + 2πp3 )/p1
p2

V33 (x, y) = r p1 · (cos t, sin t)

33

Blur (Variation 34)
V34 (x, y) = Ψ1 · (cos(2πΨ2 ), sin(2πΨ2 ))Gaussian (Variation 35)
Summing 4 random numbers and subtracting 2 is an attempt at approximating
a Gaussian distribution.
!
4X
V35 (x, y) =Ψk − 2 · (cos(2πΨ5 ), sin(2πΨ5 ))k=1

34

RadialBlur (Variation 36) - parametrict1 = v36 (

4
X

k=1

p1 = (radialBlur.angle) · (π/2)Ψk − 2), t2 = φ + t1 sin p1 , t3 = t1 cos p1 − 1

V36 (x, y) =1
· (r cos t2 + t3 x, r sin t2 + t3 y)v36

Pie (Variation 37) - parametricp1 = pie.slices, p2 = pie.rotation, p3 = pie.thickness
t1 = trunc(Ψ1 p1 + 0.5)2π
(t1 + Ψ2 p3 )t 2 = p2 +p1
V37 (x, y) = Ψ3 (cos t2 , sin t2 )35

Ngon (Variation 38) - parametricp1 = ngon.power, p2 = 2π/ngon.sides, p3 = ngon.corners, p4 = ngon.circle
t3 = φ − p2 ⌊φ/p2 ⌋t3
t3 > p2 /2
t4 =t3 − p2 t3 ≤ p2 /2
p3 cos1 t4 − 1 + p4
k=rp1
V38 (x, y) = k · (x, y)36Curl (Variation 39) - parametricp1 = curl.c1, p2 = curl.c2
t1 = 1 + p1 x + p2 (x2 − y 2 ), t2 = p1 y + 2p2 xy
V39 (x, y) =1

· (xt1 + yt2 , yt1 − xt2 )t21 + t22

Rectangles (Variation 40) - parametricp1 = rectangles.x, p2 = rectangles.yV40 (x, y) = (2⌊x/p1 ⌋ + 1)p1 − x, (2⌊y/p2 ⌋ + 1)p2 − y)37Arch (Variation 41)
V41 (x, y) = (sin(Ψπv41 ), sin2 (Ψπv41 )/ cos(Ψπv41 ))Tangent (Variation 42)
V42 (x, y) =



sin x
, tan y
cos y

38



Square (Variation 43)
V43 (x, y) = (Ψ1 − 0.5, Ψ2 − 0.5)

Rays (Variation 44)
V44 (x, y) =v44 tan(Ψπv44 )· (cos x, sin y)r2

39Blade (Variation 45)
V45 (x, y) = x · (cos(Ψrv45 ) + sin(Ψrv45 ), cos(Ψrv45 ) − sin(Ψrv45 ))Secant (Variation 46)
V46 (x, y) =



x,

1
v46 cos(v46 r)

40Twintrian (Variation 47)

t = log10 sin2 (Ψrv47 ) + cos(Ψrv47 )V47 (x, y) = x · (t, t − π sin(Ψrv47 ))Cross (Variation 48)
V47 (x, y) =p1/(x2 − y 2 )2 · (x, y)41