// Daily Glitch Wallpaper Generator // Generates 6 unique glitch-inspired wallpapers at Pixel 8 resolution (1080x2400) // Each run produces different art via randomized parameters and algorithm selection. // // Usage: go run daily.go [output-dir] package main import ( "fmt" "image" "image/color" "image/png" "math" "math/rand" "os" "path/filepath" "time" ) const ( W = 1080 H = 2400 ) func main() { rand.Seed(time.Now().UnixNano()) outDir := "daily-output" if len(os.Args) > 1 { outDir = os.Args[1] } os.MkdirAll(outDir, 0755) // Pool of generators — pick 6 unique ones (or repeat with different params if pool < 6) type Generator struct { Name string Draw func(img *image.RGBA, w, h int) } generators := []Generator{ {"ghost-in-the-machine", drawGhost}, {"pixel-aurora", drawAurora}, {"data-rain", drawDataRain}, {"fractal-burn", drawFractalBurn}, {"void-signal", drawVoidSignal}, {"neon-decay", drawNeonDecay}, {"static-portrait", drawStaticPortrait}, {"circuit-dream", drawCircuitDream}, {"plasma-tear", drawPlasmaTear}, {"bit-cascade", drawBitCascade}, {"deep-scan", drawDeepScan}, {"entropy-wave", drawEntropyWave}, {"topo-drift", drawTopoDrift}, {"chromatic-shatter", drawChromaticShatter}, } // Shuffle and pick 6 rand.Shuffle(len(generators), func(i, j int) { generators[i], generators[j] = generators[j], generators[i] }) for i := 0; i < 6; i++ { gen := generators[i] img := image.NewRGBA(image.Rect(0, 0, W, H)) gen.Draw(img, W, H) name := fmt.Sprintf("%02d-%s.png", i+1, gen.Name) path := filepath.Join(outDir, name) f, err := os.Create(path) if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) continue } png.Encode(f, img) f.Close() fmt.Printf("āœ“ %s\n", path) } fmt.Println("\nšŸŽŖ Done!") } func clamp(v float64) uint8 { if v < 0 { return 0 } if v > 255 { return 255 } return uint8(v) } func lerpColor(a, b color.RGBA, t float64) color.RGBA { return color.RGBA{ clamp(float64(a.R)*(1-t) + float64(b.R)*t), clamp(float64(a.G)*(1-t) + float64(b.G)*t), clamp(float64(a.B)*(1-t) + float64(b.B)*t), 255, } } func fillBg(img *image.RGBA, w, h int, top, bot color.RGBA) { for y := 0; y < h; y++ { t := float64(y) / float64(h) c := lerpColor(top, bot, t) for x := 0; x < w; x++ { img.SetRGBA(x, y, c) } } } func addScanlines(img *image.RGBA, w, h int, intensity float64) { for y := 0; y < h; y += 2 + rand.Intn(3) { a := intensity * (0.5 + rand.Float64()*0.5) for x := 0; x < w; x++ { c := img.RGBAAt(x, y) c.R = clamp(float64(c.R) * (1 - a)) c.G = clamp(float64(c.G) * (1 - a)) c.B = clamp(float64(c.B) * (1 - a)) img.SetRGBA(x, y, c) } } } func addGlitchBars(img *image.RGBA, w, h int, count int) { for i := 0; i < count; i++ { barY := rand.Intn(h) barH := 1 + rand.Intn(4) shift := rand.Intn(30) - 15 tint := []color.RGBA{ {255, 0, 80, 255}, {0, 255, 200, 255}, {200, 0, 255, 255}, {255, 200, 0, 255}, }[rand.Intn(4)] a := 0.1 + rand.Float64()*0.25 for dy := 0; dy < barH; dy++ { yy := barY + dy if yy >= h { break } for x := 0; x < w; x++ { sx := x + shift if sx < 0 || sx >= w { continue } c := img.RGBAAt(sx, yy) c.R = clamp(float64(c.R)*(1-a) + float64(tint.R)*a) c.G = clamp(float64(c.G)*(1-a) + float64(tint.G)*a) c.B = clamp(float64(c.B)*(1-a) + float64(tint.B)*a) img.SetRGBA(x, yy, c) } } } } // === GENERATORS === func drawGhost(img *image.RGBA, w, h int) { fillBg(img, w, h, color.RGBA{3, 3, 12, 255}, color.RGBA{10, 8, 30, 255}) cx := float64(w) / 2 startY := float64(h) * 0.12 fh := float64(h) * 0.70 n := w * 120 for i := 0; i < n; i++ { t := float64(i) / float64(n) sway := math.Sin(t*22+rand.Float64()*0.5) * float64(w) * (0.08 - t*0.05) spread := math.Sin(t*math.Pi) * float64(w) * 0.12 px := int(cx + sway + (rand.Float64()-0.5)*spread*2) py := int(startY + t*fh + (rand.Float64()-0.5)*4) if px < 0 || px >= w || py < 0 || py >= h { continue } alpha := (1 - t) * 0.85 if rand.Float64() > 0.96 { for dx := -8; dx < 15+rand.Intn(w/12); dx++ { sx := px + dx if sx >= 0 && sx < w { img.SetRGBA(sx, py, color.RGBA{clamp(255 * alpha), 0, clamp(100 * alpha), 255}) } } } else { img.SetRGBA(px, py, color.RGBA{clamp(150 * alpha), clamp(200 * alpha), clamp(255 * alpha), 255}) } } addScanlines(img, w, h, 0.04) addGlitchBars(img, w, h, 6) } func drawAurora(img *image.RGBA, w, h int) { phase1 := rand.Float64() * math.Pi * 2 phase2 := rand.Float64() * math.Pi * 2 freq := 0.003 + rand.Float64()*0.004 fillBg(img, w, h, color.RGBA{2, 2, 15, 255}, color.RGBA{5, 3, 20, 255}) for y := 0; y < h; y++ { fy := float64(y) / float64(h) // Aurora bands in the upper portion bandIntensity := math.Exp(-math.Pow((fy-0.3)/0.25, 2)) for x := 0; x < w; x++ { fx := float64(x) wave1 := math.Sin(fx*freq+phase1+fy*3) * 0.5 wave2 := math.Cos(fx*freq*1.7+phase2+fy*2) * 0.3 v := (wave1 + wave2 + 0.5) * bandIntensity tear := 0.0 if math.Sin(fy*80+fx*0.01) > 0.97 { tear = 0.4 } r := clamp(v*80 + tear*200) g := clamp(v * 255) b := clamp(v*180 + tear*100) c := img.RGBAAt(x, y) c.R = clamp(float64(c.R) + float64(r)) c.G = clamp(float64(c.G) + float64(g)) c.B = clamp(float64(c.B) + float64(b)) img.SetRGBA(x, y, c) } } // Stars for i := 0; i < 400; i++ { px, py := rand.Intn(w), rand.Intn(h/2) b := uint8(100 + rand.Intn(155)) img.SetRGBA(px, py, color.RGBA{b, b, b, 255}) } addGlitchBars(img, w, h, 4) } func drawDataRain(img *image.RGBA, w, h int) { baseHue := rand.Float64() // randomize color each run fillBg(img, w, h, color.RGBA{0, 0, 0, 255}, color.RGBA{5, 5, 10, 255}) cols := w / 8 for c := 0; c < cols; c++ { x := c*8 + rand.Intn(4) speed := 3 + rand.Intn(8) startOff := rand.Intn(h) length := 40 + rand.Intn(120) for i := 0; i < length; i++ { y := (startOff + i*speed) % h t := float64(i) / float64(length) brightness := (1 - t) * 0.9 // HSV-ish color from baseHue r := clamp(math.Sin(baseHue*math.Pi*2)*100*brightness + 50*brightness) g := clamp(math.Sin((baseHue+0.33)*math.Pi*2)*100*brightness + 200*brightness) b := clamp(math.Sin((baseHue+0.66)*math.Pi*2)*100*brightness + 80*brightness) for dx := 0; dx < 3; dx++ { if x+dx < w { img.SetRGBA(x+dx, y, color.RGBA{r, g, b, 255}) } } } } addScanlines(img, w, h, 0.06) addGlitchBars(img, w, h, 10) } func drawFractalBurn(img *image.RGBA, w, h int) { cx := float64(w)/2 + rand.Float64()*100 - 50 cy := float64(h)/2 + rand.Float64()*200 - 100 maxIter := 80 + rand.Intn(40) zoom := 200.0 + rand.Float64()*200 // 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++ { zr := (float64(x) - cx) / zoom zi := (float64(y) - cy) / zoom cr, ci := zr, zi iter := 0 for ; iter < maxIter; iter++ { zr2, zi2 := zr*zr, zi*zi if zr2+zi2 > 4 { break } zr, zi = zr2-zi2+cr, 2*zr*zi+ci } t := float64(iter) / float64(maxIter) idx := t * float64(len(palette)-1) i1 := int(idx) if i1 >= len(palette)-1 { i1 = len(palette) - 2 } frac := idx - float64(i1) // Burn effect — occasional pixel corruption if (x*131+y*97+iter*3)%200 < 3 { img.SetRGBA(x, y, color.RGBA{255, 255, 255, 255}) } else { img.SetRGBA(x, y, lerpColor(palette[i1], palette[i1+1], frac)) } } } addGlitchBars(img, w, h, 8) } func drawVoidSignal(img *image.RGBA, w, h int) { fillBg(img, w, h, color.RGBA{0, 0, 0, 255}, color.RGBA{0, 0, 5, 255}) ringCx := float64(w)/2 + rand.Float64()*60 - 30 ringCy := float64(h)*0.4 + rand.Float64()*100 for y := 0; y < h; y++ { for x := 0; x < w; x++ { dist := math.Hypot(float64(x)-ringCx, float64(y)-ringCy) ring := math.Sin(dist*0.04) * 0.5 * math.Exp(-dist*0.001) noise := float64((x*9871+y*6563)%256) / 256.0 v := ring*0.8 + noise*0.05 // Color: deep teal to white r := clamp(v * 150) g := clamp(v * 255) b := clamp(v * 280) img.SetRGBA(x, y, color.RGBA{r, g, b, 255}) } } addScanlines(img, w, h, 0.08) addGlitchBars(img, w, h, 12) } func drawNeonDecay(img *image.RGBA, w, h int) { neonColors := []color.RGBA{ {255, 0, 110, 255}, {0, 255, 200, 255}, {130, 50, 255, 255}, {255, 200, 0, 255}, {0, 150, 255, 255}, } pick := neonColors[rand.Intn(len(neonColors))] pick2 := neonColors[rand.Intn(len(neonColors))] fillBg(img, w, h, color.RGBA{8, 5, 15, 255}, color.RGBA{15, 8, 25, 255}) // Neon lines that decay for l := 0; l < 30+rand.Intn(20); l++ { y := rand.Intn(h) thickness := 2 + rand.Intn(6) c := pick if rand.Float64() > 0.5 { c = pick2 } decayStart := rand.Intn(w / 2) for x := 0; x < w; x++ { alpha := 1.0 if x > decayStart { decay := float64(x-decayStart) / float64(w-decayStart) alpha = 1 - decay // Chunk decay — blocks disappear if ((x/8)*17+l*31)%10 < int(decay*10) { continue } } for dy := 0; dy < thickness; dy++ { yy := y + dy if yy < h { img.SetRGBA(x, yy, color.RGBA{ clamp(float64(c.R) * alpha), clamp(float64(c.G) * alpha), clamp(float64(c.B) * alpha), 255, }) } } } } addScanlines(img, w, h, 0.03) } func drawStaticPortrait(img *image.RGBA, w, h int) { // TV static with a silhouette carved out for y := 0; y < h; y++ { for x := 0; x < w; x++ { v := uint8(rand.Intn(60)) img.SetRGBA(x, y, color.RGBA{v, v, v, 255}) } } // Silhouette — oval head + body headCx, headCy := float64(w)/2, float64(h)*0.28 headRx, headRy := float64(w)*0.12, float64(w)*0.15 bodyCx, bodyCy := float64(w)/2, float64(h)*0.65 bodyRx, bodyRy := float64(w)*0.22, float64(h)*0.3 for y := 0; y < h; y++ { for x := 0; x < w; x++ { fx, fy := float64(x), float64(y) inHead := math.Pow((fx-headCx)/headRx, 2)+math.Pow((fy-headCy)/headRy, 2) < 1 inBody := math.Pow((fx-bodyCx)/bodyRx, 2)+math.Pow((fy-bodyCy)/bodyRy, 2) < 1 if inHead || inBody { img.SetRGBA(x, y, color.RGBA{0, 0, 0, 255}) } } } // Glitch the silhouette edges addGlitchBars(img, w, h, 15) addScanlines(img, w, h, 0.1) } func drawCircuitDream(img *image.RGBA, w, h int) { accent := []color.RGBA{ {0, 255, 180, 255}, {0, 150, 255, 255}, {255, 100, 0, 255}, }[rand.Intn(3)] fillBg(img, w, h, color.RGBA{5, 10, 15, 255}, color.RGBA{10, 15, 25, 255}) // Grid of circuit-like paths gridSize := 20 + rand.Intn(20) for gy := 0; gy < h/gridSize; gy++ { for gx := 0; gx < w/gridSize; gx++ { if rand.Float64() > 0.3 { continue } x1 := gx * gridSize y1 := gy * gridSize // Draw horizontal or vertical trace horizontal := rand.Float64() > 0.5 length := gridSize * (1 + rand.Intn(4)) thick := 1 + rand.Intn(2) alpha := 0.3 + rand.Float64()*0.7 for d := 0; d < length; d++ { for t := 0; t < thick; t++ { var px, py int if horizontal { px, py = x1+d, y1+t } else { px, py = x1+t, y1+d } if px >= 0 && px < w && py >= 0 && py < h { img.SetRGBA(px, py, color.RGBA{ clamp(float64(accent.R) * alpha), clamp(float64(accent.G) * alpha), clamp(float64(accent.B) * alpha), 255, }) } } } // Node dot at start for dx := -2; dx <= 2; dx++ { for dy := -2; dy <= 2; dy++ { px, py := x1+dx, y1+dy if px >= 0 && px < w && py >= 0 && py < h { img.SetRGBA(px, py, accent) } } } } } addGlitchBars(img, w, h, 5) } func drawPlasmaTear(img *image.RGBA, w, h int) { p1 := rand.Float64() * 10 p2 := rand.Float64() * 10 p3 := rand.Float64() * 10 for y := 0; y < h; y++ { for x := 0; x < w; x++ { fx := float64(x) / float64(w) * 8 fy := float64(y) / float64(h) * 8 v1 := math.Sin(fx*1.5 + p1) v2 := math.Sin(fy*2.0 + p2) v3 := math.Sin((fx+fy)*1.2 + p3) v4 := math.Sin(math.Hypot(fx-4, fy-4) * 1.5) v := (v1 + v2 + v3 + v4) / 4.0 r := clamp((v*0.5 + 0.5) * 255) g := clamp((math.Sin(v*math.Pi)*0.5 + 0.5) * 200) b := clamp(((1-v)*0.5 + 0.5) * 255) // Tear: horizontal displacement if math.Sin(float64(y)*0.05) > 0.92 { shift := int(math.Sin(float64(y)*0.3) * 40) nx := x + shift if nx >= 0 && nx < w { img.SetRGBA(nx, y, color.RGBA{r, g, b, 255}) } } else { img.SetRGBA(x, y, color.RGBA{r, g, b, 255}) } } } addScanlines(img, w, h, 0.05) } func drawBitCascade(img *image.RGBA, w, h int) { shift := rand.Intn(8) fillBg(img, w, h, color.RGBA{0, 0, 0, 255}, color.RGBA{0, 0, 10, 255}) for y := 0; y < h; y++ { for x := 0; x < w; x++ { bx, by := x>>2, y>>2 v1 := (bx ^ by) >> shift v2 := (bx & by) v3 := (bx | by) * 3 r := uint8((v1 * 13) % 256) g := uint8((v2 * 7) % 256) b := uint8((v3 * 5) % 256) // Cascade: progressive corruption downward corruptChance := float64(y) / float64(h) if rand.Float64() < corruptChance*0.02 { r, g, b = 255-r, 255-g, 255-b } img.SetRGBA(x, y, color.RGBA{r, g, b, 255}) } } addGlitchBars(img, w, h, int(float64(h)*0.005)) } func drawDeepScan(img *image.RGBA, w, h int) { scanY := rand.Float64() accent := []color.RGBA{ {0, 255, 100, 255}, {255, 50, 50, 255}, {50, 100, 255, 255}, }[rand.Intn(3)] fillBg(img, w, h, color.RGBA{0, 0, 0, 255}, color.RGBA{5, 5, 8, 255}) // Horizontal bands of data for y := 0; y < h; y++ { fy := float64(y) / float64(h) bandDist := math.Abs(fy - scanY) intensity := math.Exp(-bandDist * 8) for x := 0; x < w; x++ { noise := float64((x*3571+y*2819)%256) / 256.0 v := intensity * (0.5 + noise*0.5) r := clamp(float64(accent.R) * v) g := clamp(float64(accent.G) * v) b := clamp(float64(accent.B) * v) // Data blocks if intensity > 0.3 && (x/6+y/3)%4 == 0 { r = clamp(float64(r) * 2) g = clamp(float64(g) * 2) b = clamp(float64(b) * 2) } img.SetRGBA(x, y, color.RGBA{r, g, b, 255}) } } addScanlines(img, w, h, 0.06) addGlitchBars(img, w, h, 8) } func drawEntropyWave(img *image.RGBA, w, h int) { seed1 := rand.Float64() * 100 seed2 := rand.Float64() * 100 palette := []color.RGBA{ {uint8(rand.Intn(256) | 128), uint8(rand.Intn(128)), uint8(rand.Intn(256)), 255}, {uint8(rand.Intn(128)), uint8(rand.Intn(256) | 128), uint8(rand.Intn(256)), 255}, {uint8(rand.Intn(256)), uint8(rand.Intn(128)), uint8(rand.Intn(256) | 128), 255}, } for y := 0; y < h; y++ { for x := 0; x < w; x++ { fx := float64(x)/float64(w)*6 + seed1 fy := float64(y)/float64(h)*6 + seed2 v := math.Sin(fx*2)*math.Cos(fy*3) + math.Sin((fx+fy)*1.5)*0.5 + math.Cos(fx*fy*0.3)*0.3 // Normalize -ish to 0..1 v = v*0.3 + 0.5 if v < 0 { v = 0 } if v > 1 { v = 1 } idx := v * float64(len(palette)-1) i1 := int(idx) if i1 >= len(palette)-1 { i1 = len(palette) - 2 } frac := idx - float64(i1) c := lerpColor(palette[i1], palette[i1+1], frac) // Entropy: increasing noise toward bottom entropy := float64(y) / float64(h) if rand.Float64() < entropy*0.08 { c.R ^= uint8(rand.Intn(256)) c.G ^= uint8(rand.Intn(256)) c.B ^= uint8(rand.Intn(256)) } img.SetRGBA(x, y, c) } } 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)) }