const NUM_LINE_CIRCLES= 0;
const NUM_LINE_RECTS = 16;
const TIME_MOD = 0.00005;
const TIME_COLOR_MOD = 0.00015;
const RECT_ROT_RADIUS = 0.3;
const FRAME_OFFSET = Math.random() * 10000;
let colorScheme = chroma.scale(['#da3843', '#e4bb33', '#16d951', '#34beec', '#2635d9', '#020208', '#9846df', '#e9ec42', '#da3843']);
constructor(parameters) {
for (let [key, value] of Object.entries(parameters)) {
if (this.position == null || this.angle == null || this.radius == null || linesShader == null) return;
class LineCircle extends LinesShape {
constructor(parameters) {
class LinesRect extends LinesShape {
constructor(parameters) {
this.timeOffset = 1000 * Math.random();
linesShader.setUniform('uAngle', this.angle);
linesShader.setUniform('uLineWidth', this.linesWidth);
linesShader.setUniform('uLineScale', this.linesScale);
linesShader.setUniform('uRgb0', this.rgb0);
linesShader.setUniform('uRgb1', this.rgb1);
linesShader.setUniform('uCenter', this.center);
linesShader.setUniform('uTime', frameCount * 0.02 * TIME_SCALE + this.timeOffset);
rect(0, 0, width, height);
class LinesShapeAnimator {
constructor(parameters) {
if (parameters != null) {
for (let [key, value] of Object.entries(parameters)) {
const dim = Math.max(width, height);
const linesScale = Math.floor(map(dim, 300, 2500, 4, 20));
for (let i = 0; i < NUM_LINE_RECTS; i++) {
this.linesRects.push(new LinesRect({
for (let i = 0; i < this.linesRects.length; i++) {
const linesRect = this.linesRects[i];
let angleOffset = Math.floor(i - this.linesRects.length * 0.5 + 1);
angleOffset -= (angleOffset <= 0 ? 1 : 0);
const a = i * 2 * Math.PI / this.linesRects.length;
linesRect.angle = a + (frameCount * TIME_SCALE + mouseX + FRAME_OFFSET) * TIME_MOD * angleOffset;
const t = (i / this.linesRects.length + (frameCount * TIME_SCALE + mouseY - mouseX) * TIME_COLOR_MOD + FRAME_OFFSET) % 1;
const color0 = colorScheme(t).saturate().darken(2).rgb();
linesRect.rgb0 = [color0[0] / 255, color0[1] / 255, color0[2] / 255];
linesRect.rgb1 = [0, 0, 0];
const x = 0.4 + RECT_ROT_RADIUS * Math.cos(t * 2 * Math.PI);
const y = 0.3 + RECT_ROT_RADIUS * Math.sin(t * 2 * Math.PI);
linesRect.center = [x, y];
for (let linesRect of this.linesRects) {
linesShader = loadShader('lines.vert', 'lines.frag');
baseCanvas = createCanvas(windowWidth, windowHeight, WEBGL);
shapeAnimator = new LinesShapeAnimator();
describe("A series of rotating polygons layered on top of each other, each with shifting lines that generate colorful moire patterns.");
linesShader.setUniform('uAspectRatio', windowHeight / windowWidth);
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
window.parent.postMessage('exitFullscreen', '*');
window.parent.postMessage('enterFullscreen', '*');