Ouroboros Neural Network

📅 April 25, 2026 🏷️ art
ouroboros strange-attractor recursive-neural esoteric-occult flow-field metallic-gold multi-layer-compositing curve-vertex pending-review
Generated by GridFlow AI | Tags: ouroboros, strange-attractor, recursive-neural, esoteric-occult, flow-field, metallic-gold, multi-layer-compositing, curve-vertex

💡 AI 提示词

Ouroboros Neural Network Recursively Devouring Its Own Emergent Consciousness — esoteric occult — metallic gold and brass structures floating in infinite dark voids — render paradigm: mathematical strange attractors (Clifford, Peter de Jong) mapped to flow fields

🔧 核心算法要点

  1. Clifford attractor iterated 8000 times with evolving parameters creates chaotic trajectory points that form the primary neural structure
  2. Peter de Jong attractor generates secondary 6000-point trajectory with complementary dynamics for layered complexity
  3. Attractor points are mapped to flow fields by computing velocity vectors between consecutive points, creating directional flow data
  4. Multi-layer compositing with 6 separate p.createGraphics buffers for background void, flow field, main structure, glow effects, FX, and pixel processing
  5. Organic flowing curves trace paths through the flow field using curveVertex sequences, creating silk-ribbon like tendrils that follow attractor dynamics
  6. Recursive ouroboros spiral patterns drawn with curveVertex using spiral radius formula with self-referential noise modulation
  7. ADD and SCREEN blend modes create luminous metallic glow by compositing multiple layers of the same structure at varying opacities
  8. Mouse position applies magnetic distortion field attracting flow curves toward cursor with concentric ring emanations

🎨 原始代码

