Day 28 - Art 1

Infinite Scroll

Neon Drift

Neon Drift is a mesmerizing generative art piece that creates a continuously scrolling, dynamic field of glowing orbs and shifting squares. Using Perlin noise, each shape's color and size evolve organically, forming a smooth and ever-changing pattern. The artwork features a vibrant neon-like palette, blending complementary hues as the grid drifts upward, creating a hypnotic and dreamlike effect reminiscent of bioluminescent waves or digital landscapes.

  // Speed at which the tile pattern scrolls upwards
  let scrollSpeed = 1.5;
  
  // Scale factor for Perlin noise, affecting the randomness of shapes
  let noiseScale = 0.02;
  
  // Height of a single tile grid
  let tileHeight;
  
  // Offset to track vertical scrolling position
  let yOffset = 0;
  
  // Resolution of the grid (distance between shapes)
  let resolution = 20;
  
  // Canvas reference
  let canvas;
  
  function setup() {
    // Create a 400x400 pixel canvas and attach it to a container in the HTML
    canvas = createCanvas(400, 400);
    canvas.parent('canvas-container');
  
    // Use HSB (Hue, Saturation, Brightness, Alpha) color mode for vibrant colors
    colorMode(HSB, 360, 100, 100, 1);
  
    // Set tile height to match canvas height for seamless scrolling
    tileHeight = height;
  
    // Disable strokes for a cleaner visual effect
    noStroke();
  }
  
  function draw() {
    // Dark background for contrast
    background(0, 0, 10);
  
    // Draw two overlapping tile grids for continuous scrolling effect
    drawTile(yOffset);
    drawTile(yOffset - tileHeight);
  
    // Move the offset downward to create a scrolling illusion
    yOffset += scrollSpeed;
  
    // Reset the offset when it completes a full cycle to loop seamlessly
    if (yOffset >= tileHeight) {
      yOffset = 0;
    }
  }
  
  /**
   * Generates a grid of randomly colored and sized shapes using Perlin noise.
   * 
   * @param {number} offsetY - The vertical offset for scrolling effect.
   */
  function drawTile(offsetY) {
    // Loop through a grid with spacing defined by 'resolution'
    for (let x = -resolution / 2; x < width + resolution / 2; x += resolution) {
      for (let y = -resolution / 2; y < tileHeight + resolution / 2; y += resolution) {
        
        // Generate a Perlin noise value based on position
        let noiseVal = noise(x * noiseScale, (y + offsetY) * noiseScale);
  
        // Map noise value to a hue range (0-360 for full spectrum)
        let hue = map(noiseVal, 0, 1, 0, 360);
  
        // Map noise value to determine shape size
        let size = map(noiseVal, 0, 1, 5, 20);
  
        // Draw an ellipse with a slightly transparent fill
        fill(hue, 80, 80, 0.8);
        ellipse(x, y + offsetY, size, size);
  
        // Draw a secondary shape (square) with complementary color
        fill((hue + 180) % 360, 80, 80, 0.6);
        rect(x - size / 4, y + offsetY - size / 4, size / 2, size / 2);
      }
    }
  }