Barnsley Fern is a fractal set that looks like a shape of a fern. If you plot this and magnify any one part (e.g, the tip of a leaf) you will see the similar shape of the whole leafs wherever you magnify.
The Barnsley Fern is a well-known example of a fractal, a complex geometric shape that exhibits self-similarity. This means that the fern's structure looks similar at various levels of magnification. It closely resembles the shape of an actual fern plant, with its intricate and repetitive patterns.
The Barnsley Fern is generated using a set of mathematical equations, specifically an iterative process known as an iterated function system (IFS). By repeatedly applying these functions to points on a plane, the image of the fern gradually emerges. Each transformation contributes a specific part to the overall structure, such as the stem, the large fronds, and the smaller leaflets.
One of the fascinating properties of the Barnsley Fern is its self-similarity. If you zoom into a specific part of the fern, for instance, the tip of a leaf, you will find that this small section has the same general shape as the entire fern. This recursive pattern repeats infinitely, making the fern a classic example of fractal geometry.
The Barnsley Fern not only demonstrates the beauty of mathematical constructs but also has practical applications in fields such as computer graphics, where fractals are used to generate natural-looking structures and landscapes efficiently.
Build Up Intuition
Before the equations, let's watch the fern grow. The program below runs the same random process that the How it works section describes, and it draws the points as they arrive. Press Start and look at where the points land. The stem, the leaflets and the tip all fill in at the same time, not one after another.
This is how you use (play with) this program
Color Scheme Selector
The color scheme changes only how each point is painted, not where the point goes. So the fern has the same shape under every scheme. Classic Green, Rainbow Gradient and Custom Gradient compute the color from the height y of each point, which makes the vertical build-up of the fern easy to follow.
- Classic Green: Creates a natural-looking fern with varying shades of green
- Rainbow Gradient: Applies a multi-color effect, with colors changing based on position
- Monochrome: Uses a single color with different intensities for depth
- Custom Gradient: Allows you to define your own color transitions
Point Appearance Controls
These three controls change the drawing, not the mathematics, so the program generates the same kind of points whatever you choose. Opacity matters most. Many points land on the same pixel, and a low opacity lets the dense areas look stronger than the sparse ones.
- Points/Frame (100-10000):
- Controls how many points are generated in each animation frame
- Higher values create denser, more detailed ferns but may affect performance
- Lower values create sparser ferns but render more smoothly
- Size (0.5-3.0):
- Adjusts the size of individual points
- Larger sizes create a more bold, abstract look
- Smaller sizes provide more detail and realism
- Opacity (0.1-1.0):
- Controls how transparent each point appears
- Lower values create a soft, ethereal effect
- Higher values make the fern more solid and defined
Fern Structure
Unlike the controls above, these three change the four transformations themselves. So every change clears the canvas and starts a new fern. Width scales the horizontal terms of the maps. Curvature sets the two off-diagonal terms of the main map to +c and -c, and its default 0.04 is the value of the classic fern. Randomness shifts the left and right leaflet maps once, each time the maps are rebuilt, so one fern gets one fixed variation.
- Width (0.3-1.1):
- Modifies the overall spread of the fern
- Lower values create a narrow, compact fern
- Higher values produce a wider, more spread-out pattern
- Curvature (-0.1 to 0.1):
- Affects the main stem's curve
- Positive values curve the fern to the right
- Negative values curve the fern to the left
- Zero creates a straight stem
- Randomness (0-0.1):
- Adds natural variation to the leaflets
- Higher values create more chaotic, organic patterns
- Lower values maintain mathematical precision
Probability Controls
Each new point picks one of the four maps at random, and these four numbers are the chances of each pick. As long as every value is above zero, they do not change the final shape of the fern. They change how fast each part fills in, and so how a partly drawn fern looks.
These controls determine the frequency of different parts of the fern:
- Stem (f1Prob):
- Controls vertical growth
- Higher values create longer, more pronounced stems
- Typically kept small (around 0.01) for natural appearance
- Leaflet (f2Prob):
- Controls the main leaflet generation
- Higher values create fuller, more detailed fronds
- Usually the largest probability (around 0.85)
- Left (f3Prob):
- Controls left-side branching
- Affects the symmetry and density of left-side growth
- Typically balanced with right probability (around 0.07)
- Right (f4Prob):
- Controls right-side branching
- Affects the symmetry and density of right-side growth
- Typically balanced with left probability (around 0.07)
Note: The sum of all probabilities must equal 1.0 for proper generation.
The program divides each value by the sum of the four values before it picks a map. So a set of values that does not add up to exactly 1 still runs, and the program uses their relative sizes. A value of 0 removes that map completely. For example, a Stem value of 0 removes the stem and every smaller copy of the stem inside the leaflets.
Visualization Aids
These options add reference marks and change the drawing method, and none of them moves a point. The Box option draws a fixed frame from x = -3 to 3 and from y = 0 to 15. It is not fitted to the points, and the default fern fills only x = -2.18 to 2.66 and y = 0 to 10.
- Axes: Displays coordinate system for reference
- Box: Shows the bounding box of the fern
- WebGL:
- ON: Better performance, smoother rendering
- OFF: Falls back to Canvas rendering (slower but more compatible)
Control Buttons
Two buttons control the run. Start adds a batch of new points on every animation frame until you press the button again, and the Points/Frame value sets the size of each batch. Clear removes all points, and with Randomness above zero it also creates a new random variation of the leaflet maps.
- Start/Pause: Controls the generation process
- Clear: Resets the visualization to start fresh
Real-time Information
The overlay in the corner of the canvas reports three live values. The point count tells you how far the fern has filled in. The FPS value shows whether the Points/Frame setting is too heavy for your browser.
The display shows:
- Total points generated
- Current rendering speed (FPS)
- Mouse coordinate position
Tips for Creating Different Fern Styles
The three recipes below combine the controls described above. Each recipe starts from the default settings and changes only a few values. So it is easy to see which control causes which change in the picture.
- Natural Look:
- Use default probabilities
- Keep randomness low (0.01-0.02)
- Use Classic Green color scheme
- Abstract Style:
- Increase point size
- Use Rainbow or Custom gradient
- Adjust width and curvature for unique shapes
- Dense Pattern:
- Increase Points/Frame
- Reduce opacity
- Adjust leaflet probability higher
How it works ?
The program above hides the mathematics behind its controls. Let's look at the rule itself. It uses four affine transformations, one random choice per step, and a plot of every position the point visits. The same rule works in a few lines of Octave, as the listing below shows.
The plot below shows the points on the range x = -3 to 3 and y = 0 to 10. The stem starts at the origin and runs straight up. The largest leaflets sit low on each side, and smaller leaflets follow them towards the top. The tip curls to the right and ends near (2.66, 10).

