From 35175d04a6083ba80a810fb23c5df89651e4ce77 Mon Sep 17 00:00:00 2001 From: Ed Date: Thu, 26 Feb 2026 14:02:18 +0000 Subject: [PATCH] glitch-art: add topo-drift + chromatic-shatter, evolve fractal-burn palettes New algorithms: - topo-drift: topographic contour maps with fractal elevation, contour line rendering, and horizontal drift displacement - chromatic-shatter: RGB channel displacement through geometric shard zones with quadratic falloff and edge glow Evolved: - fractal-burn: now rotates between 4 color palettes (classic purple-fire, ocean abyss, toxic green, infrared) Pool: 12 -> 14 algorithms --- daily.go | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 183 insertions(+), 3 deletions(-) diff --git a/daily.go b/daily.go index 69bd25f..ddeb801 100644 --- a/daily.go +++ b/daily.go @@ -51,6 +51,8 @@ func main() { {"bit-cascade", drawBitCascade}, {"deep-scan", drawDeepScan}, {"entropy-wave", drawEntropyWave}, + {"topo-drift", drawTopoDrift}, + {"chromatic-shatter", drawChromaticShatter}, } // Shuffle and pick 6 @@ -259,10 +261,18 @@ func drawFractalBurn(img *image.RGBA, w, h int) { maxIter := 80 + rand.Intn(40) zoom := 200.0 + rand.Float64()*200 - palette := []color.RGBA{ - {20, 0, 40, 255}, {80, 0, 120, 255}, {200, 50, 50, 255}, - {255, 150, 0, 255}, {255, 255, 100, 255}, {255, 255, 255, 255}, + // Rotating palette selection for variety + palettes := [][]color.RGBA{ + // Classic purple-fire + {{20, 0, 40, 255}, {80, 0, 120, 255}, {200, 50, 50, 255}, {255, 150, 0, 255}, {255, 255, 100, 255}, {255, 255, 255, 255}}, + // Ocean abyss + {{0, 5, 20, 255}, {0, 30, 80, 255}, {0, 120, 160, 255}, {40, 220, 200, 255}, {200, 255, 240, 255}, {255, 255, 255, 255}}, + // Toxic green + {{5, 10, 0, 255}, {20, 60, 10, 255}, {80, 180, 20, 255}, {200, 255, 50, 255}, {255, 255, 150, 255}, {255, 255, 255, 255}}, + // Infrared + {{10, 0, 0, 255}, {60, 0, 30, 255}, {180, 0, 60, 255}, {255, 80, 0, 255}, {255, 200, 50, 255}, {255, 255, 200, 255}}, } + palette := palettes[rand.Intn(len(palettes))] for y := 0; y < h; y++ { for x := 0; x < w; x++ { @@ -597,6 +607,176 @@ func drawEntropyWave(img *image.RGBA, w, h int) { addGlitchBars(img, w, h, 6) } +// === TOPOGRAPHIC DRIFT === +// Simulates contour/elevation maps with glitchy drift lines +func drawTopoDrift(img *image.RGBA, w, h int) { + seed1 := rand.Float64() * 100 + seed2 := rand.Float64() * 100 + numOctaves := 3 + // Color scheme: earthy to neon + schemes := [][]color.RGBA{ + {{10, 15, 20, 255}, {40, 80, 60, 255}, {180, 140, 80, 255}, {255, 200, 120, 255}}, + {{5, 5, 25, 255}, {20, 60, 120, 255}, {100, 200, 220, 255}, {230, 240, 255, 255}}, + {{15, 5, 10, 255}, {120, 30, 60, 255}, {220, 100, 80, 255}, {255, 220, 180, 255}}, + } + scheme := schemes[rand.Intn(len(schemes))] + contourSpacing := 0.06 + rand.Float64()*0.06 // how tight the contour lines are + lineWidth := 0.008 + rand.Float64()*0.008 + + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + fx := float64(x)/float64(w)*4 + seed1 + fy := float64(y)/float64(h)*8 + seed2 // taller aspect + + // Simple fractal noise approximation + elevation := 0.0 + amp := 1.0 + freq := 1.0 + for o := 0; o < numOctaves; o++ { + elevation += amp * (math.Sin(fx*freq*2.1+fy*freq*0.7) + + math.Cos(fy*freq*1.9+fx*freq*1.3)*0.8 + + math.Sin((fx+fy)*freq*1.1)*0.5) + amp *= 0.5 + freq *= 2.0 + } + elevation = elevation*0.15 + 0.5 + + // Contour lines: bright where elevation is near a contour level + contourDist := math.Mod(elevation, contourSpacing) + if contourDist > contourSpacing/2 { + contourDist = contourSpacing - contourDist + } + onLine := 0.0 + if contourDist < lineWidth { + onLine = 1.0 - contourDist/lineWidth + } + + // Base color from elevation + t := elevation + if t < 0 { + t = 0 + } + if t > 1 { + t = 1 + } + idx := t * float64(len(scheme)-1) + i1 := int(idx) + if i1 >= len(scheme)-1 { + i1 = len(scheme) - 2 + } + base := lerpColor(scheme[i1], scheme[i1+1], idx-float64(i1)) + + // Brighten contour lines + r := clamp(float64(base.R) + onLine*180) + g := clamp(float64(base.G) + onLine*180) + b := clamp(float64(base.B) + onLine*180) + + // Drift: horizontal displacement in bands + if math.Sin(float64(y)*0.02+seed1) > 0.85 { + shift := int(math.Sin(float64(y)*0.15) * 20) + nx := x + shift + if nx >= 0 && nx < w { + img.SetRGBA(nx, y, color.RGBA{r, g, b, 255}) + continue + } + } + img.SetRGBA(x, y, color.RGBA{r, g, b, 255}) + } + } + addScanlines(img, w, h, 0.03) + addGlitchBars(img, w, h, 5) +} + +// === CHROMATIC SHATTER === +// Splits RGB channels with geometric displacement — like broken glass refracting light +func drawChromaticShatter(img *image.RGBA, w, h int) { + // Generate a base pattern first (grayscale), then displace R/G/B separately + wf, hf := float64(w), float64(h) + seed := rand.Float64() * 100 + + // Base intensity field + baseVal := func(x, y int) float64 { + fx := float64(x)/wf*6 + seed + fy := float64(y)/hf*10 + seed*0.7 + v := math.Sin(fx*1.5)*math.Cos(fy*0.8) + + math.Sin(math.Hypot(fx-3, fy-5)*2)*0.6 + + math.Cos(fx*fy*0.1)*0.4 + return v*0.3 + 0.5 + } + + // Shatter zones: random triangular regions with big displacement + type Shard struct { + cx, cy float64 + angle float64 + shiftR int + shiftG int + shiftB int + radius float64 + } + numShards := 5 + rand.Intn(8) + shards := make([]Shard, numShards) + for i := range shards { + shards[i] = Shard{ + cx: rand.Float64() * wf, + cy: rand.Float64() * hf, + angle: rand.Float64() * math.Pi * 2, + shiftR: rand.Intn(40) - 20, + shiftG: rand.Intn(40) - 20, + shiftB: rand.Intn(40) - 20, + radius: 80 + rand.Float64()*250, + } + } + + // Background: dark + fillBg(img, w, h, color.RGBA{5, 3, 10, 255}, color.RGBA{10, 5, 18, 255}) + + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + // Find chromatic shift for this pixel + drx, dgx, dbx := 0, 0, 0 + dry, dgy, dby := 0, 0, 0 + for _, s := range shards { + dist := math.Hypot(float64(x)-s.cx, float64(y)-s.cy) + if dist < s.radius { + influence := 1 - dist/s.radius + influence *= influence // quadratic falloff + drx += int(float64(s.shiftR) * influence) + dgx += int(float64(s.shiftG) * influence * 0.5) + dbx += int(float64(s.shiftB) * influence) + dry += int(float64(s.shiftR) * influence * 0.3) + dgy += int(float64(s.shiftG) * influence) + dby += int(float64(s.shiftB) * influence * 0.7) + } + } + + // Sample each channel from displaced positions + sampleR := baseVal(x+drx, y+dry) + sampleG := baseVal(x+dgx, y+dgy) + sampleB := baseVal(x+dbx, y+dby) + + r := clamp(sampleR * 255) + g := clamp(sampleG * 200) + b := clamp(sampleB * 280) + + // Edge glow at shard boundaries + for _, s := range shards { + dist := math.Hypot(float64(x)-s.cx, float64(y)-s.cy) + edgeDist := math.Abs(dist - s.radius) + if edgeDist < 3 { + glow := (3 - edgeDist) / 3 * 0.7 + r = clamp(float64(r) + glow*200) + g = clamp(float64(g) + glow*200) + b = clamp(float64(b) + glow*200) + } + } + + img.SetRGBA(x, y, color.RGBA{r, g, b, 255}) + } + } + addGlitchBars(img, w, h, 7) + addScanlines(img, w, h, 0.04) +} + func rand_Intn(n int) uint8 { return uint8(rand.Intn(n)) }