added shadow blur to software implementation

This commit is contained in:
Thomas Friedel 2019-05-04 22:36:14 +02:00
parent e0b88c0ca6
commit 505386f199
4 changed files with 196 additions and 0 deletions

1
.gitignore vendored
View file

@ -2,6 +2,7 @@ test*.html
plan.txt
glowgen
testapp
testblur
videocap
.DS_Store
.vscode

View file

@ -0,0 +1,188 @@
package softwarebackend
import (
"image"
"image/color"
"image/draw"
"math"
)
func (b *SoftwareBackend) activateBlurTarget() {
b.blurSwap = b.Image
b.Image = image.NewRGBA(b.Image.Rect)
}
func (b *SoftwareBackend) drawBlurred(size float64) {
blurred := box3(b.Image, size)
b.Image = b.blurSwap
draw.Draw(b.Image, b.Image.Rect, blurred, image.ZP, draw.Over)
}
func box3(img *image.RGBA, size float64) *image.RGBA {
rsize := int(math.Round(size * 0.75)) // todo properly size
img = box3x(img, rsize)
img = box3x(img, rsize)
img = box3x(img, rsize)
img = box3y(img, rsize)
img = box3y(img, rsize)
img = box3y(img, rsize)
return img
}
func box3x(img *image.RGBA, size int) *image.RGBA {
bounds := img.Bounds()
result := image.NewRGBA(bounds)
w, h := bounds.Dx(), bounds.Dy()
for y := 0; y < h; y++ {
if size >= w {
var r, g, b, a float64
for x := 0; x < w; x++ {
col := img.RGBAAt(x, y)
r += float64(col.R)
g += float64(col.G)
b += float64(col.B)
a += float64(col.A)
}
factor := 1.0 / float64(w)
col := color.RGBA{
R: uint8(math.Round(r * factor)),
G: uint8(math.Round(g * factor)),
B: uint8(math.Round(b * factor)),
A: uint8(math.Round(a * factor)),
}
for x := 0; x < w; x++ {
result.SetRGBA(x, y, col)
}
continue
}
var r, g, b, a float64
for x := 0; x <= size; x++ {
col := img.RGBAAt(x, y)
r += float64(col.R)
g += float64(col.G)
b += float64(col.B)
a += float64(col.A)
}
samples := size + 1
x := 0
for {
factor := 1.0 / float64(samples)
col := color.RGBA{
R: uint8(math.Round(r * factor)),
G: uint8(math.Round(g * factor)),
B: uint8(math.Round(b * factor)),
A: uint8(math.Round(a * factor)),
}
result.SetRGBA(x, y, col)
if x >= w-1 {
break
}
if left := x - size; left >= 0 {
col = img.RGBAAt(left, y)
r -= float64(col.R)
g -= float64(col.G)
b -= float64(col.B)
a -= float64(col.A)
samples--
}
x++
if right := x + size; right < w {
col = img.RGBAAt(right, y)
r += float64(col.R)
g += float64(col.G)
b += float64(col.B)
a += float64(col.A)
samples++
}
}
}
return result
}
func box3y(img *image.RGBA, size int) *image.RGBA {
bounds := img.Bounds()
result := image.NewRGBA(bounds)
w, h := bounds.Dx(), bounds.Dy()
for x := 0; x < w; x++ {
if size >= h {
var r, g, b, a float64
for y := 0; y < h; y++ {
col := img.RGBAAt(x, y)
r += float64(col.R)
g += float64(col.G)
b += float64(col.B)
a += float64(col.A)
}
factor := 1.0 / float64(h)
col := color.RGBA{
R: uint8(math.Round(r * factor)),
G: uint8(math.Round(g * factor)),
B: uint8(math.Round(b * factor)),
A: uint8(math.Round(a * factor)),
}
for y := 0; y < h; y++ {
result.SetRGBA(x, y, col)
}
continue
}
var r, g, b, a float64
for y := 0; y <= size; y++ {
col := img.RGBAAt(x, y)
r += float64(col.R)
g += float64(col.G)
b += float64(col.B)
a += float64(col.A)
}
samples := size + 1
y := 0
for {
factor := 1.0 / float64(samples)
col := color.RGBA{
R: uint8(math.Round(r * factor)),
G: uint8(math.Round(g * factor)),
B: uint8(math.Round(b * factor)),
A: uint8(math.Round(a * factor)),
}
result.SetRGBA(x, y, col)
if y >= h-1 {
break
}
if top := y - size; top >= 0 {
col = img.RGBAAt(x, top)
r -= float64(col.R)
g -= float64(col.G)
b -= float64(col.B)
a -= float64(col.A)
samples--
}
y++
if bottom := y + size; bottom < h {
col = img.RGBAAt(x, bottom)
r += float64(col.R)
g += float64(col.G)
b += float64(col.B)
a += float64(col.A)
samples++
}
}
}
return result
}

View file

@ -20,6 +20,11 @@ func (b *SoftwareBackend) Clear(pts [4][2]float64) {
}
func (b *SoftwareBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
if style.Blur > 0 {
b.activateBlurTarget()
defer b.drawBlurred(style.Blur)
}
if lg := style.LinearGradient; lg != nil {
lg := lg.(*LinearGradient)
from := [2]float64{style.Gradient.X0, style.Gradient.Y0}

View file

@ -12,6 +12,8 @@ type SoftwareBackend struct {
MSAA int
blurSwap *image.RGBA
clip *image.Alpha
mask *image.Alpha
w, h int