Figure 1. Barnsley fern drawn by the IFS rule. Every leaflet is a smaller copy of the whole fern, and the tip curls to the right.
The stem is a short vertical line : it runs along x = 0 from the origin up to about y = 1.6.The lowest left leaflet is the largest on its side : its tip is near (-2.1, 4.4).The lowest right leaflet starts lower : it leaves the stem below the left one, and its tip is near (2.4, 3.5).The upper part repeats the whole fern : above the lowest pair of leaflets, the same pattern repeats at a smaller size, and it rotates slightly clockwise at each level.
The procedure to plot this as follows.
i) define four sets of 2D transformation equation as follows. (p stands for the coordinate for the current point, m is a 2x2 matrix that is specially created for this transformation, v is 2x1 vector)
tf1 = m1 . p + v1
tf2 = m2 . p + v2
tf3 = m3 . p + v3
tf4 = m4 . p + v4
ii) pick any arbitray points (let's say this point is named as p)
iii) pick one transformation equation out of the 4 equation defined in step i). The probability of the random selection for each transformation equation should be predefined).
iv) transform p with the transformation equation selected at step iii).
v) move the current point to the transformed location and set the new position to the current point (p).
vi) repeat the process iii) ~ v) and plot the point p on the coordinate at each iterations.
Following is the Octave/Matlab code that I wrote as per the procedure described above.
m1 = [0.85 0.04;-0.04 0.85]; v1 = [0.0;1.60];
m2 = [0.2 -0.26;0.23 0.22]; v2 = [0.0;1.60];
m3 = [-0.15 0.28;0.26 0.24]; v3 = [0.0;0.44];
m4 = [0.0 0.0;0.0 0.16]; v4 = [0.0;0.0];
prob = [0.85 0.07 0.07 0.01];
Np = 50000;
p_old = [0.5;0.5];
pList = [p_old'];
for i = 1:Np
r = rand();
if (r < prob(1))
p_new = m1 * p_old + v1;
elseif (r < (prob(1)+prob(2)))
p_new = m2 * p_old + v2;
elseif (r < (prob(1)+prob(2)+prob(3)))
p_new = m3 * p_old + v3;
else
p_new = m4 * p_old + v4;
endif;
pList = [pList;p_new'];
p_old = p_new;
end;
Note : the syntax of if statement of Octave may be a little different from Matlab. I tried this only on Octave, so not sure if this code would work in matlab.
Let's check the listing against the procedure. The four lines m1 to m4 define the four transformations, and prob holds their chances in the same order. In the loop, one call to rand() gives a number between 0 and 1. The if and elseif tests compare it with the running sums of prob. So the first map is picked with probability 0.85, the next two with 0.07 each, and the last with 0.01. The picked map moves the point, and pList collects every position.
Three practical notes apply to the listing. First, the code builds pList but has no plot command, so it draws nothing on its own. A line such as plot(pList(:,1), pList(:,2), 'g.') after the loop gives a plot like Figure 1. Second, endif is Octave syntax, and Matlab needs end in its place. Third, the start point p_old = [0.5;0.5] is about 0.16 away from the fern. Each move shrinks the distance to the fern by a factor of about 0.85 or less, so only the first 15 or so points can sit visibly away from the pattern.
The rule is four affine maps and a random pick : each step moves the point with p = m p + v, using one of the four maps.prob sets the chance of each map : the running sums of prob split the range 0 to 1 into four parts, one per map.The listing needs a plot command : it collects the points in pList, and a plot of pList draws the fern.
Why do four maps draw a fern ?
The procedure works, but it does not say why four small formulas give such a detailed shape. The answer is that each map places one shrunken copy of the whole fern. The four copies together make up the fern exactly. This is the self-similarity that the introduction describes, written as equations.
The table below lists the four maps of the listing. It adds the determinant det of each matrix, which is the factor by which the map scales an area. The last column names the part of Figure 1 that each map produces from the whole fern.
Map | Matrix | Offset | det | prob | Part of the fern |
m1, v1 | [0.85 0.04; -0.04 0.85] | (0, 1.6) | 0.724 | 0.85 | the whole fern above the lowest leaflets, shrunk to 0.85 and turned 2.7 deg clockwise |
m2, v2 | [0.2 -0.26; 0.23 0.22] | (0, 1.6) | 0.104 | 0.07 | the lowest left leaflet |
m3, v3 | [-0.15 0.28; 0.26 0.24] | (0, 0.44) | -0.109 | 0.07 | the lowest right leaflet, as a mirror image |
m4, v4 | [0 0; 0 0.16] | (0, 0) | 0 | 0.01 | the stem |
Let's follow one point to see this. The tip of the fern at (2.66, 9.96) is the fixed point of m1, because m1 maps that point to itself. The map m2 sends the same tip to (-2.06, 4.40), which is the tip of the lowest left leaflet. The map m3 sends it to (2.39, 3.52), the tip of the lowest right leaflet. The base of the stem at (0, 0) goes to (0, 1.6) under m1 and m2, and to (0, 0.44) under m3. So the left leaflet leaves the stem at y = 1.6, and the right leaflet leaves it lower, at y = 0.44. Finally, the map m4 squashes the whole fern onto the line x = 0 between y = 0 and 1.6, which is the stem.
The signs of det tell you more. The map m3 has a negative det, so it flips the fern over as it shrinks it. That is why the right leaflet is a mirror image of the whole fern. The map m4 has det = 0, so it flattens the fern into a line. The largest det belongs to m1, because its copy covers most of the fern.
The probabilities follow from the same numbers. A common choice sets each probability in proportion to |det|, because the map with the larger area needs more points to reach the same density. With the values in the table, that rule gives about 0.77, 0.11, 0.12 and 0. The stem would then never be drawn, because its det is 0. The classic values 0.85, 0.07, 0.07 and 0.01 give the stem a small share and keep the density even. They change how fast each part fills in, but the finished fern has the same shape.
The program at the top of the page uses the same four maps in a different order. Its Stem, Leaflet, Left and Right controls correspond to m4, m1, m2 and m3 of the listing. Its default probabilities 0.01, 0.85, 0.07 and 0.07 are therefore the same values as prob in the listing.
Each map draws one copy of the whole fern : m1 gives the upper fern, m2 and m3 give the lowest leaflets, and m4 gives the stem.The tip is the fixed point of m1 : repeated use of m1 moves every point towards (2.66, 9.96).A negative det means a mirror image : m3 flips the fern, so the right leaflet curls the other way.Probabilities set the density, not the shape : any set of positive values draws the same fern, and |det| is a good starting point for choosing them.