📄 color-systems.md

← Vault

Color Systems

Color Modes

HSB (Recommended for Generative Art)

`javascript

colorMode(HSB, 360, 100, 100, 100);

// Hue: 0-360 (color wheel position)

// Saturation: 0-100 (gray to vivid)

// Brightness: 0-100 (black to full)

// Alpha: 0-100

fill(200, 80, 90); // blue, vivid, bright

fill(200, 80, 90, 50); // 50% transparent

`

HSB advantages:

HSL

`javascript

colorMode(HSL, 360, 100, 100, 100);

// Lightness 50 = pure color, 0 = black, 100 = white

// More intuitive for tints (L > 50) and shades (L < 50)

`

RGB

`javascript

colorMode(RGB, 255, 255, 255, 255); // default

// Direct channel control, less intuitive for procedural palettes

`

Color Objects

`javascript

let c = color(200, 80, 90); // create color object

fill(c);

// Extract components

let h = hue(c);

let s = saturation(c);

let b = brightness(c);

let r = red(c);

let g = green(c);

let bl = blue(c);

let a = alpha(c);

// Hex colors work everywhere

fill('#e8d5b7');

fill('#e8d5b7cc'); // with alpha

// Modify via setters

c.setAlpha(128);

c.setRed(200);

`

Color Interpolation

lerpColor

`javascript

let c1 = color(0, 80, 100); // red

let c2 = color(200, 80, 100); // blue

let mixed = lerpColor(c1, c2, 0.5); // midpoint blend

// Works in current colorMode

`

paletteLerp (p5.js 1.11+)

Interpolate through multiple colors at once.

`javascript

let colors = [

color('#2E0854'),

color('#850E35'),

color('#EE6C4D'),

color('#F5E663')

];

let c = paletteLerp(colors, t); // t = 0..1, interpolates through all

`

Manual Multi-Stop Gradient

`javascript

function multiLerp(colors, t) {

t = constrain(t, 0, 1);

let segment = t * (colors.length - 1);

let idx = floor(segment);

let frac = segment - idx;

idx = min(idx, colors.length - 2);

return lerpColor(colors[idx], colors[idx + 1], frac);

}

`

Gradient Rendering

Linear Gradient

`javascript

function linearGradient(x1, y1, x2, y2, c1, c2) {

let steps = dist(x1, y1, x2, y2);

for (let i = 0; i <= steps; i++) {

let t = i / steps;

let c = lerpColor(c1, c2, t);

stroke(c);

let x = lerp(x1, x2, t);

let y = lerp(y1, y2, t);

// Draw perpendicular line at each point

let dx = -(y2 - y1) / steps * 1000;

let dy = (x2 - x1) / steps * 1000;

line(x - dx, y - dy, x + dx, y + dy);

}

}

`

Radial Gradient

`javascript

function radialGradient(cx, cy, r, innerColor, outerColor) {

noStroke();

for (let i = r; i > 0; i--) {

let t = 1 - i / r;

fill(lerpColor(innerColor, outerColor, t));

ellipse(cx, cy, i * 2);

}

}

`

Noise-Based Gradient

`javascript

function noiseGradient(colors, noiseScale, time) {

loadPixels();

for (let y = 0; y < height; y++) {

for (let x = 0; x < width; x++) {

let n = noise(x noiseScale, y noiseScale, time);

let c = multiLerp(colors, n);

let idx = 4 (y width + x);

pixels[idx] = red(c);

pixels[idx+1] = green(c);

pixels[idx+2] = blue(c);

pixels[idx+3] = 255;

}

}

updatePixels();

}

`

Procedural Palette Generation

Complementary

`javascript

function complementary(baseHue) {

return [baseHue, (baseHue + 180) % 360];

}

`

Analogous

`javascript

function analogous(baseHue, spread = 30) {

return [

(baseHue - spread + 360) % 360,

baseHue,

(baseHue + spread) % 360

];

}

`

Triadic

`javascript

function triadic(baseHue) {

return [baseHue, (baseHue + 120) % 360, (baseHue + 240) % 360];

}

`

Split Complementary

`javascript

function splitComplementary(baseHue) {

return [baseHue, (baseHue + 150) % 360, (baseHue + 210) % 360];

}

`

Tetradic (Rectangle)

`javascript

function tetradic(baseHue) {

return [baseHue, (baseHue + 60) % 360, (baseHue + 180) % 360, (baseHue + 240) % 360];

}

`

Monochromatic Variations

`javascript

function monoVariations(hue, count = 5) {

let colors = [];

for (let i = 0; i < count; i++) {

let s = map(i, 0, count - 1, 20, 90);

let b = map(i, 0, count - 1, 95, 40);

colors.push(color(hue, s, b));

}

return colors;

}

`

Curated Palette Library

Warm Palettes

`javascript

const SUNSET = ['#2E0854', '#850E35', '#EE6C4D', '#F5E663'];

const EMBER = ['#1a0000', '#4a0000', '#8b2500', '#cd5c00', '#ffd700'];

const PEACH = ['#fff5eb', '#ffdab9', '#ff9a76', '#ff6b6b', '#c94c4c'];

const COPPER = ['#1c1108', '#3d2b1f', '#7b4b2a', '#b87333', '#daa06d'];

`

