124 lines
2.3 KiB
Go
124 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"image"
|
|
|
|
"git.kirsle.net/go/render"
|
|
)
|
|
|
|
// App holds the ripple applet state.
|
|
type App struct {
|
|
e render.Engine
|
|
image image.Image
|
|
source *image.RGBA
|
|
data *image.RGBA
|
|
tex render.Texturer
|
|
|
|
// computed
|
|
width int
|
|
height int
|
|
size int
|
|
|
|
// frame buffers
|
|
buffer0 []int
|
|
buffer1 []int
|
|
}
|
|
|
|
// New creates the ripple applet.
|
|
func New(e render.Engine, i image.Image) *App {
|
|
var (
|
|
bounds = i.Bounds()
|
|
width = bounds.Max.X
|
|
height = bounds.Max.Y
|
|
size = width * height
|
|
)
|
|
a := &App{
|
|
e: e,
|
|
image: i,
|
|
source: render.ImageToRGBA(i),
|
|
data: render.ImageToRGBA(i),
|
|
width: width,
|
|
height: height,
|
|
size: size,
|
|
buffer0: make([]int, size),
|
|
buffer1: make([]int, size),
|
|
}
|
|
|
|
tex, err := a.e.StoreTexture("pic", a.data)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
a.tex = tex
|
|
return a
|
|
}
|
|
|
|
// Disturb creates a disturbance in the water.
|
|
func (a *App) Disturb(x, y, z int) {
|
|
if x < 2 || x > Width-2 || y < 1 || y > Height-2 {
|
|
return
|
|
}
|
|
var i = x + y*Width
|
|
a.buffer0[i] += z
|
|
a.buffer0[i-1] -= z
|
|
}
|
|
|
|
// Ripple runs the ripple algorithm.
|
|
func (a *App) Ripple() {
|
|
var (
|
|
width = a.width
|
|
size = a.size
|
|
)
|
|
|
|
// average cells to make the surface more even
|
|
for i := width + 1; i < size-width-1; i += 2 {
|
|
for x := 1; x < width-1; x++ {
|
|
avg := (a.buffer0[i] + a.buffer0[i+1] + a.buffer0[i-1] + a.buffer0[i-width] + a.buffer0[i+width]) / 5
|
|
a.buffer0[i] = avg
|
|
i++
|
|
}
|
|
}
|
|
|
|
// Loop for every non-edge element.
|
|
y := 0
|
|
for i := width + 1; i < size-width-1; i += 2 {
|
|
y++
|
|
for x := 1; x < width-1; x++ {
|
|
// Wave propagation
|
|
waveHeight := (a.buffer0[i-1]+
|
|
a.buffer0[i+1]+
|
|
a.buffer0[i+Width]+
|
|
a.buffer0[i-Width])/2 - a.buffer1[i]
|
|
a.buffer1[i] = waveHeight
|
|
|
|
// Some very fake lighting
|
|
var light = int(float64(waveHeight)*2.0 - float64(a.buffer1[i-2])*0.6)
|
|
if light < -10 {
|
|
light = -10
|
|
} else if light > 100 {
|
|
light = 100
|
|
}
|
|
|
|
color := a.source.At(x, y)
|
|
a.data.Set(x, y, render.FromColor(color).Lighten(light).ToColor())
|
|
|
|
i++
|
|
}
|
|
}
|
|
|
|
aux := a.buffer0
|
|
a.buffer0 = a.buffer1
|
|
a.buffer1 = aux
|
|
|
|
a.tex, _ = a.e.StoreTexture("pic", a.data)
|
|
}
|
|
|
|
// Present the visual state.
|
|
func (a *App) Present() {
|
|
rect := render.Rect{
|
|
W: a.width,
|
|
H: a.height,
|
|
}
|
|
a.e.Copy(a.tex, rect, rect)
|
|
a.e.Present()
|
|
}
|