87 lines
1.9 KiB
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
|
||
|
}
|