Cool Palettes

`javascript

const OCEAN = ['#0a0e27', '#1a1b4b', '#2a4a7f', '#3d7cb8', '#87ceeb'];

const ARCTIC = ['#0d1b2a', '#1b263b', '#415a77', '#778da9', '#e0e1dd'];

const FOREST = ['#0b1a0b', '#1a3a1a', '#2d5a2d', '#4a8c4a', '#90c990'];

const DEEP_SEA = ['#000814', '#001d3d', '#003566', '#006d77', '#83c5be'];

`

Neutral Palettes

`javascript

const GRAPHITE = ['#1a1a1a', '#333333', '#555555', '#888888', '#cccccc'];

const CREAM = ['#f4f0e8', '#e8dcc8', '#c9b99a', '#a89070', '#7a6450'];

const SLATE = ['#1e293b', '#334155', '#475569', '#64748b', '#94a3b8'];

`

Vivid Palettes

`javascript

const NEON = ['#ff00ff', '#00ffff', '#ff0080', '#80ff00', '#0080ff'];

const RAINBOW = ['#ff0000', '#ff8000', '#ffff00', '#00ff00', '#0000ff', '#8000ff'];

const VAPOR = ['#ff71ce', '#01cdfe', '#05ffa1', '#b967ff', '#fffb96'];

const CYBER = ['#0f0f0f', '#00ff41', '#ff0090', '#00d4ff', '#ffd000'];

`

Earth Tones

`javascript

const TERRA = ['#2c1810', '#5c3a2a', '#8b6b4a', '#c4a672', '#e8d5b7'];

const MOSS = ['#1a1f16', '#3d4a2e', '#6b7c4f', '#9aab7a', '#c8d4a9'];

const CLAY = ['#3b2f2f', '#6b4c4c', '#9e7676', '#c9a0a0', '#e8caca'];

`

Blend Modes

`javascript

blendMode(BLEND); // default — alpha compositing

blendMode(ADD); // additive — bright glow effects

blendMode(MULTIPLY); // darkening — shadows, texture overlay

blendMode(SCREEN); // lightening — soft glow

blendMode(OVERLAY); // contrast boost — high/low emphasis

blendMode(DIFFERENCE); // color subtraction — psychedelic

blendMode(EXCLUSION); // softer difference

blendMode(REPLACE); // overwrite (no alpha blending)

blendMode(REMOVE); // subtract alpha

blendMode(LIGHTEST); // keep brighter pixel

blendMode(DARKEST); // keep darker pixel

blendMode(BURN); // darken + saturate

blendMode(DODGE); // lighten + saturate

blendMode(SOFT_LIGHT); // subtle overlay

blendMode(HARD_LIGHT); // strong overlay

// ALWAYS reset after use

blendMode(BLEND);

`

Blend Mode Recipes

EffectModeUse case
------------------------
Additive glowADDLight beams, fire, particles
Shadow overlayMULTIPLYTexture, vignette
Soft light mixSCREENFog, mist, backlight
High contrastOVERLAYDramatic compositing
Color negativeDIFFERENCEGlitch, psychedelic
Layer compositingBLENDStandard alpha layering

Background Techniques

Textured Background

`javascript

function texturedBackground(baseColor, noiseScale, noiseAmount) {

loadPixels();

let r = red(baseColor), g = green(baseColor), b = blue(baseColor);

for (let i = 0; i < pixels.length; i += 4) {

let x = (i / 4) % width;

let y = floor((i / 4) / width);

let n = (noise(x noiseScale, y noiseScale) - 0.5) * noiseAmount;

pixels[i] = constrain(r + n, 0, 255);

pixels[i+1] = constrain(g + n, 0, 255);

pixels[i+2] = constrain(b + n, 0, 255);

pixels[i+3] = 255;

}

updatePixels();

}

`

Vignette

`javascript

function vignette(strength = 0.5, radius = 0.7) {

loadPixels();

let cx = width / 2, cy = height / 2;

let maxDist = dist(0, 0, cx, cy);

for (let i = 0; i < pixels.length; i += 4) {

let x = (i / 4) % width;

let y = floor((i / 4) / width);

let d = dist(x, y, cx, cy) / maxDist;

let factor = 1.0 - smoothstep(constrain((d - radius) / (1 - radius), 0, 1)) * strength;

pixels[i] *= factor;

pixels[i+1] *= factor;

pixels[i+2] *= factor;

}

updatePixels();

}

function smoothstep(t) { return t t (3 - 2 * t); }

`

Film Grain

`javascript

function filmGrain(amount = 30) {

loadPixels();

for (let i = 0; i < pixels.length; i += 4) {

let grain = random(-amount, amount);

pixels[i] = constrain(pixels[i] + grain, 0, 255);

pixels[i+1] = constrain(pixels[i+1] + grain, 0, 255);

pixels[i+2] = constrain(pixels[i+2] + grain, 0, 255);

}

updatePixels();

}

`