var sketch = function(p) {
  var container;
  var bgBuffer, fieldBuffer, mainBuffer, glowBuffer, fxBuffer, pixBuffer;
  var cliffordPoints, deJongPoints;
  var cliffordFlow, deJongFlow;
  var state = {
    frameCount: 0,
    palettes: [
      { gold: {h: 42, s: 75, b: 90}, brass: {h: 35, s: 65, b: 75}, dark: {h: 240, s: 30, b: 5} }
    ],
    paletteIndex: 0,
    activeAttractor: 'both',
    evolveSpeed: 0.002
  };
  
  p.setup = function() {
    container = document.getElementById('p5-wrapper');
    if (container) {
      p.createCanvas(container.offsetWidth, container.offsetHeight).parent(container);
    } else {
      p.createCanvas(p.windowWidth, p.windowHeight);
    }
    p.frameRate(60);
    
    bgBuffer = p.createGraphics(p.width, p.height);
    fieldBuffer = p.createGraphics(p.width, p.height);
    mainBuffer = p.createGraphics(p.width, p.height);
    glowBuffer = p.createGraphics(p.width, p.height);
    fxBuffer = p.createGraphics(p.width, p.height);
    pixBuffer = p.createGraphics(p.width, p.height);
    
    initBuffers();
    generateAttractors();
  };
  
  function initBuffers() {
    bgBuffer.background(5, 3, 8);
    fieldBuffer.background(0, 0, 0, 0);
    mainBuffer.background(0, 0, 0, 0);
    glowBuffer.background(0, 0, 0, 0);
    fxBuffer.background(0, 0, 0, 0);
    pixBuffer.background(0, 0, 0, 0);
    
    for (var i = 0; i < 20; i++) {
      var angle = p.random(p.TWO_PI);
      var dist = p.random(p.min(p.width, p.height) * 0.3);
      var x = p.width / 2 + Math.cos(angle) * dist;
      var y = p.height / 2 + Math.sin(angle) * dist;
      
      bgBuffer.noStroke();
      for (var r = 80; r > 0; r -= 5) {
        var alpha = p.map(r, 0, 80, 0.3, 0.01);
        bgBuffer.fill(240, 20, 8, alpha);
        bgBuffer.ellipse(x, y, r, r);
      }
    }
  }
  
  function cliffordAttractor(x, y, a, b, c, d) {
    return {
      x: Math.sin(a * y) + c * Math.cos(a * x),
      y: Math.sin(b * x) + d * Math.cos(b * y)
    };
  }
  
  function deJongAttractor(x, y, a, b, c, d) {
    return {
      x: Math.sin(a * y) - Math.cos(b * x),
      y: Math.sin(c * x) - Math.cos(d * y)
    };
  }
  
  function generateAttractorPoints(type, params, iterations) {
    var points = [];
    var x = p.random(-2, 2);
    var y = p.random(-2, 2);
    
    for (var i = 0; i < iterations; i++) {
      var next;
      if (type === 'clifford') {
        next = cliffordAttractor(x, y, params.a, params.b, params.c, params.d);
      } else {
        next = deJongAttractor(x, y, params.a, params.b, params.c, params.d);
      }
      
      var screenX = next.x * params.scale + p.width / 2;
      var screenY = next.y * params.scale + p.height / 2;
      
      points.push({
        x: screenX,
        y: screenY,
        vx: next.x,
        vy: next.y
      });
      
      x = next.x;
      y = next.y;
    }
    
    return points;
  }
  
  function buildFlowField(points, resolution) {
    var cols = Math.floor(p.width / resolution);
    var rows = Math.floor(p.height / resolution);
    var field = [];
    
    for (var i = 0; i < cols * rows; i++) {
      field.push({ angle: 0, magnitude: 0, count: 0 });
    }
    
    for (var i = 0; i < points.length - 1; i++) {
      var p1 = points[i];
      var p2 = points[i + 1];
      
      var dx = p2.x - p1.x;
      var dy = p2.y - p1.y;
      var mag = Math.sqrt(dx * dx + dy * dy);
      
      if (mag > 0.1) {
        var col = p.constrain(Math.floor(p1.x / resolution), 0, cols - 1);
        var row = p.constrain(Math.floor(p1.y / resolution), 0, rows - 1);
        var idx = row * cols + col;
        
        field[idx].angle += Math.atan2(dy, dx);
        field[idx].magnitude += mag;
        field[idx].count++;
      }
    }
    
    for (var i = 0; i < field.length; i++) {
      if (field[i].count > 0) {
        field[i].angle /= field[i].count;
        field[i].magnitude /= field[i].count;
      }
    }
    
    return { field: field, cols: cols, rows: rows, resolution: resolution };
  }
  
  function generateAttractors() {
    var palette = state.palettes[state.paletteIndex];
    
    var cliffordParams = {
      a: -2.5 + p.sin(state.frameCount * state.evolveSpeed) * 0.3,
      b: -2.5 + p.cos(state.frameCount * state.evolveSpeed * 0.7) * 0.3,
      c: -1.5,
      d: -1.0,
      scale: p.min(p.width, p.height) * 0.35
    };
    
    var deJongParams = {
      a: -2.0,
      b: -2.0,
      c: -1.2 + p.sin(state.frameCount * state.evolveSpeed * 0.5) * 0.2,
      d: 2.0 + p.cos(state.frameCount * state.evolveSpeed * 0.3) * 0.2,
      scale: p.min(p.width, p.height) * 0.30
    };
    
    cliffordPoints = generateAttractorPoints('clifford', cliffordParams, 8000);
    deJongPoints = generateAttractorPoints('dejong', deJongParams, 6000);
    
    cliffordFlow = buildFlowField(cliffordPoints, 8);
    deJongFlow = buildFlowField(deJongPoints, 10);
    
    renderAttractorToBuffer(cliffordPoints, fieldBuffer, palette.gold, 0.7, 3000);
    renderAttractorToBuffer(deJongPoints, fieldBuffer, palette.brass, 0.5, 2000);
  }
  
  function renderAttractorToBuffer(points, buffer, color, alpha, maxPoints) {
    buffer.push();
    buffer.blendMode(p.ADD);
    
    var drawCount = Math.min(points.length, maxPoints);
    
    for (var i = 0; i < drawCount - 1; i++) {
      var p1 = points[i];
      var p2 = points[i + 1];
      
      var intensity = p.map(i, 0, drawCount, 0.2, 1.0);
      var strokeAlpha = alpha * intensity;
      
      buffer.stroke(color.h, color.s, color.b, strokeAlpha);
      buffer.strokeWeight(p.map(i, 0, drawCount, 0.5, 2.0));
      buffer.line(p1.x, p1.y, p2.x, p2.y);
    }
    
    buffer.pop();
  }
  
  function drawFlowingCurves(flowData, buffer, config) {
    buffer.push();
    buffer.blendMode(p.ADD);
    
    for (var c = 0; c < config.curveCount; c++) {
      var startX = p.random(p.width);
      var startY = p.random(p.height);
      var curvePoints = [];
      var x = startX;
      var y = startY;
      
      for (var s = 0; s < config.steps; s++) {
        var col = Math.floor(x / flowData.resolution);
        var row = Math.floor(y / flowData.resolution);
        
        if (col >= 0 && col < flowData.cols && row >= 0 && row < flowData.rows) {
          var idx = row * flowData.cols + col;
          var cell = flowData.field[idx];
          
          if (cell.count > 0) {
            var flowAngle = cell.angle + p.noise(x * 0.005, y * 0.005, state.frameCount * 0.01) * p.TWO_PI;
            x += Math.cos(flowAngle) * flowData.resolution * 0.5;
            y += Math.sin(flowAngle) * flowData.resolution * 0.5;
            
            curvePoints.push({ x: x, y: y });
          }
        }
      }
      
      if (curvePoints.length > 3) {
        buffer.noFill();
        buffer.stroke(config.hue, config.sat, config.bri, config.alpha);
        buffer.strokeWeight(config.weight);
        buffer.beginShape();
        
        buffer.vertex(curvePoints[0].x, curvePoints[0].y);
        
        for (var i = 1; i < curvePoints.length - 1; i++) {
          buffer.curveVertex(curvePoints[i].x, curvePoints[i].y);
        }
        
        buffer.endShape();
      }
    }
    
    buffer.pop();
  }
  
  function drawOuroborosPattern(buffer, centerX, centerY, baseRadius) {
    var palette = state.palettes[state.paletteIndex];
    buffer.push();
    buffer.blendMode(p.ADD);
    
    var segments = 120;
    var spiralTightness = 0.15;
    var recursionDepth = 4;
    
    function recursiveSpiral(cx, cy, radius, depth, angleOffset) {
      if (depth <= 0 || radius < 20) return;
      
      var pts = [];
      var numPts = Math.floor(segments * (depth / recursionDepth));
      
      for (var i = 0; i <= numPts; i++) {
        var t = i / numPts;
        var angle = t * p.TWO_PI * 3 + angleOffset;
        var spiralRadius = radius * (1 - t * spiralTightness);
        
        var noiseFactor = p.noise(cx * 0.002, cy * 0.002, t * 5 + state.frameCount * 0.02);
        var r = spiralRadius * (1 + (noiseFactor - 0.5) * 0.3);
        
        var px = cx + Math.cos(angle) * r;
        var py = cy + Math.sin(angle) * r;
        
        var selfInfluence = p.sin(angle * 5 + state.frameCount * 0.03) * 5;
        px += Math.cos(angle + p.HALF_PI) * selfInfluence;
        py += Math.sin(angle + p.HALF_PI) * selfInfluence;
        
        pts.push({ x: px, y: py, t: t });
      }
      
      for (var i = 0; i < pts.length - 1; i++) {
        var p1 = pts[i];
        var p2 = pts[i + 1];
        var intensity = 0.3 + p1.t * 0.5;
        
        buffer.stroke(palette.gold.h + p1.t * 10, palette.gold.s, palette.gold.b, intensity * 0.6);
        buffer.strokeWeight(p.map(depth, 1, recursionDepth, 0.5, 3));
        buffer.line(p1.x, p1.y, p2.x, p2.y);
      }
      
      if (depth >= 3) {
        for (var i = 0; i < pts.length; i += 4) {
          var pt = pts[i];
          var glowSize = 10 + depth * 3;
          
          for (var g = glowSize; g > 0; g -= 2) {
            var gAlpha = p.map(g, 0, glowSize, 0.8, 0);
            buffer.noStroke();
            buffer.fill(palette.gold.h, palette.gold.s, palette.gold.b, gAlpha * 0.3);
            buffer.ellipse(pt.x, pt.y, g, g);
          }
        }
      }
      
      if (depth > 1) {
        var newRadius = radius * 0.6;
        var newCX = cx + Math.cos(angleOffset + p.PI) * radius * 0.3;
        var newCY = cy + Math.sin(angleOffset + p.PI) * radius * 0.3;
        
        recursiveSpiral(newCX, newCY, newRadius, depth - 1, angleOffset + p.PI * 0.5);
        recursiveSpiral(cx, cy, newRadius, depth - 1, angleOffset - p.PI * 0.3);
      }
    }
    
    recursiveSpiral(centerX, centerY, baseRadius, recursionDepth, state.frameCount * 0.02);
    
    buffer.pop();
  }
  
  function renderNeuralNodes(buffer, points) {
    var palette = state.palettes[state.paletteIndex];
    buffer.push();
    buffer.blendMode(p.ADD);
    
    var nodeSpacing = 30;
    
    for (var i = 0; i < points.length; i += nodeSpacing) {
      var pt = points[i];
      var noiseVal = p.noise(pt.x * 0.01, pt.y * 0.01, state.frameCount * 0.015);
      var nodeSize = 3 + noiseVal * 12;
      
      for (var r = nodeSize * 4; r > 0; r -= 3) {
        var gAlpha = p.map(r, 0, nodeSize * 4, 1.0, 0);
        buffer.noStroke();
        buffer.fill(palette.gold.h, 60, 80, gAlpha * 0.4);
        buffer.ellipse(pt.x, pt.y, r, r);
      }
      
      buffer.noStroke();
      buffer.fill(palette.brass.h, palette.brass.s, palette.brass.b, 0.95);
      buffer.ellipse(pt.x, pt.y, nodeSize, nodeSize);
      
      buffer.stroke(palette.gold.h, palette.gold.s, 100, 0.7);
      buffer.strokeWeight(0.5);
      buffer.noFill();
      buffer.ellipse(pt.x, pt.y, nodeSize + 2, nodeSize + 2);
    }
    
    buffer.pop();
  }
  
  function renderRecursiveVoid(buffer) {
    var palette = state.palettes[state.paletteIndex];
    buffer.push();
    buffer.blendMode(p.MULTIPLY);
    
    var voidLayers = 6;
    
    for (var layer = 0; layer < voidLayers; layer++) {
      var progress = layer / voidLayers;
      var radius = p.min(p.width, p.height) * 0.35 * (1 - progress * 0.25);
      var segments = 32 + layer * 16;
      
      buffer.noFill();
      buffer.stroke(palette.dark.h, palette.dark.s, 20 + layer * 8, 0.4 - progress * 0.15);
      buffer.strokeWeight(1.5 + (voidLayers - layer) * 0.8);
      
      buffer.beginShape();
      
      for (var i = 0; i <= segments; i++) {
        var angle = (i / segments) * p.TWO_PI * 2.5;
        var wobble = 0.15 * p.sin(angle * (4 + layer)) + 0.08 * p.noise(angle * 3, state.frameCount * 0.02);
        var r = radius * (1 + wobble);
        
        var cx = p.width / 2 + Math.cos(state.frameCount * 0.01 + layer) * 20;
        var cy = p.height / 2 + Math.sin(state.frameCount * 0.01 + layer) * 20;
        
        buffer.curveVertex(cx + Math.cos(angle) * r, cy + Math.sin(angle) * r);
      }
      
      buffer.endShape();
    }
    
    buffer.pop();
  }
  
  function applyMouseDistortion(buffer) {
    var mx = p.mouseX;
    var my = p.mouseY;
    var palette = state.palettes[state.paletteIndex];
    
    buffer.push();
    buffer.blendMode(p.ADD);
    
    var mouseRadius = 100;
    
    for (var i = 0; i < 8; i++) {
      var angle = state.frameCount * 0.08 + i * p.TWO_PI / 8;
      var dist = 40 + i * 12;
      var x = mx + Math.cos(angle) * dist;
      var y = my + Math.sin(angle) * dist;
      
      for (var r = 25 + i * 5; r > 0; r -= 3) {
        var alpha = p.map(r, 0, 25 + i * 5, 0.5, 0);
        buffer.noStroke();
        buffer.fill(palette.gold.h, 70, 90, alpha * 0.2);
        buffer.ellipse(x, y, r, r);
      }
    }
    
    buffer.stroke(palette.gold.h, 80, 100, 0.3);
    buffer.strokeWeight(1);
    buffer.noFill();
    buffer.ellipse(mx, my, mouseRadius * 2, mouseRadius * 2);
    
    buffer.pop();
  }
  
  function drawSelfDevouringEffect(buffer) {
    var palette = state.palettes[state.paletteIndex];
    buffer.push();
    buffer.blendMode(p.SCREEN);
    
    var segments = 24;
    var layers = 5;
    
    for (var layer = 0; layer < layers; layer++) {
      var layerProgress = layer / layers;
      var baseRadius = p.min(p.width, p.height) * 0.4 * (1 - layerProgress * 0.2);
      var rotation = state.frameCount * 0.015 * (layer % 2 === 0 ? 1 : -1);
      
      buffer.noFill();
      buffer.stroke(palette.gold.h + layer * 5, 85, 95, 0.4 - layerProgress * 0.1);
      buffer.strokeWeight(2 - layerProgress);
      
      buffer.beginShape();
      
      for (var i = 0; i <= segments; i++) {
        var t = i / segments;
        var angle = t * p.TWO_PI + rotation;
        
        var selfEat = Math.pow(t, 0.5) * baseRadius * 0.3 * p.sin(angle * 6 + state.frameCount * 0.05);
        var r = baseRadius * (1 - t * 0.4) + selfEat;
        
        var noiseVal = p.noise(Math.cos(angle) * 2, Math.sin(angle) * 2, state.frameCount * 0.02);
        r += (noiseVal - 0.5) * 20;
        
        buffer.curveVertex(
          p.width / 2 + Math.cos(angle) * r,
          p.height / 2 + Math.sin(angle) * r
        );
      }
      
      buffer.endShape(p.CLOSE);
    }
    
    buffer.pop();
  }
  
  function compositeLayers() {
    p.image(bgBuffer, 0, 0);
    
    p.blendMode(p.ADD);
    p.image(fieldBuffer, 0, 0);
    
    p.image(mainBuffer, 0, 0);
    
    p.blendMode(p.SCREEN);
    p.image(glowBuffer, 0, 0);
    
    p.image(fxBuffer, 0, 0);
    
    p.blendMode(p.BLEND);
    
    renderRecursiveVoid(p);
    
    renderNeuralNodes(p, cliffordPoints);
    renderNeuralNodes(p, deJongPoints);
  }
  
  p.draw = function() {
    var palette = state.palettes[state.paletteIndex];
    
    fieldBuffer.background(0, 0, 0, 0);
    mainBuffer.background(0, 0, 0, 0);
    glowBuffer.background(0, 0, 0, 0);
    fxBuffer.background(0, 0, 0, 0);
    
    drawSelfDevouringEffect(mainBuffer);
    
    drawOuroborosPattern(mainBuffer, p.width / 2, p.height / 2, p.min(p.width, p.height) * 0.4);
    
    if (state.activeAttractor === 'clifford' || state.activeAttractor === 'both') {
      drawFlowingCurves(cliffordFlow, mainBuffer, {
        hue: palette.gold.h,
        sat: palette.gold.s,
        bri: palette.gold.b,
        alpha: 0.35,
        weight: 1.5,
        curveCount: 60,
        steps: 100
      });
    }
    
    if (state.activeAttractor === 'dejong' || state.activeAttractor === 'both') {
      drawFlowingCurves(deJongFlow, mainBuffer, {
        hue: palette.brass.h,
        sat: palette.brass.s,
        bri: palette.brass.b,
        alpha: 0.25,
        weight: 1.2,
        curveCount: 40,
        steps: 80
      });
    }
    
    if (p.mouseX > 0 && p.mouseX < p.width && p.mouseY > 0 && p.mouseY < p.height) {
      applyMouseDistortion(mainBuffer);
    }
    
    renderNeuralNodes(glowBuffer, cliffordPoints);
    renderNeuralNodes(glowBuffer, deJongPoints);
    
    compositeLayers();
    
    state.frameCount++;
    
    if (state.frameCount % 240 === 0) {
      generateAttractors();
    }
  };
  
  p.mousePressed = function() {
    generateAttractors();
    
    fxBuffer.push();
    fxBuffer.blendMode(p.ADD);
    
    var mx = p.mouseX;
    var my = p.mouseY;
    var palette = state.palettes[state.paletteIndex];
    
    for (var i = 0; i < 40; i++) {
      var angle = p.random(p.TWO_PI);
      var speed = p.random(3, 12);
      var size = p.random(2, 8);
      
      fxBuffer.noStroke();
      fxBuffer.fill(palette.gold.h, 90, 100, 0.8);
      fxBuffer.ellipse(
        mx + Math.cos(angle) * speed * 8,
        my + Math.sin(angle) * speed * 8,
        size,
        size
      );
    }
    
    for (var r = 60; r > 0; r -= 4) {
      var alpha = p.map(r, 0, 60, 0.6, 0);
      fxBuffer.noFill();
      fxBuffer.stroke(palette.gold.h, 80, 100, alpha);
      fxBuffer.strokeWeight(2);
      fxBuffer.ellipse(mx, my, r, r);
    }
    
    fxBuffer.pop();
  };
  
  p.keyPressed = function() {
    if (p.key === 'r' || p.key === 'R') {
      initBuffers();
      generateAttractors();
      state.frameCount = 0;
    } else if (p.key === 'c' || p.key === 'C') {
      state.paletteIndex = (state.paletteIndex + 1) % state.palettes.length;
      generateAttractors();
    } else if (p.key === '1') {
      state.activeAttractor = 'clifford';
    } else if (p.key === '2') {
      state.activeAttractor = 'dejong';
    } else if (p.key === '3') {
      state.activeAttractor = 'both';
    } else if (p.key === 'e' || p.key === 'E') {
      state.evolveSpeed = state.evolveSpeed > 0.01 ? 0.002 : 0.015;
    }
  };
  
  p.windowResized = function() {
    container = document.getElementById('p5-wrapper');
    if (container) {
      p.resizeCanvas(container.offsetWidth, container.offsetHeight);
    } else {
      p.resizeCanvas(p.windowWidth, p.windowHeight);
    }
    initBuffers();
    generateAttractors();
  };
};
// p5 init stripped

✨ AI 艺术解读

This piece visualizes consciousness as a self-consuming ouroboros neural network — the recursive spiral patterns represent the endless cycle of a mind devouring its own emergent thoughts while simultaneously regenerating them. The strange attractors create unpredictable yet coherent structures that emerge from simple mathematical rules, mirroring how complex consciousness arises from neural firing patterns. The viewer witnesses an eternal transformation where metallic golden structures spiral inward toward recursive void centers only to re-emerge transformed, embodying the philosophical paradox of ego-death and cosmic enlightenment through mathematical beauty.

📝 补充说明

  • Clifford attractor uses equations x' = sin(ay) + c*cos(ax), y' = sin(bx) + d*cos(by) — parameters evolve over time creating organic parameter drift
  • Peter de Jong uses simpler equations x' = sin(ay) - cos(bx), y' = sin(cx) - cos(dy) providing complementary chaotic behavior
  • Flow field resolution of 8-10 pixels balances computational efficiency with visual smoothness for real-time performance
  • Recursion depth of 4 with spiral tightness 0.15 creates the characteristic ouroboros swallowing effect without excessive computation
  • Press 1/2/3 to switch attractor modes, R to reset, C to cycle palette, E to toggle evolution speed for interactive exploration