L-systems (or Lindenmayer systems) use a parallel rewriting systeem. It's a formal grammer meaning it consists of an alphabet to make strings. Productions rules are used to iterate over a string, expanding it into a larger string. The more iterations, the more complex your string becomes. When iterating over the string to render, each symbol in the alphabet represents an action, either drawing, rotating, or saving a state.
My alphabet is as follows:
And here are the results:
As an example, here is the L-system I created.
In the first iteration we'd end up with "ff[^B][++++^B][----^B]" which only draws 1 branch units. But after that it starts to get very complex very quickly: "ff[^f[^Al][+++^Al][---^Al][++++++^Al]][++++^f[^Al][+++^Al][---^Al][++++++^Al]][----^f[^Al][+++^Al][---^Al][++++++^Al]]". But if you keep in mind the general concept, you can realize it's just a trunk with 3 branches, and each branch has 4 of its own, which each has a leaf on the end of it.
L-Systems ended up being much more complex than I anticipated. On the surface it seem complex, then when first researching it it starts to make sense, only to find another layer of complexity. At the heart is algorithmic hierarchical modeling. The braches are all composed of cylinders of a fixed size and the leaves are transformed cubes. I added a trig function to the branching angle (the angle is the same for any rotation axis) to create a swaying effect, and in the case of the third tree and kind of blooming effect. I also added color changing in the leaves based on trig functions by pressing E. I added the option to change the branching angle using R and F, change how much it sways using T and G, or disable swaying all together with Z. You can switch between tree types using Q and by doing so you reset the branching and swaying angle back to default. Here is a link to a video showing these effects in action.
References: