---
title: "A forest in one line, but not a thousand free trees"
locale: "en"
url: "https://irz.fr/en/articles/p5-strands-instancing-one-line-en"
markdown_url: "https://irz.fr/en/articles/p5-strands-instancing-one-line-en.md"
category: "creative"
tags: ["p5.js", "p5.strands", "creative coding", "GPU", "instancing", "Processing"]
published_at: "2026-08-21T16:00:00.000Z"
author: "Jules Garnier"
translation: "https://irz.fr/fr/articles/p5-strands-instancing-one-line-fr.md"
---

# A forest in one line, but not a thousand free trees

p5.strands is preparing an API where one line can launch hundreds of instances. The speedup comes from shared geometry and fewer draw calls, not free rendering.

“Drawing a forest in one line” first reads like demo-day magic: take a long-established GPU technique, compress its syntax and let the headline imply that the hard part disappeared. In this case the syntax compression is the work worth examining.

With a Processing Foundation microgrant, Akshat Patil worked on a new p5.strands instancing API; his August 10 article captions one demonstration **800 trees, two draw calls**, while the minimal `instances(500).sphere(20)` example submits five hundred spheres through one instanced draw call.[1](https://medium.com/processing-foundation/drawing-a-forest-in-one-line-a-preview-of-instancing-in-p5-strands-a2e93f9c9e04)[3](https://gist.github.com/aashu2006/ca13773766637bb22785f16a475b0be1)

Instancing itself predates the project by a comfortable margin; games and graphics software have used it for grass, crowds, particles, stars and repeated props for years. Patil is dealing with a less glamorous question about access: how much machinery should appear before somebody whose immediate goal is filling a canvas?

The result is API design around an existing GPU technique, where success is measured partly by how little ceremony survives into the final sketch.

## A thousand calls

Imagine a forest where every tree starts from the same base geometry. The naive JavaScript approach loops through the scene, changes a transform, draws one tree, then does the same thing again hundreds or thousands of times.

The picture can be perfectly correct while the submission path remains wasteful, because repeated drawing may create repeated CPU-to-GPU draw instructions. Patil uses the clean pedagogical contrast of 1,000 trees and 1,000 separate submissions versus one shared tree submitted with an instance count.[1](https://medium.com/processing-foundation/drawing-a-forest-in-one-line-a-preview-of-instancing-in-p5-strands-a2e93f9c9e04)

The GPU can then process those copies while an instance index distinguishes one from another. Position, scale, colour and related variation can be calculated from that index in a shader.[1](https://medium.com/processing-foundation/drawing-a-forest-in-one-line-a-preview-of-instancing-in-p5-strands-a2e93f9c9e04)[3](https://gist.github.com/aashu2006/ca13773766637bb22785f16a475b0be1)

> **Same forest, different contract**
> - A sequence of draw submissions repeats the shape.: CPU loop
> - One geometry, an instance count, then per-copy variation on the GPU.: Instancing
> - Trees, grass, stars, crowds or particles.: Same motif
> - Geometry is shared, but every instance still has to be transformed and rasterized.: Different cost
> Instancing mainly reduces draw-call overhead; it does not make pixels free.

That distinction can matter enormously for performance, although no tree becomes free in the process: a thousand instances still contain vertices, cover pixels and run shader work, so dense transparency, expensive materials or heavy geometry can remain expensive after the draw-call overhead falls.

The API shortens the route between artistic intent and an appropriate rendering strategy; the remaining rendering bill still arrives on schedule.

## Before the one-liner

p5.js already supported instancing before this microgrant. The previous route relied on retained geometry: build the shape with `buildGeometry()`, render it with `model()`, then read `instanceID()` in a shader to tell copies apart.[1](https://medium.com/processing-foundation/drawing-a-forest-in-one-line-a-preview-of-instancing-in-p5-strands-a2e93f9c9e04)

For somebody already comfortable with 3D rendering the previous sequence makes sense, whereas a beginner who only wanted five hundred spheres has to learn several renderer concepts before the first batch appears.

The tracking issue makes the access goal explicit: GPU instancing should be easier to discover and use before a learner has mastered the renderer pipeline.[2](https://github.com/processing/p5.js/issues/8911) Processing Foundation describes Patil’s microgrant in similarly practical terms, as work on a **beginner-friendly instancing API** for p5.strands.[5](https://processingfoundation.org/dev/open-source-software-microgrant-program)

The resulting proposal tries to look like ordinary p5.js:

`instances(100).sphere(20)`

`instances(100)` returns a drawable object that exposes familiar primitive methods. Custom shapes follow a related approach, with the proposed design allowing the instance count to travel through `endShape()` rather than forcing beginners into a completely separate workflow.[3](https://gist.github.com/aashu2006/ca13773766637bb22785f16a475b0be1)

> Illustration: Visual example accompanying the new p5.strands instancing API. The API tries to keep instancing inside p5.js's familiar drawing vocabulary instead of leading with renderer plumbing. Credit: [Akshat Patil / Processing Foundation](https://medium.com/processing-foundation/drawing-a-forest-in-one-line-a-preview-of-instancing-in-p5-strands-a2e93f9c9e04).

The instance remains part of the mental model; much of the ceremony required to obtain it has been removed.

## Keep the index

Five hundred copies of a sphere would be rather disappointing if they all occupied the same position. The shader still needs a way to know which copy it is currently processing.

The older API used `instanceID()`, while the new design introduces `instanceIndex` as a value rather than a function call.[2](https://github.com/processing/p5.js/issues/8911)[3](https://gist.github.com/aashu2006/ca13773766637bb22785f16a475b0be1) The GitHub discussion makes a microscopic-looking change much easier to understand.

Dave Pagurek argued that the index behaves more like `width` or `mouseX`: a contextual value rather than an operation. Patil also noted the beginner-level error this avoids, namely forgetting the parentheses on a function whose only job is returning a built-in value.[2](https://github.com/processing/p5.js/issues/8911)

The word changes too. “ID” can suggest a durable unique identifier, while “index” describes the useful mental model here: a number in a sequence. The design proposal notes that the name also aligns with WGSL's `instance_index` builtin and nearby graphics APIs.[3](https://gist.github.com/aashu2006/ca13773766637bb22785f16a475b0be1)

In other words, the API removes a small source of beginner friction without pretending the underlying concept vanished.

A beginner can postpone learning how the instance count moves through renderer internals, but the per-copy index still matters because it is what turns 800 coincident trees into a forest rather than a suspiciously dense single tree.

## Hide the plumbing

p5.strands already makes a similar tradeoff around shader authoring. Its purpose is to let people write shader snippets in JavaScript-like syntax and transform those snippets into shader code.[4](https://p5js.org/contribute/p5.strands/)

The contributor documentation describes a multi-stage pipeline: user pseudo-JavaScript is transformed, executed to build a graph of operations, and that graph is then emitted as GLSL.[4](https://p5js.org/contribute/p5.strands/) The language also borrows shader-friendly conveniences, including vector-like arrays and swizzling, that ordinary JavaScript does not natively provide in the same form.

To be sure, p5.strands does not make a shader literally **become** JavaScript; it provides a familiar façade and postpones how much graphics-specific language creators need before making something visible.

The instancing API applies the same philosophy one level higher, choosing an instanced draw that matches the requested repetition rather than making draw calls mysteriously cease to exist.

> **What the one line hides**
> - Define the shape shared by every copy.: Geometry
> - Tell the GPU how many copies to produce.: Instances
> - Expose a number for each copy inside shader code.: Index
> - Change position, size or colour without duplicating the model.: Variation
> The syntax can be short because the mental model underneath remains coherent.

A useful abstraction decides which technical concept still deserves to reach the person using the tool instead of erasing everything behind one convenient method.

## Most of it was talking

The most revealing part of Patil’s article has little to do with the GPU: relatively little time went into the final implementation, he says, while most of the project involved reading renderer internals, studying other libraries, drawing options in tldraw, writing proposals and discussing decisions through Discord and GitHub.[1](https://medium.com/processing-foundation/drawing-a-forest-in-one-line-a-preview-of-instancing-in-p5-strands-a2e93f9c9e04)

The public tracking issue matches that account. Completed work includes the `instanceIndex` change, the `instances(count)` object, integration with primitive rendering paths, WebGL and WebGPU tests, documentation and examples.[2](https://github.com/processing/p5.js/issues/8911)

Even the name and shape of `instanceIndex` changed through review.[2](https://github.com/processing/p5.js/issues/8911) The final interface is supposed to look unsurprising, which is an underrated achievement for an API aimed at beginners.

Visible simplicity creates design work elsewhere, because every removed step still needs a rule covering primitives, custom geometry, zero instances, backend behaviour and compatibility with sketches that already use `instanceID()`.

The one-liner is the end product of complexity negotiated before the user arrives.

## Not 2.4 yet

Patil's August 10 article says the new API is merged and is intended to land in **p5.js 2.4**.[1](https://medium.com/processing-foundation/drawing-a-forest-in-one-line-a-preview-of-instancing-in-p5-strands-a2e93f9c9e04)[3](https://gist.github.com/aashu2006/ca13773766637bb22785f16a475b0be1) On August 21, the future tense still matters: the latest stable release listed by the project is **v2.3.2**, published July 30.[6](https://github.com/processing/p5.js/releases)

As of August 21, copying `instances(500).sphere(20)` into the stable p5.js release therefore belongs to preview territory rather than to guaranteed production documentation.

Issue #8911 was closed on July 30 and its planned work is marked complete, but “merged into the project” and “available in the latest stable version” are different states.[2](https://github.com/processing/p5.js/issues/8911)[6](https://github.com/processing/p5.js/releases)

The finished work is sufficient to evaluate the design; calling the preview a released stable API can wait for the release that actually carries it.

## The right shortcut

Two readings miss what a creative-coding library is for: one treats the one-liner as though the GPU stopped rendering a thousand trees, while the other dismisses the project because instancing itself is old.

A library in this space makes capabilities **possible**, but it also decides when they become **approachable without prior graphics-programming training**; p5.strands works at that boundary by providing enough familiar syntax for a quick result while leaving enough of the underlying model visible to keep the result editable.

The future `instances(500).sphere(20)` hides repeated draw submissions while keeping the instance count visible, and `instanceIndex` removes an awkward API detail while preserving the fact that every copy has a position in a sequence.

By contrast with an abstraction that hides everything, this one removes administrative work and leaves the interesting decision in front of the artist.

An artist should not need to write a thousand draw calls to make a forest; what remains is the part worth spending time on, deciding what makes one tree different from the next.

## References

1. [Akshat Patil, Drawing a Forest in One Line: A Preview of Instancing in p5.strands, Processing Foundation, August 10 2026](https://medium.com/processing-foundation/drawing-a-forest-in-one-line-a-preview-of-instancing-in-p5-strands-a2e93f9c9e04)
2. [processing/p5.js issue #8911, p5.strands Instancing API improvements](https://github.com/processing/p5.js/issues/8911)
3. [Akshat Patil, p5.strands Instancing API design proposal](https://gist.github.com/aashu2006/ca13773766637bb22785f16a475b0be1)
4. [p5.js contributor docs, p5.strands Overview](https://p5js.org/contribute/p5.strands/)
5. [Processing Foundation, Open Source Software Microgrants Program](https://processingfoundation.org/dev/open-source-software-microgrant-program)
6. [processing/p5.js releases](https://github.com/processing/p5.js/releases)
