Website for a Music Festival for Creators
OFF RECORD is an international music festival that puts the creative process at its center. It brings together musicians, producers and creators from around the world, creating a space where music is made, developed and shared — from the first idea to the stage.
Create · Connect · Perform
The visual language of OFF RECORD was inspired by sound, movement and the unpredictable nature of the creative process.
Using p5.js, I built a generative system of shifting lines and forms, creating visuals that are constantly in motion.
function setup() {
createCanvas(500, 700);
noFill();
strokeWeight(3);
}
function draw() {
background('#F1F1F5');
let blobW = map(mouseX, 0, width, 180, 360);
let blobH = map(mouseY, 0, height, 220, 460);
drawBlob(width * 0.32, height * 0.42, blobW, blobH, 34);
}
function drawBlob(cx, cy, w, h, count) {
let c1 = color('#3E2324');
let c2 = color('#5C82C1');
let c3 = color('#FCC538');
let distortion = map(mouseX, 0, width, 5, 45);
let movement = map(mouseY, 0, height, 5, 35);
for (let i = 0; i < count; i++) {
let t = i / (count - 1);
let col;
if (t < 0.5) {
col = lerpColor(c1, c2, t * 2);
} else {
col = lerpColor(c2, c3, (t - 0.5) * 2);
}
stroke(col);
let scale = map(i, 0, count - 1, 1, 0.18);
beginShape();
for (let a = 0; a < TWO_PI; a += 0.04) {
let wave = sin(frameCount * 0.03 + a * 3 + i * 0.2) * movement;
let rX =
w * scale +
sin(a * 2) * distortion +
sin(a * 5) * (distortion * 0.5) +
wave;
let rY =
h * scale +
cos(a * 3) * distortion +
wave;
let x = cos(a) * rX;
let y = sin(a) * rY;
x += sin(y * 0.018) * 45;
y += cos(x * 0.012) * 25;
vertex(cx + x, cy + y);
}
endShape(CLOSE);
}
}
function setup() {
createCanvas(500, 700);
}
function draw() {
background('#F1F1F5');
noFill();
strokeCap(ROUND);
let focusX = 355;
let focusY = 335;
let linesCount = 115;
let time = frameCount * 0.035;
for (let i = 0; i < linesCount; i++) {
let t = i / (linesCount - 1);
let d = abs(t - 0.5) * 2;
let startX = -560;
let endX = width + 170;
let startCenterY = focusY - 310;
let endCenterY = focusY + 170;
let leftSpread = pow(d, 0.7) * 1050;
let rightSpread = pow(d, 0.65) * 360;
let startY = startCenterY + (t - 0.5) * leftSpread;
let endY = endCenterY + (t - 0.5) * rightSpread;
startY += sin(t * TWO_PI * 1.1 + time) * 70 * d;
endY += sin(t * TWO_PI * 1.4 + time * 0.8) * 55 * d;
let move =
sin(time * 1.4 + t * TWO_PI) * 42 +
sin(time * 0.7 + t * TWO_PI * 2.3) * 16;
let cp1X = 120;
let cp1Y = startY + move;
let cp2X = focusX - 250;
let cp2Y = focusY + (startY - focusY) * 0.1 + move;
let cp3X = focusX + 80;
let cp3Y = focusY + (endY - focusY) * 0.18;
let cp4X = width - 10;
let cp4Y = endY + 60;
let prev = getPointOnFullCurve(
startX, startY,
cp1X, cp1Y,
cp2X, cp2Y,
focusX, focusY,
cp3X, cp3Y,
cp4X, cp4Y,
endX, endY,
0
);
for (let s = 1; s <= 120; s++) {
let p = s / 120;
let pt = getPointOnFullCurve(
startX, startY,
cp1X, cp1Y,
cp2X, cp2Y,
focusX, focusY,
cp3X, cp3Y,
cp4X, cp4Y,
endX, endY,
p
);
let colorMix = t * 0.65 + p * 0.35;
colorMix += sin((t * 5 + p * 2) * TWO_PI) * 0.06;
colorMix = constrain(colorMix, 0, 1);
stroke(getSoftColor(colorMix));
strokeWeight(2);
line(prev.x, prev.y, pt.x, pt.y);
prev = pt;
}
}
}
function getSoftColor(v) {
let c1 = color("#3E2324");
let c2 = color("#4A72B8");
let c3 = color("#8FA0A0");
let c4 = color("#FCC538");
if (v < 0.33) return lerpColor(c1, c2, v / 0.33);
if (v < 0.66) return lerpColor(c2, c3, (v - 0.33) / 0.33);
return lerpColor(c3, c4, (v - 0.66) / 0.34);
}
function getPointOnFullCurve(
x1, y1,
cp1X, cp1Y,
cp2X, cp2Y,
focusX, focusY,
cp3X, cp3Y,
cp4X, cp4Y,
x2, y2,
p
) {
if (p < 0.5) {
let q = p / 0.5;
return createVector(
bezierPoint(x1, cp1X, cp2X, focusX, q),
bezierPoint(y1, cp1Y, cp2Y, focusY, q)
);
} else {
let q = (p - 0.5) / 0.5;
return createVector(
bezierPoint(focusX, cp3X, cp4X, x2, q),
bezierPoint(focusY, cp3Y, cp4Y, y2, q)
);
}
}
function setup() {
createCanvas(500, 700);
noStroke();
}
function draw() {
background('#F1F1F5');
let c1 = color('#3E2324');
let c2 = color('#5C82C1');
let c3 = color('#FCC538');
let barW = 4;
let gap = 8;
let centerY = height * 0.55;
for (let x = 40; x < width - 40; x += barW + gap) {
let t = map(x, 40, width - 40, 0, 1);
let col;
if (t < 0.5) {
col = lerpColor(c1, c2, t * 2);
} else {
col = lerpColor(c2, c3, (t - 0.5) * 2);
}
let wave =
sin(x * 0.025 + frameCount * 0.03) * 90 +
sin(x * 0.012 + mouseX * 0.02) * 120;
let mouseShape = map(mouseY, 0, height, 80, 260);
let h = 220 + wave + mouseShape;
let edgeFade = sin(t * PI);
h *= edgeFade;
fill(col);
fill(red(col), green(col), blue(col), alpha);
rect(
x,
centerY - h / 2,
barW,
h,
20
);
}
}