Randomness & Noise
Use random() and Perlin noise to generate organic, varied visuals with controlled unpredictability.
random(): uniform random numbers
random(min, max) returns a float chosen uniformly at random in the range [min, max). The result is different every time — including every time you restart the sketch.
void draw() {
// Random position, size, and colour for each dot
float x = random(width);
float y = random(height);
float r = random(4, 30);
fill(random(255), random(100, 200), 180);
noStroke();
ellipse(x, y, r, r);
}
random(n) is shorthand for random(0, n).
To pick a random integer index, use int(random(n)) or floor(random(n)):
color[] palette = { #E63946, #457B9D, #1D3557, #A8DADC };
fill(palette[int(random(palette.length))]);
randomSeed: reproducible results
By default, the random number sequence is different every run. Pass a seed to randomSeed() to lock it to a specific sequence — useful for generating the same layout every time:
void setup() {
size(600, 400);
randomSeed(42); // same sequence every run
background(15);
noStroke();
for (int i = 0; i < 200; i++) {
fill(random(255), random(255), random(255), 150);
float x = random(width);
float y = random(height);
float r = random(5, 40);
ellipse(x, y, r, r);
}
}
Change 42 to any other integer to get a completely different but equally reproducible layout.
noise(): Perlin noise
random() produces “spiky” results — consecutive values can jump wildly. Perlin noise produces a smoothly varying sequence that feels more natural. Processing’s noise() returns a value between 0.0 and 1.0.
float t = 0;
void draw() {
background(20);
float n = noise(t); // 0.0 – 1.0
float x = map(n, 0, 1, 50, width - 50);
fill(100, 180, 255);
noStroke();
ellipse(x, height / 2, 40, 40);
t += 0.01; // step through noise space slowly
}
The key insight: the step size controls how fast the noise changes. Small steps (0.005–0.02) produce slow, smooth movement. Large steps (0.2+) produce jittery, almost-random movement.
noise(x, y): 2D noise field
Pass two arguments to sample a 2D slice of the noise field. Use this to set colours, heights, or positions across a grid:
float SCALE = 0.008; // zoom level of the noise
void setup() {
size(600, 600);
noStroke();
loadPixels();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
float n = noise(x * SCALE, y * SCALE);
float bright = map(n, 0, 1, 0, 255);
pixels[y * width + x] = color(bright * 0.3, bright * 0.5, bright);
}
}
updatePixels();
}
Smaller SCALE values zoom in, producing large smooth blobs. Larger values zoom out, producing finer texture.
noise(x, y, z): animated noise
The third argument adds a time dimension. Increment z each frame to animate the field:
float SCALE = 0.006;
float timeStep = 0;
void draw() {
loadPixels();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
float n = noise(x * SCALE, y * SCALE, timeStep);
float h = map(n, 0, 1, 0, 255);
pixels[y * width + x] = color(h * 0.2, h * 0.6, h);
}
}
updatePixels();
timeStep += 0.005;
}
noiseSeed: reproducible noise
Just like randomSeed(), noiseSeed(n) locks the noise field to a fixed pattern:
noiseSeed(99); // same landscape every run
map(): translating noise into useful ranges
noise() always returns 0–1. The map() function stretches or shrinks that range to whatever you need:
float n = noise(t);
// Map to a y position between 100 and 500
float y = map(n, 0, 1, 100, 500);
// Map to a speed between 0.5 and 4.0
float speed = map(n, 0, 1, 0.5, 4.0);
// Map to a colour channel
float red = map(n, 0, 1, 80, 220);
map(value, fromLow, fromHigh, toLow, toHigh) — memorise this signature.
Full example: noise-based terrain line
A rolling landscape silhouette, updated every frame to scroll left:
float[] terrain;
int POINTS = 200;
float xOff = 0;
void setup() {
size(800, 500);
terrain = new float[POINTS];
}
void draw() {
background(15, 15, 30);
// Build terrain heights from noise
float t = xOff;
for (int i = 0; i < POINTS; i++) {
terrain[i] = map(noise(t), 0, 1, height * 0.3, height * 0.85);
t += 0.018;
}
// Draw filled terrain shape
noStroke();
fill(40, 80, 60);
beginShape();
vertex(0, height);
for (int i = 0; i < POINTS; i++) {
float x = map(i, 0, POINTS - 1, 0, width);
vertex(x, terrain[i]);
}
vertex(width, height);
endShape(CLOSE);
// Draw glowing ridge line
stroke(80, 200, 120);
strokeWeight(2);
noFill();
beginShape();
for (int i = 0; i < POINTS; i++) {
float x = map(i, 0, POINTS - 1, 0, width);
vertex(x, terrain[i]);
}
endShape();
// Scroll by advancing the noise offset
xOff += 0.005;
}
The landscape scrolls because xOff increases each frame, sliding the window through noise space. Every run produces the same initial terrain if you add noiseSeed(1) to setup().
Key takeaways
random(min, max)gives uniformly distributed values; consecutive results can jump anywhere.randomSeed(n)makesrandom()reproducible.noise(x)gives smoothly interpolated values — ideal for organic motion.- Add a second argument
noise(x, y)for 2D fields; a thirdnoise(x, y, z)for animation over time. - Always run noise output through
map()to translate the 0–1 range into useful numbers. noiseSeed(n)fixes the noise field for reproducible generations.