github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/pixel/cmc/main.go (about) 1 package main 2 3 import ( 4 "image/color" 5 "math/rand" 6 "time" 7 8 "github.com/faiface/pixel" 9 "github.com/faiface/pixel/pixelgl" 10 ) 11 12 const Detail = 1 << 16 13 14 func main() { 15 pixelgl.Run(run) 16 } 17 18 func run() { 19 cfg := pixelgl.WindowConfig{ 20 Title: "CMC!", 21 Bounds: pixel.R(0, 0, 480, 320), 22 Resizable: true, 23 VSync: true, 24 } 25 26 win, err := pixelgl.NewWindow(cfg) 27 if err != nil { 28 panic(err) 29 } 30 31 r := rand.New(rand.NewSource(0)) 32 33 canvas := NewImage() 34 backbuffer := pixel.MakePictureData(pixel.R(0, 0, 64, 64)) 35 for i := range backbuffer.Pix { 36 backbuffer.Pix[i] = color.RGBA{0xFF, 0x00, 0x00, 0xFF} 37 } 38 39 now := time.Now() 40 tt := float32(0.0) 41 brightness := float32(1.0) 42 for !win.Closed() { 43 win.SetClosed(win.JustPressed(pixelgl.KeyEscape)) 44 45 next := time.Now() 46 dt := next.Sub(now).Seconds() 47 now = next 48 if dt > 1.0/15.0 { 49 dt = 1.0 / 15.0 50 } 51 tt += float32(dt) 52 53 winsize := win.Bounds().Size() 54 if canvas.SetSize(int(winsize.X), int(winsize.Y)) { 55 backbuffer = pixel.MakePictureData( 56 pixel.R(0, 0, float64(canvas.Width), float64(canvas.Height)), 57 ) 58 } 59 canvas.Clear() 60 61 { 62 os := Sin(float32(tt)) 63 64 size := V{float32(winsize.X) * 0.5, float32(winsize.Y) * 0.5, 0} 65 for i := 0; i < Detail; i++ { 66 p := V{r.Float32() - 0.5, r.Float32() - 0.5, r.Float32() - 0.5} 67 p = N(p, 17) 68 h := Atan2(p.Y, p.X) 69 p = T0(tt, os, p) 70 p = Rx(Ry(p, tt), os) 71 canvas.Put(P(p, size), HL{h, 0.1}) 72 } 73 } 74 canvas.Smear() 75 76 if backbuffer.Stride != canvas.Width { 77 panic("invalid stride") 78 } 79 80 max, total, nz := float32(0.0), float32(0.0), 0 81 for _, v := range canvas.Pix { 82 if v.L == 0 { 83 continue 84 } 85 nz++ 86 total += v.L 87 if v.L > max { 88 max = v.L 89 } 90 } 91 average := total / float32(nz) 92 brightness = Lerp(brightness, Lerp(average, max, 0.1), 0.01) 93 scale := 1 / brightness 94 95 for i, v := range canvas.Pix { 96 backbuffer.Pix[i] = v.RGBA(scale) 97 } 98 99 sprite := pixel.NewSprite(backbuffer, backbuffer.Bounds()) 100 sprite.Draw(win, pixel.IM.Moved(win.Bounds().Center())) 101 102 win.Update() 103 } 104 } 105 106 func F0(tt float32, v V) float32 { return Sin(tt+v.X+v.Z) * 3 } 107 func F1(tt float32, v V) float32 { return Sin(tt+v.X/3+v.Y/3) + 1.5 } 108 func T0(tt, os float32, v V) V { 109 return S(v, F1(tt, v)+os*F0(tt, v)/10+os) 110 }