Generative art

Tools for work where chance decides the picture: a seed you control (and that travels inside every PNG), a sheet of variations to choose from, and an export that turns the chosen one into a print-quality PNG, an SVG, or paths for a pen plotter.

On this page · 5 entries

Seed · RandomSeed · NoiseSeed

  • Seed → int
  • RandomSeed(seed)
  • NoiseSeed(seed)

Every sketch has a seed: Random(), RandomGaussian(), Noise(), PVector.Random2D() and list Shuffle() all follow it, so the same seed draws the same picture. The IDE picks one before Setup() — a new one per Run — and shows it in the status bar. RandomSeed(Seed) at the top of Draw() makes every frame repeat the same numbers, so a [Tweak] slider changes only what it controls.

In the IDE. 🎲 next to Run (F6) runs again with a new seed; Sketch → Keep the seed locks it. Every PNG a sketch saves (Save(), SaveFrame()) carries its seed, frame and [Tweak] values inside, and Sketch → Open seed from PNG... brings them back: the same image again. Randomness from new System.Random() or Random.Shared doesn't follow the seed.

Variations sheet Ctrl+Shift+V

Sketch → Variations sheet draws the sketch 9 or 16 times side by side: each with its own seed, its own [Tweak] values (random inside each slider's range) or both, after the first frame or after 1–3 seconds of animation. Click the best one: its seed is locked and its values go back into the running sketch — then Apply tweaks to code writes them into the source. Like a contact sheet for generative work: you choose instead of rolling the dice one Run at a time.

From code. VariationRenderer.Plan(...) makes the list of seeds/values and VariationRenderer.Render(...) draws each one offscreen into a PImage, without touching the running sketch.

Export for print · SVG for plotters Ctrl+Shift+E

File → Export for print redraws the sketch from scratch — same seed and [Tweak] values, after as many frames as you choose — as vectors, so it is sharp at any size. Three outputs:

OutputWhat you get
PNG, 2x–16xA poster-sized PNG rendered band by band, so even 16x never has to fit in memory. Carries the seed and values inside, like every PNG a sketch saves.
SVGThe drawing as vectors for Illustrator, Inkscape or a laser cutter.
SVG for a plotterOne Inkscape layer per stroke color (one pen each), backgrounds dropped, fills turned into outlines, and the strokes reordered — and reversed when that's shorter — so the pen travels as little as possible in the air.
From code. PrintExport.SavePng(factory, seed, tweaks, frames, scale, path), PrintExport.SaveSvg(...) and PlotterSvg.Optimize(svg) are public. Sketches that read pixels back (LoadPixels(), Get()) can't be recorded as vectors; they're exported as pixels at the big size and the IDE says so.

Runnable example: seeded landscapes

A landscape made only with Random() and Noise(): F6 rolls another seed, Ctrl+Shift+V opens the variations sheet, and S saves a PNG you can reopen with Sketch → Open seed from PNG. Test in Dana opens it in the IDE, or paste it into a new tab and press Run. It is also in Sketch → Examples.

C#
// Seeded generative art: same seed, same landscape.
//
// Everything random here comes from Random() and Noise(), which follow the
// sketch's Seed -- so:
//   F6 (🎲)              a new seed (Sketch menu: keep the seed to lock it)
//   Ctrl+Shift+V         the variations sheet: pick the best of 9 or 16
//   S                    save a PNG; it remembers the seed and the sliders
//                        (Sketch > Open seed from PNG... brings them back)
//
// RandomSeed(Seed) at the top of Draw() makes every frame repeat the same
// random numbers, so moving a slider changes only what that slider controls.
public class MySketch : Sketch
{
    [Tweak(2, 8)] int layers = 5;
    [Tweak(0.5f, 6)] float roughness = 2.2f;
    [Tweak(0, 360)] float hue = 215;
    [Tweak(0, 400)] int stars = 160;
    [Tweak] bool sun = true;

    public override void Setup() => Size(800, 500);

    public override void Draw()
    {
        RandomSeed(Seed);

        // Sky: a vertical gradient.
        for (int y = 0; y < Height; y += 4)
        {
float t = y / (float)Height;
FillHSB(hue, 50 - t * 20, 18 + t * 30);
NoStroke();
Rect(0, y, Width, 4);
        }

        // Stars.
        for (int i = 0; i < stars; i++)
        {
float x = Random(Width), y = Random(Height * 0.6f);
Fill(255, Random(80, 230));
Circle(x, y, Random(1, 3));
        }

        // Sun (or moon).
        if (sun)
        {
FillHSB((hue + 180) % 360, 40, 100, 230);
Circle(Random(120, Width - 120), Random(80, 200), Random(60, 120));
        }

        // Mountain layers, back to front: lighter and smoother far away.
        for (int layer = 0; layer < layers; layer++)
        {
float depth = layer / (float)Math.Max(1, layers - 1);
float baseY = Height * (0.45f + depth * 0.4f);
float amp = 60 + depth * 90;
float offset = Random(1000);
FillHSB(hue, 35 + depth * 30, 70 - depth * 55);
BeginShape();
Vertex(0, Height);
for (int x = 0; x <= Width; x += 6)
    Vertex(x, baseY - Noise(offset + x * 0.004f * roughness, layer * 10) * amp * 2 + amp);
Vertex(Width, Height);
EndShape(true);
        }

        Fill(255, 200);
        TextSize(13);
        Text($"seed {Seed}   ·   F6 new seed   ·   Ctrl+Shift+V variations   ·   S save PNG", 14, Height - 14);
    }

    public override void KeyPressed()
    {
        if (Key == 's')
        {
HideTweaks();
SaveFrame($"landscape-{Seed}-####.png");
ShowTweaks();
Println($"Saved landscape-{Seed}-{FrameCount:0000}.png (seed and sliders are inside the PNG)");
        }
    }
}

Runnable example: flow lines for a plotter

Hundreds of strokes following a Noise() field in two colors — export it with Ctrl+Shift+E as an SVG for a plotter (one layer per pen) or as an 8x PNG. Test in Dana opens it in the IDE, or paste it into a new tab and press Run. It is also in Sketch → Examples.

C#
// Plotter-friendly art: only strokes, two pens.
//
// File > Export for print (Ctrl+Shift+E):
//   "Plotter SVG"  one layer per color (= per pen), strokes reordered so the
//                  pen travels as little as possible between them
//   "Big PNG"      2x-16x, drawn again as vectors: sharp at poster size
// Same seed, same drawing -- F6 rolls another one.
public class MySketch : Sketch
{
    [Tweak(50, 900)] int lines = 420;
    [Tweak(10, 160)] int steps = 70;
    [Tweak(0.5f, 6)] float zoom = 2.2f;
    [Tweak(0, 1)] float secondPen = 0.25f;

    public override void Setup()
    {
        Size(700, 500);
        FrameRate(12); // a still drawing: a few frames a second is plenty for the sliders
    }

    public override void Draw()
    {
        RandomSeed(Seed);
        Background(250, 248, 240);
        NoFill();
        StrokeWeight(1);

        for (int i = 0; i < lines; i++)
        {
float x = Random(-50, Width + 50);
float y = Random(-50, Height + 50);
bool red = Random(1) < secondPen;
if (red) Stroke(200, 40, 40); else Stroke(20, 20, 30);

BeginShape();
for (int s = 0; s < steps; s++)
{
    Vertex(x, y);
    float angle = Noise(x / Width * zoom, y / Height * zoom) * TWO_PI * 2;
    x += Cos(angle) * 4;
    y += Sin(angle) * 4;
}
EndShape();
        }
    }

}