L-Systems and Procedural Growth
A forest artist has a problem of scale: a single hero tree can be sculpted by hand, but a
wood of ten thousand ferns, saplings and grasses cannot. Modelling each blade individually
would take a lifetime, and if every plant looked identical the eye would instantly cry "copy-paste".
What we want is a tiny recipe that, run over and over, grows an endless variety of
believable plants — and, better still, one we can play forwards so a seedling visibly sprouts
into a bush on screen.
That recipe is an L-system. Invented in 1968 by the Hungarian biologist
Aristid Lindenmayer to model how algae and simple plants divide, it is one of the
most beautiful ideas in procedural graphics: a handful of text-rewriting rules that, iterated, produce
the branching, self-similar structure of living things. This page builds the machine from the string
up, teaches the turtle that turns strings into drawings, and shows how to make a plant
grow over time.
It belongs to the procedural-generation strand of the
Computer Animation
course, alongside its siblings
noise and fractal terrain
and
particle systems.
The machine: alphabet, axiom, rules
An L-system rewrites strings of symbols. It has three parts, and that is genuinely all of it.
- An alphabet — the set of symbols that may appear in the string (for a plant,
letters like A, B,
F and the punctuation +\,-\,[\,]).
- An axiom — the starting string, the "seed" the whole structure grows from.
- A set of production rules, each of the form
\text{symbol} \to \text{replacement string}, telling you what every
symbol becomes in the next generation.
One iteration means: scan the current string and replace every symbol at once by the
right-hand side of its rule (a symbol with no rule stands still). Do it again on the result, and
again. Because the same rules fire everywhere simultaneously, the same little motif reappears at every
scale — that is exactly the self-similarity of a branch that looks like the whole tree.
The crucial twist: rewriting is parallel
This is what separates an L-system from an ordinary grammar. A normal (Chomsky) grammar rewrites
one symbol per step, chosen sequentially. An L-system rewrites all of
them in the same step — the way every cell of a growing organism divides at once, not one
after another down a queue. Get this wrong and every string you compute afterwards is wrong, so let us
watch it on the tiniest possible example.
Alphabet \{A, B\}, axiom A, rules
A \to AB and B \to A. Applying both
rules to every symbol each generation:
axiom : A
step 1: AB (A -> AB)
step 2: ABA (A -> AB, B -> A)
step 3: ABAAB (A -> AB, B -> A, A -> AB)
Read step 2 carefully: the A becomes AB
and the B becomes A, both in the one
step, so AB \to (AB)(A) = ABA. Now the punchline — the string lengths are
1,\; 2,\; 3,\; 5,\; 8,\; 13,\; \dots
the Fibonacci sequence.
It has to be: an A produces one A and one
B, and a B produces one A,
so the count of A's in the next generation is the total count in this one —
the very recurrence f_{n+1} = f_n + f_{n-1}. A three-line rewrite rule
quietly re-derives Fibonacci. That is the flavour of an L-system: trivial local rules, rich global
structure.
From strings to plants: the turtle
A string of letters is not yet a picture. To draw it we hand the finished string to a
turtle — an imaginary pen with a position and a heading that reads the symbols left
to right as movement commands. The classic vocabulary:
| Symbol | Turtle command |
| F | step forward, drawing a segment |
| + | turn left by a fixed angle |
| - | turn right by a fixed angle |
| [ | push — save position and heading on a stack |
| ] | pop — restore the last saved position and heading |
The bracket pair is the magic that makes branches. When the turtle hits
[ it remembers where it was; it wanders off drawing a limb; and when it
hits the matching ] it teleports straight back to the fork to grow the next
limb from the same spot. Nested brackets give branches-on-branches — a tree. For example, with a turn
angle of about 25^{\circ}, the short string
F [ + F ] F [ - F ] F
draws a trunk (F) that sprouts a left twig
([+F]), continues up (F), sprouts a right twig
([-F]), and finishes the trunk (F). Feed that
same shape back into the rule F \to F[+F]F[-F]F a few times and each
F becomes another little sprig — the whole thing bushes out into the plant
below.
Watching it grow
Here is the identical rule F \to F[+F]F[-F]F from the axiom
F, turtle-drawn at two iteration depths. The left plant has been rewritten
twice; the right plant three times. Nothing changed but the number
of iterations — one extra pass replaces every segment of the left plant with a whole miniature copy of
the left plant, and the silhouette fills in. Deeper iteration, denser plant.
This is also the key to animating growth. If you interpolate the turtle's segment
lengths from the shallow figure toward the deep one — or, in a parametric L-system, advance an
"age" parameter continuously — the plant appears to sprout in real time: a seedling unfurling into a
bush over a few seconds of screen time.
Making them natural: stochastic and parametric L-systems
A single deterministic rule gives a single perfect plant — and a field of clones looks fake. Two
extensions fix this and are the workhorses of production plant generation.
- Stochastic L-system — a symbol has several possible replacements, each
with a probability, and the turtle rolls a die each time it expands one. The same rule now grows a
family of plants that differ in exactly the small, organic ways real plants do.
- Parametric L-system — symbols carry numbers, e.g.
F(\ell) draws a segment of length \ell, and a
rule like F(\ell) \to F(\ell \cdot 1.3) lets branches thicken, lengthen
or age continuously rather than in discrete jumps.
Together they turn the toy machine into something that can dress a whole landscape: scatter a
stochastic-parametric L-system across a terrain with a different random seed and a different age at
each instance, and every plant is unique yet unmistakably the same species.
Two mistakes bite everyone the first time. First: the rewriting is parallel. It is
tempting to sweep left to right and expand each symbol as you meet it — but if you do that on
A \to AB,\ B \to A, the first A you rewrite drops
a fresh B into the string that you then rewrite again in the same
pass, and you get a longer, wrong string. Every symbol must be expanded from the original
generation, all at once — build the new string in a separate buffer and only then swap it in.
Second: iteration explodes. Each pass multiplies the string length (that plant rule
turns one F into five, so the count grows like
5^n). Ten iterations of a modest rule is already millions of symbols and
will freeze your renderer. Always cap the depth — plants look complete by four to six
iterations, and you gain almost nothing visible past that while paying exponentially more.
Yes — L-systems draw famous fractals, not just plants. Take axiom F, rule
F \to F+F--F+F with a turn angle of 60^{\circ},
and no brackets at all: the turtle traces the Koch curve, and three of them arranged
in a triangle make the Koch snowflake. Change the rule to
F \to F-F+F+F-F at 90^{\circ} and you get a
Koch island; a dragon curve, a Sierpiński triangle and the Hilbert space-filling curve are
all just different alphabets and angles. Plants are the headline use, but the turtle-plus-grammar
machine is a general fractal factory.