p5.js Code Examples: The Creative Surrender: Patterns Drawn by Unpredictable Formulas
Is there any point in combining mathematical formulas that have no specific meaning or purpose, and then drawing shapes based on them?
I don't know. But I find it incredibly fun! 😊
The surprise and excitement of seeing shapes rendered from seemingly meaningless equations—shapes that I could never have imagined myself!
I'll introduce this enjoyment through code using p5.js in this post.
Calculating and Drawing X, Y Coordinates with Equations
Let's consider code that calculates x and y coordinates using a mathematical formula and then plots points at those locations.
A "circle" is a great example. If you calculate the x and y coordinates using the following formulas, the resulting shape is a circle.
let x = r * cos(t);
let y = r * sin(t);
The idea is: what if we simply vary the formulas used to calculate these x and y coordinates? That's where things get interesting.
Experimenting with Different Formulas
For example, if we modify the circle-drawing formulas like this...
let x = r * cos(t);
let y = r * sin(t * 2);
You get what's known as a Lissajous curve.
Lissajous Curve: Wikipedia
Simply changing the ratio of the coefficients (e.g., 3:2 or 3:5) generates entirely different patterns.
let x = r * cos(t * 3);
let y = r * sin(t * 2);
let x = r * cos(t * 3);
let y = r * sin(t * 5);
Abandoning Intent: Enjoying the Unpredictable
To keep the drawing within the canvas boundaries, it's desirable to use formulas that return values within a certain range. sin() and cos() are perfect for this, as they return values between -1 and 1.
Many formulas can return values between -1 and 1. What happens if we use a more complex one, like this?
let x = r * cos(PI * (sin(PI * t) + 0.5));
let y = r * sin(PI * (t + 0.5)) * cos(PI * t * 0.5);
We've suddenly introduced a rather complicated formula, but please treat it as a black box for now—just acknowledge that it's a long equation. The resulting drawing is as follows.
Here's the key: you are not imagining the result first and then designing the formula to achieve it. You simply focus on writing a formula that returns values in the -1 to 1 range, without considering what the result will be.
This approach gives you the pleasure of being surprised by the outcome of your own code—an outcome often beyond your imagination. (Although, sometimes the result is far less interesting than you might hope...)
The Code Example
In this code, we calculate the x and y coordinates using polar coordinates, deriving the radius (r) and angle (t) from mathematical formulas.
Furthermore, by increasing the changing parameters to two (pA and pB), we control the drawing with a double loop. This transforms the single line seen so far into "multiple lines drawn, each slightly changing shape."
The parameter values fed into the formulas are randomized, ensuring that a unique, random result is drawn every time the code is executed.
/*
* p5.js Code Example
* Drawing shapes from meaningless math.
*
* @author @deconbatch
* @version 0.1
* @license CC0 1.0 https://creativecommons.org/publicdomain/zero/1.0/deed.ja
* p5js 2.0.0
* created 2025.12.08
*/
function setup() {
const CANVAS_SIZE = 640;
// Parameters that determine the curve's shape. Initial values are set randomly.
const A_FROM = random(-1, 1);
const B_FROM = random(-1, 1);
const A_TO = A_FROM + random(0.3, 0.5);
const B_TO = B_FROM + random(0.3, 0.5);
const A_STEP = 0.005;
const B_STEP = 0.1;
createCanvas(CANVAS_SIZE, CANVAS_SIZE);
noFill();
stroke("MidnightBlue");
strokeWeight(1);
background("CornSilk");
translate(width * 0.5, height * 0.5);
// Outer loop. A change in pA results in a major change/shift in the entire line.
for (let pA = A_FROM; pA < A_TO; pA += A_STEP) {
beginShape();
// Inner loop. The variable that determines the angle of individual points forming the line (shape).
for (let pB = B_FROM; pB < B_TO; pB += B_STEP) {
let r = CANVAS_SIZE * 0.5 * calcRadiusFactor(pA, pB);
let t = PI * calcAngleFactor(pA, pB);
let x = r * cos(t);
let y = r * sin(t);
vertex(x, y);
}
endShape();
}
}
/**
* A meaningless formula that determines the 'variation rate' of the radius.
* Return value is in the range of -1 to 1. This is multiplied by the radius to fit it on the canvas.
*/
function calcRadiusFactor(_pA, _pB) {
return cos(PI * (sin(TWO_PI * _pA * _pB) + _pB));
}
/**
* A meaningless formula that determines the angle.
* Return value is in the range of -1 to 1. This is multiplied by PI to be used as an angle (from -PI to PI).
*/
function calcAngleFactor(_pA, _pB) {
return sin(PI * (_pA + _pB)) * cos(PI * _pA * _pB);
}
By refining and further expanding upon this technique, I was able to achieve expressions like the ones shown below:
Oh my, how scandalous! Ohohoho!🤭#processing #creativecoding pic.twitter.com/CDGWpzDNOV
— deconbatch (@deconbatch) December 6, 2025
Four Designs for the Trumpet of the Apocalypse 📯#processing #creativecoding pic.twitter.com/Z9fsKGfozE
— deconbatch (@deconbatch) December 3, 2025
Moire Jellyfish 🪼#processing #creativecoding pic.twitter.com/3CFC7bQ7lQ
— deconbatch (@deconbatch) December 3, 2025
Conclusion 💡
The code presented here offers the enjoyment of not knowing what you're going to create. This is truly one of the greatest pleasures of creative coding.
Instead of the approach, "I want to create this, therefore I must write this code," the ethos of creative coding is: "What will be created if I write this code?" This freedom of exploration is what makes it so rewarding.








