xxxxxxxxxx
/*
Efflorescence
Jacob Joaquin
Description:
Efflorescence is a series of kaleidoscopic art stills generated
with Processing p5js.
Images are generated as a Perlin noise walker moves an evolving
brush inside a kaleidoscopic pattern. All stills are created using
the same script with two variable changes: The Perlin noise seed
and the number of kaleidoscope points. Minor brightness curves are
applied inside Photoshop.
*/
// User settings
var nAngles = 20; // Number of points in the kaleidoscope
var seed = -1; // Noise seed. A negative number will randomly select seed.
var nInc = 0.0008; // Perling inc amount
var minSize = 0; // Minimum brush size
var maxSize = 40; // Maximum brush size
var hueInc = 0.8001; // Rate of hue shifting
var sPhaseInc = 0.002; // Frequency of saturation oscillation
var rPhaseInc = 0.00001; // Frequence of brush rotation
var endFrame = 100; // Number of frames to draw
var capture = true; // Stops at endFrame if true
// Global vars
var nDrawsPerFrame = 32; // Number of draws per frame
var sPhase = 0; // Saturation phase
var rPhase = 0; // Rotation phase
var h = 0; // Hue
var nx = 0; // Noise x
var ny = 5; // Noise y
var nz = 0.006; // Noise z (size of brush)
var angle; // Base angle of kaleidoscope segment
var accent = true; // Status of accent brush
function setup() {
createCanvas(500, 500);
// Sketch behaviors
noStroke();
colorMode(HSB);
angle = 1 / nAngles * TAU;
rectMode(CENTER);
background(0);
// Set seed
if (seed < 0) {
seed = int(random(0, 30000));
}
println("noiseSeed(" + seed + ")");
noiseSeed(seed);
}
function draw() {
push();
translate(width / 2, height / 2);
for (var j = 0; j < nDrawsPerFrame; j++) {
// Noise
var x = map(noise(nx), 0, 1, -width, width);
var y = map(noise(ny), 0, 1, -height, height);
var s = map(noise(nz), 0, 1, minSize, maxSize);
nx += nInc;
ny += nInc;
nz += nInc * 4;
var center = createVector(0, 0);
var drawPoint = createVector(x, y);
var cmAngle = atan2(drawPoint.y - center.y, drawPoint.x - center.x);
var magnitude = center.dist(drawPoint);
// Envelope
var ae = endFrame * nDrawsPerFrame;
var af = frameCount * nDrawsPerFrame;
var afFade = 5 * nDrawsPerFrame;
var afWhere = ae - af;
var afScale = 1;
if (af >= ae - afFade) {
afScale = ((afWhere) / afFade);
} else if (af === ae) {
afScale = 0;
}
if (s < 0) {
afScale = 0;
}
s *= afScale
// Apply brush to every kaleidoscope segment
for (var i = 0; i < nAngles; i++) {
// Get angle for normal or mirrored segemnt
a = i * angle;
if (i % 2 === 0) {
a += cmAngle;
} else {
a += angle - cmAngle;
}
var v = p5.Vector.fromAngle(a).mult(magnitude);
v.add(center);
// Saturation
var sat = sin(sPhase * TAU);
sat = map(sat, -1, 1, 50, 65);
sat *= frameCount / endFrame;
// Brightness
var b = 100;
var maxDistance = 900;
var d = center.dist(v);
b = maxDistance - min(maxDistance, d);
b = map(b, 0, maxDistance, 0, 100);
b = max(b, 50);
b *= frameCount / endFrame;
push();
translate(v.x, v.y);
// Set rotation for normal or mirror
if (i % 2 === 0) {
a += cmAngle;
rotate(rPhase * TAU);
} else {
a += angle - cmAngle;
rotate(1 - rPhase * TAU);
}
// Highlight layer
fill((h + 32) % 360, sat * 1.1, b * 2, 0.1);
rect(0 + -s * 0.125, 0 + -s * 0.125, s, s * 0.617);
// Shadow layer
fill((h + 128) % 360, sat * 1.1, b / 3, 0.025);
rect(0 + s * 0.125, 0 + s * 0.125, s, s);
// Normal layer
fill(h, sat, b);
rect(0, 0, s, s);
// Accent
var accentSize = map(frameCount / endFrame, 0, 1, 0.2, 1.5);
if (accent) {
fill(0, 0, 100, 0.1);
ellipse(-s / 2.2, -s, accentSize, accentSize);
ellipse(s, 0, accentSize, accentSize);
}
if (random() < 0.01) {
accent = !accent;
}
pop();
}
// Update phasors and hue
rPhase += rPhaseInc;
if (rPhase >= 1.0) {
rPhase -= 1;
}
sPhase += sPhaseInc;
if (sPhase >= 1.0) {
sPhase -= 1;
}
h = (h + hueInc) % 360;
}
pop();
// Stop generating
if (capture && frameCount === endFrame) {
noLoop();
}
}