109 lines
3.1 KiB
Go
109 lines
3.1 KiB
Go
package goglbackend
|
|
|
|
import (
|
|
"runtime"
|
|
|
|
"github.com/go-gl/gl/v3.2-core/gl"
|
|
"github.com/tfriedel6/canvas/backend/backendbase"
|
|
)
|
|
|
|
// LinearGradient is a gradient with any number of
|
|
// stops and any number of colors. The gradient will
|
|
// be drawn such that each point on the gradient
|
|
// will correspond to a straight line
|
|
type LinearGradient struct {
|
|
gradient
|
|
}
|
|
|
|
// RadialGradient is a gradient with any number of
|
|
// stops and any number of colors. The gradient will
|
|
// be drawn such that each point on the gradient
|
|
// will correspond to a circle
|
|
type RadialGradient struct {
|
|
gradient
|
|
radFrom, radTo float64
|
|
}
|
|
|
|
type gradient struct {
|
|
from, to vec
|
|
tex uint32
|
|
loaded bool
|
|
deleted bool
|
|
opaque bool
|
|
}
|
|
|
|
func (b *GoGLBackend) LoadLinearGradient(data *backendbase.LinearGradientData) backendbase.LinearGradient {
|
|
lg := &LinearGradient{
|
|
gradient: gradient{from: vec{data.X0, data.Y0}, to: vec{data.X1, data.Y1}, opaque: true},
|
|
}
|
|
gl.GenTextures(1, &lg.tex)
|
|
gl.ActiveTexture(gl.TEXTURE0)
|
|
gl.BindTexture(gl.TEXTURE_2D, lg.tex)
|
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
|
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
|
|
lg.load(data.Stops)
|
|
runtime.SetFinalizer(lg, func(lg *LinearGradient) {
|
|
b.glChan <- func() {
|
|
gl.DeleteTextures(1, &lg.tex)
|
|
}
|
|
})
|
|
return lg
|
|
}
|
|
|
|
func (b *GoGLBackend) LoadRadialGradient(data *backendbase.RadialGradientData) backendbase.RadialGradient {
|
|
rg := &RadialGradient{
|
|
gradient: gradient{from: vec{data.X0, data.Y0}, to: vec{data.X1, data.Y1}, opaque: true},
|
|
radFrom: data.RadFrom,
|
|
radTo: data.RadTo,
|
|
}
|
|
gl.GenTextures(1, &rg.tex)
|
|
gl.ActiveTexture(gl.TEXTURE0)
|
|
gl.BindTexture(gl.TEXTURE_2D, rg.tex)
|
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
|
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
|
|
rg.load(data.Stops)
|
|
runtime.SetFinalizer(rg, func(rg *RadialGradient) {
|
|
b.glChan <- func() {
|
|
gl.DeleteTextures(1, &rg.tex)
|
|
}
|
|
})
|
|
return rg
|
|
}
|
|
|
|
// Delete explicitly deletes the gradient
|
|
func (g *gradient) Delete() {
|
|
gl.DeleteTextures(1, &g.tex)
|
|
g.deleted = true
|
|
}
|
|
|
|
func (g *gradient) IsDeleted() bool { return g.deleted }
|
|
func (g *gradient) IsOpaque() bool { return g.opaque }
|
|
|
|
func (lg *LinearGradient) Replace(data *backendbase.LinearGradientData) { lg.load(data.Stops) }
|
|
func (rg *RadialGradient) Replace(data *backendbase.RadialGradientData) { rg.load(data.Stops) }
|
|
|
|
func (g *gradient) load(stops backendbase.Gradient) {
|
|
if g.loaded {
|
|
return
|
|
}
|
|
|
|
gl.ActiveTexture(gl.TEXTURE0)
|
|
gl.BindTexture(gl.TEXTURE_2D, g.tex)
|
|
var pixels [2048 * 4]byte
|
|
pp := 0
|
|
for i := 0; i < 2048; i++ {
|
|
c := stops.ColorAt(float64(i) / 2047)
|
|
pixels[pp] = c.R
|
|
pixels[pp+1] = c.G
|
|
pixels[pp+2] = c.B
|
|
pixels[pp+3] = c.A
|
|
pp += 4
|
|
}
|
|
|
|
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2048, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(&pixels[0]))
|
|
g.loaded = true
|
|
}
|