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
This commit is contained in:
parent
4f2fa7b8d6
commit
35175d04a6
1 changed files with 183 additions and 3 deletions
186
daily.go
186
daily.go
|
|
@ -51,6 +51,8 @@ func main() {
|
||||||
{"bit-cascade", drawBitCascade},
|
{"bit-cascade", drawBitCascade},
|
||||||
{"deep-scan", drawDeepScan},
|
{"deep-scan", drawDeepScan},
|
||||||
{"entropy-wave", drawEntropyWave},
|
{"entropy-wave", drawEntropyWave},
|
||||||
|
{"topo-drift", drawTopoDrift},
|
||||||
|
{"chromatic-shatter", drawChromaticShatter},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shuffle and pick 6
|
// Shuffle and pick 6
|
||||||
|
|
@ -259,10 +261,18 @@ func drawFractalBurn(img *image.RGBA, w, h int) {
|
||||||
maxIter := 80 + rand.Intn(40)
|
maxIter := 80 + rand.Intn(40)
|
||||||
zoom := 200.0 + rand.Float64()*200
|
zoom := 200.0 + rand.Float64()*200
|
||||||
|
|
||||||
palette := []color.RGBA{
|
// Rotating palette selection for variety
|
||||||
{20, 0, 40, 255}, {80, 0, 120, 255}, {200, 50, 50, 255},
|
palettes := [][]color.RGBA{
|
||||||
{255, 150, 0, 255}, {255, 255, 100, 255}, {255, 255, 255, 255},
|
// 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 y := 0; y < h; y++ {
|
||||||
for x := 0; x < w; x++ {
|
for x := 0; x < w; x++ {
|
||||||
|
|
@ -597,6 +607,176 @@ func drawEntropyWave(img *image.RGBA, w, h int) {
|
||||||
addGlitchBars(img, w, h, 6)
|
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 {
|
func rand_Intn(n int) uint8 {
|
||||||
return uint8(rand.Intn(n))
|
return uint8(rand.Intn(n))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue