1
0
Fork 0
leet/draw.go

87 lines
1.9 KiB
Go

package main // import "github.com/serverwentdown/leet"
import (
"log"
ws2811 "github.com/rpi-ws281x/rpi-ws281x-go"
)
// TODO: full-sized grid with multiple channels mapped onto the grid
type Drawer struct {
layers [][]uint32
length int
device *ws2811.WS2811
}
func NewDrawer(length int) (*Drawer, error) {
opt := ws2811.DefaultOptions
opt.Channels[0].LedCount = length
d := &Drawer{}
d.length = length
d.layers = make([][]uint32, 100)
dev, err := ws2811.MakeWS2811(&opt)
if err != nil {
return nil, err
}
err = dev.Init()
if err != nil {
return nil, err
}
d.device = dev
return d, nil
}
func (d *Drawer) SetLayer(layer int32, dots []uint32) {
d.layers[layer] = dots
}
func (d *Drawer) SetLayerOrFill(layer int32, dots []uint32, fill uint32) {
if dots == nil {
fillDots := make([]uint32, d.length)
for i := 0; i < d.length; i++ {
fillDots[i] = fill
}
d.layers[layer] = fillDots
} else {
d.SetLayer(layer, dots)
}
}
func (d *Drawer) Draw() error {
for i := 0; i < len(d.device.Leds(0)); i++ {
dot := mix(d.layers, i)
d.device.Leds(0)[i] = dot
}
if err := d.device.Render(); err != nil {
return err
}
return nil
}
func mix(layers [][]uint32, j int) uint32 {
var base uint32
for i := 0; i < len(layers); i++ {
base = mixColors(base, layers[i][j])
}
return base
}
func mixColors(a uint32, b uint32) uint32 {
// Extract channels
aa, ba := uint32(a>>24), uint32(b>>24)
ar, br := a&uint32(0x00FF0000)>>16, b&uint32(0x00FF0000)>>16
ag, bg := a&uint32(0x0000FF00)>>8, b&uint32(0x0000FF00)>>8
ab, bb := a&uint32(0x000000FF), b&uint32(0x000000FF)
// Apply alpha computation to each channel
log.Println(aa, ar, ag, ab, ba, br, bg, bb)
oa := uint32(ba*(255-aa)/255 + aa)
or := uint32(br*ba*(255-aa)/(255*255) + ar*aa/255)
og := uint32(bg*ba*(255-aa)/(255*255) + ag*aa/255)
ob := uint32(bb*ba*(255-aa)/(255*255) + ab*aa/255)
return (oa << 24) | (or << 16) | (og << 8) | ob
}