implemented software gradients
This commit is contained in:
parent
e3bb07a09c
commit
a913b8b33b
3 changed files with 64 additions and 13 deletions
|
@ -244,7 +244,7 @@ void main() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float o = max(o1, o2);
|
float o = max(o1, o2);
|
||||||
float r = radFrom + o * (radTo - radFrom);
|
//float r = radFrom + o * (radTo - radFrom);
|
||||||
vec4 col = texture2D(gradient, vec2(o, 0.0));
|
vec4 col = texture2D(gradient, vec2(o, 0.0));
|
||||||
col.a *= texture2D(alphaTex, v_atc).a * globalAlpha;
|
col.a *= texture2D(alphaTex, v_atc).a * globalAlpha;
|
||||||
gl_FragColor = col;
|
gl_FragColor = col;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package softwarebackend
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
|
"math"
|
||||||
|
|
||||||
"github.com/tfriedel6/canvas/backend/backendbase"
|
"github.com/tfriedel6/canvas/backend/backendbase"
|
||||||
)
|
)
|
||||||
|
@ -19,23 +20,50 @@ func (b *SoftwareBackend) Clear(pts [4][2]float64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *SoftwareBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
|
func (b *SoftwareBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
|
||||||
p2 := b.mask.Pix
|
b.clearMask()
|
||||||
for i := range p2 {
|
|
||||||
p2[i] = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
iterateTriangles(pts[:], func(tri [][2]float64) {
|
if lg := style.LinearGradient; lg != nil {
|
||||||
b.fillTriangle(tri, func(x, y int) {
|
lg := lg.(*LinearGradient)
|
||||||
if b.clip.AlphaAt(x, y).A == 0 {
|
from := [2]float64{style.Gradient.X0, style.Gradient.Y0}
|
||||||
|
dir := [2]float64{style.Gradient.X1 - style.Gradient.X0, style.Gradient.Y1 - style.Gradient.Y0}
|
||||||
|
dirlen := math.Sqrt(dir[0]*dir[0] + dir[1]*dir[1])
|
||||||
|
dir[0] /= dirlen
|
||||||
|
dir[1] /= dirlen
|
||||||
|
b.fillTriangles(pts, func(x, y int) {
|
||||||
|
pos := [2]float64{float64(x) - from[0], float64(y) - from[1]}
|
||||||
|
r := (pos[0]*dir[0] + pos[1]*dir[1]) / dirlen
|
||||||
|
color := lg.data.ColorAt(r)
|
||||||
|
b.Image.SetRGBA(x, y, mix(color, b.Image.RGBAAt(x, y)))
|
||||||
|
})
|
||||||
|
} else if rg := style.RadialGradient; rg != nil {
|
||||||
|
rg := rg.(*RadialGradient)
|
||||||
|
from := [2]float64{style.Gradient.X0, style.Gradient.Y0}
|
||||||
|
to := [2]float64{style.Gradient.X1, style.Gradient.Y1}
|
||||||
|
radFrom := style.Gradient.RadFrom
|
||||||
|
radTo := style.Gradient.RadTo
|
||||||
|
b.fillTriangles(pts, func(x, y int) {
|
||||||
|
pos := [2]float64{float64(x), float64(y)}
|
||||||
|
oa := 0.5 * math.Sqrt(
|
||||||
|
math.Pow(-2.0*from[0]*from[0]+2.0*from[0]*to[0]+2.0*from[0]*pos[0]-2.0*to[0]*pos[0]-2.0*from[1]*from[1]+2.0*from[1]*to[1]+2.0*from[1]*pos[1]-2.0*to[1]*pos[1]+2.0*radFrom*radFrom-2.0*radFrom*radTo, 2.0)-
|
||||||
|
4.0*(from[0]*from[0]-2.0*from[0]*pos[0]+pos[0]*pos[0]+from[1]*from[1]-2.0*from[1]*pos[1]+pos[1]*pos[1]-radFrom*radFrom)*
|
||||||
|
(from[0]*from[0]-2.0*from[0]*to[0]+to[0]*to[0]+from[1]*from[1]-2.0*from[1]*to[1]+to[1]*to[1]-radFrom*radFrom+2.0*radFrom*radTo-radTo*radTo))
|
||||||
|
ob := (from[0]*from[0] - from[0]*to[0] - from[0]*pos[0] + to[0]*pos[0] + from[1]*from[1] - from[1]*to[1] - from[1]*pos[1] + to[1]*pos[1] - radFrom*radFrom + radFrom*radTo)
|
||||||
|
oc := (from[0]*from[0] - 2.0*from[0]*to[0] + to[0]*to[0] + from[1]*from[1] - 2.0*from[1]*to[1] + to[1]*to[1] - radFrom*radFrom + 2.0*radFrom*radTo - radTo*radTo)
|
||||||
|
o1 := (-oa + ob) / oc
|
||||||
|
o2 := (oa + ob) / oc
|
||||||
|
if math.IsNaN(o1) && math.IsNaN(o2) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if b.mask.AlphaAt(x, y).A > 0 {
|
o := math.Max(o1, o2)
|
||||||
return
|
col := rg.data.ColorAt(o)
|
||||||
}
|
b.Image.SetRGBA(x, y, mix(col, b.Image.RGBAAt(x, y)))
|
||||||
b.mask.SetAlpha(x, y, color.Alpha{A: 255})
|
b.Image.SetRGBA(x, y, color.RGBA{R: 255, A: 255})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
b.fillTriangles(pts, func(x, y int) {
|
||||||
b.Image.SetRGBA(x, y, mix(style.Color, b.Image.RGBAAt(x, y)))
|
b.Image.SetRGBA(x, y, mix(style.Color, b.Image.RGBAAt(x, y)))
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *SoftwareBackend) FillImageMask(style *backendbase.FillStyle, mask *image.Alpha, pts [4][2]float64) {
|
func (b *SoftwareBackend) FillImageMask(style *backendbase.FillStyle, mask *image.Alpha, pts [4][2]float64) {
|
||||||
|
@ -52,6 +80,13 @@ func (b *SoftwareBackend) FillImageMask(style *backendbase.FillStyle, mask *imag
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *SoftwareBackend) clearMask() {
|
||||||
|
p := b.mask.Pix
|
||||||
|
for i := range p {
|
||||||
|
p[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (b *SoftwareBackend) ClearClip() {
|
func (b *SoftwareBackend) ClearClip() {
|
||||||
p := b.clip.Pix
|
p := b.clip.Pix
|
||||||
for i := range p {
|
for i := range p {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package softwarebackend
|
package softwarebackend
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -173,3 +174,18 @@ func iterateTriangles(pts [][2]float64, fn func(tri [][2]float64)) {
|
||||||
fn(pts[i-3 : i])
|
fn(pts[i-3 : i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *SoftwareBackend) fillTriangles(pts [][2]float64, fn func(x, y int)) {
|
||||||
|
iterateTriangles(pts[:], func(tri [][2]float64) {
|
||||||
|
b.fillTriangle(tri, func(x, y int) {
|
||||||
|
if b.clip.AlphaAt(x, y).A == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if b.mask.AlphaAt(x, y).A > 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.mask.SetAlpha(x, y, color.Alpha{A: 255})
|
||||||
|
fn(x, y)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue