From c5c8ac500f29fff0eae87926958c74f7517cad7f Mon Sep 17 00:00:00 2001 From: Thomas Friedel Date: Wed, 20 Feb 2019 16:34:56 +0100 Subject: [PATCH] some shadow drawing now works using the backend --- backend.go | 1 + backend/backendbase/base.go | 1 - backend/gogl/shadows.go | 84 ++++++++++++++++--------- canvas.go | 15 ++++- images.go | 2 +- paths.go | 122 ++---------------------------------- shadows.go | 39 +++++++++++- 7 files changed, 109 insertions(+), 155 deletions(-) diff --git a/backend.go b/backend.go index e3639a8..65f595c 100644 --- a/backend.go +++ b/backend.go @@ -6,4 +6,5 @@ type Backend interface { ClearRect(x, y, w, h int) Clear(pts [4][2]float64) Fill(style *backendbase.Style, pts [][2]float64) + // BlurredShadow(shadow *backendbase.Shadow, pts [][2]float64) } diff --git a/backend/backendbase/base.go b/backend/backendbase/base.go index e6f36f6..fc09224 100644 --- a/backend/backendbase/base.go +++ b/backend/backendbase/base.go @@ -5,7 +5,6 @@ import "image/color" type Style struct { Color color.RGBA GlobalAlpha float64 - Shadow Shadow // radialGradient *RadialGradient // linearGradient *LinearGradient // image *Image diff --git a/backend/gogl/shadows.go b/backend/gogl/shadows.go index f1b73c3..fe30350 100644 --- a/backend/gogl/shadows.go +++ b/backend/gogl/shadows.go @@ -1,37 +1,37 @@ package goglbackend /* -import ( - "image" - "math" - "unsafe" - - "github.com/go-gl/gl/v3.2-core/gl" - "github.com/tfriedel6/canvas/backend/backendbase" -) - -func (b *GoGLBackend) drawShadow(sh *backendbase.Shadow, tris []float32) { - if len(tris) == 0 || sh.Color.A == 0 { +func (b *GoGLBackend) FillShadow(shadow *backendbase.Shadow, pts [][2]float64) { + if len(pts) == 0 || shadow.Color.A == 0 { return } - if sh.Blur > 0 { - b.offscr1.alpha = true - cv.enableTextureRenderTarget(&b.offscr1) - gl.ClearColor(0, 0, 0, 0) - gl.Clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) + ox, oy := float32(shadow.OffsetX), float32(shadow.OffsetY) + + b.ptsBuf = b.ptsBuf[:0] + b.ptsBuf = append(b.ptsBuf, + 0, 0, + 0, float32(b.fh), + float32(b.fw), float32(b.fh), + float32(b.fw), 0) + for _, pt := range pts { + b.ptsBuf = append(b.ptsBuf, float32(pt[0])+ox, float32(pt[1])+oy) } - ox, oy := float32(sh.OffsetX), float32(sh.OffsetY) + // if sh.Blur > 0 { + // b.offscr1.alpha = true + // cv.enableTextureRenderTarget(&b.offscr1) + // gl.ClearColor(0, 0, 0, 0) + // gl.Clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) + // } - count := len(tris) - for i := 12; i < count; i += 2 { - tris[i] += ox - tris[i+1] += oy + mode := uint32(gl.TRIANGLES) + if len(pts) == 4 { + mode = gl.TRIANGLE_FAN } gl.BindBuffer(gl.ARRAY_BUFFER, b.shadowBuf) - gl.BufferData(gl.ARRAY_BUFFER, len(tris)*4, unsafe.Pointer(&tris[0]), gl.STREAM_DRAW) + gl.BufferData(gl.ARRAY_BUFFER, len(b.ptsBuf)*4, unsafe.Pointer(&b.ptsBuf[0]), gl.STREAM_DRAW) gl.ColorMask(false, false, false, false) gl.StencilFunc(gl.ALWAYS, 1, 0xFF) @@ -44,20 +44,20 @@ func (b *GoGLBackend) drawShadow(sh *backendbase.Shadow, tris []float32) { gl.EnableVertexAttribArray(b.sr.Vertex) gl.VertexAttribPointer(b.sr.Vertex, 2, gl.FLOAT, false, 0, nil) - gl.DrawArrays(gl.TRIANGLES, 6, int32(len(tris)/2-6)) + gl.DrawArrays(gl.TRIANGLES, 4, int32(len(pts))) gl.DisableVertexAttribArray(b.sr.Vertex) gl.ColorMask(true, true, true, true) gl.StencilFunc(gl.EQUAL, 1, 0xFF) - var style drawStyle - style.color = colorGLToGo(sh.Color) + var style backendbase.Style + style.Color = shadow.Color vertex := b.useShader(&style) gl.EnableVertexAttribArray(vertex) gl.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, nil) - gl.DrawArrays(gl.TRIANGLES, 0, 6) + gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) gl.DisableVertexAttribArray(vertex) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) @@ -66,11 +66,35 @@ func (b *GoGLBackend) drawShadow(sh *backendbase.Shadow, tris []float32) { gl.Clear(gl.STENCIL_BUFFER_BIT) gl.StencilMask(0xFF) - if sh.Blur > 0 { - b.drawBlurredShadow() - } -} + { + gl.DrawArrays(mode, 4, int32(len(pts))) + gl.DisableVertexAttribArray(b.sr.Vertex) + gl.ColorMask(true, true, true, true) + + gl.StencilFunc(gl.EQUAL, 1, 0xFF) + + vertex := b.useShader(style) + gl.EnableVertexAttribArray(vertex) + gl.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, nil) + + b.ptsBuf = append(b.ptsBuf[:0], 0, 0, float32(b.fw), 0, float32(b.fw), float32(b.fh), 0, float32(b.fh)) + gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) + gl.DisableVertexAttribArray(vertex) + + gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) + gl.StencilFunc(gl.ALWAYS, 0, 0xFF) + + gl.Clear(gl.STENCIL_BUFFER_BIT) + gl.StencilMask(0xFF) + } + + // if sh.Blur > 0 { + // b.drawBlurredShadow() + // } +} +*/ +/* func (b *GoGLBackend) drawTextShadow(sh *backendbase.Shadow, offset image.Point, strWidth, strHeight int, x, y float64) { x += sh.OffsetX y += sh.OffsetY diff --git a/canvas.go b/canvas.go index cdfbb4b..2c71662 100644 --- a/canvas.go +++ b/canvas.go @@ -33,6 +33,8 @@ type Canvas struct { offscreen bool offscrBuf offscreenBuffer offscrImg Image + + shadowBuf [][2]float64 } type drawState struct { @@ -58,7 +60,7 @@ type drawState struct { scissor scissor clip Path2D - shadowColor glColor + shadowColor color.RGBA shadowOffsetX float64 shadowOffsetY float64 shadowBlur float64 @@ -500,6 +502,15 @@ func (cv *Canvas) backendStyle(s *drawStyle, alpha float64) backendbase.Style { } } +func (cv *Canvas) backendShadow() backendbase.Shadow { + return backendbase.Shadow{ + Color: cv.state.shadowColor, + OffsetX: cv.state.shadowOffsetX, + OffsetY: cv.state.shadowOffsetY, + Blur: cv.state.shadowBlur, + } +} + func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) { if lg := style.linearGradient; lg != nil { lg.load() @@ -843,7 +854,7 @@ func (cv *Canvas) SetTransform(a, b, c, d, e, f float64) { // then no shadow is drawn func (cv *Canvas) SetShadowColor(color ...interface{}) { if c, ok := parseColor(color...); ok { - cv.state.shadowColor = colorGoToGL(c) + cv.state.shadowColor = c } } diff --git a/images.go b/images.go index a791000..004b605 100644 --- a/images.go +++ b/images.go @@ -324,7 +324,7 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float64) { p2 := cv.tf(vec{dx + dw, dy + dh}) p3 := cv.tf(vec{dx + dw, dy}) - if cv.state.shadowColor.a != 0 { + if cv.state.shadowColor.A != 0 { tris := [24]float32{ 0, 0, float32(cv.fw), 0, diff --git a/paths.go b/paths.go index b763f3e..76a3bd4 100644 --- a/paths.go +++ b/paths.go @@ -156,62 +156,10 @@ func (cv *Canvas) strokePath(path *Path2D) { start = false } - // todo draw shadow + cv.drawShadow2(tris) stl := cv.backendStyle(&cv.state.stroke, 1) cv.b.Fill(&stl, tris) - - // gli.BindBuffer(gl_ARRAY_BUFFER, buf) - // gli.BufferData(gl_ARRAY_BUFFER, len(tris)*4, unsafe.Pointer(&tris[0]), gl_STREAM_DRAW) - - // cv.drawShadow(tris) - - // gli.BindBuffer(gl_ARRAY_BUFFER, buf) - - // if cv.state.globalAlpha >= 1 && cv.state.lineAlpha >= 1 && cv.state.stroke.isOpaque() { - // vertex := cv.useShader(&cv.state.stroke) - - // gli.EnableVertexAttribArray(vertex) - // gli.VertexAttribPointer(vertex, 2, gl_FLOAT, false, 0, 0) - // gli.DrawArrays(gl_TRIANGLES, 6, int32(len(tris)/2-6)) - // gli.DisableVertexAttribArray(vertex) - // } else { - // gli.ColorMask(false, false, false, false) - // gli.StencilFunc(gl_ALWAYS, 1, 0xFF) - // gli.StencilOp(gl_REPLACE, gl_REPLACE, gl_REPLACE) - // gli.StencilMask(0x01) - - // gli.UseProgram(sr.id) - // gli.Uniform4f(sr.color, 0, 0, 0, 0) - // gli.Uniform2f(sr.canvasSize, float32(cv.fw), float32(cv.fh)) - - // gli.EnableVertexAttribArray(sr.vertex) - // gli.VertexAttribPointer(sr.vertex, 2, gl_FLOAT, false, 0, 0) - // gli.DrawArrays(gl_TRIANGLES, 6, int32(len(tris)/2-6)) - // gli.DisableVertexAttribArray(sr.vertex) - - // gli.ColorMask(true, true, true, true) - - // gli.StencilFunc(gl_EQUAL, 1, 0xFF) - - // origAlpha := cv.state.globalAlpha - // if cv.state.lineAlpha < 1 { - // cv.state.globalAlpha *= cv.state.lineAlpha - // } - // vertex := cv.useShader(&cv.state.stroke) - // cv.state.globalAlpha = origAlpha - - // gli.EnableVertexAttribArray(vertex) - // gli.VertexAttribPointer(vertex, 2, gl_FLOAT, false, 0, 0) - // gli.DrawArrays(gl_TRIANGLES, 0, 6) - // gli.DisableVertexAttribArray(vertex) - - // gli.StencilOp(gl_KEEP, gl_KEEP, gl_KEEP) - // gli.StencilFunc(gl_ALWAYS, 0, 0xFF) - - // gli.Clear(gl_STENCIL_BUFFER_BIT) - // gli.StencilMask(0xFF) - // } } func (cv *Canvas) applyLineDash(path []pathPoint) []pathPoint { @@ -402,56 +350,10 @@ func (cv *Canvas) FillPath(path *Path2D) { return } - // todo draw shadow + cv.drawShadow2(tris) stl := cv.backendStyle(&cv.state.fill, 1) cv.b.Fill(&stl, tris) - - // gli.BindBuffer(gl_ARRAY_BUFFER, buf) - // gli.BufferData(gl_ARRAY_BUFFER, len(tris)*4, unsafe.Pointer(&tris[0]), gl_STREAM_DRAW) - - // cv.drawShadow(tris) - - // gli.BindBuffer(gl_ARRAY_BUFFER, buf) - - // if cv.state.globalAlpha >= 1 && cv.state.lineAlpha >= 1 && cv.state.fill.isOpaque() { - // vertex := cv.useShader(&cv.state.fill) - - // gli.EnableVertexAttribArray(vertex) - // gli.VertexAttribPointer(vertex, 2, gl_FLOAT, false, 0, 0) - // gli.DrawArrays(gl_TRIANGLES, 6, int32(len(tris)/2-6)) - // gli.DisableVertexAttribArray(vertex) - // } else { - // gli.ColorMask(false, false, false, false) - // gli.StencilFunc(gl_ALWAYS, 1, 0xFF) - // gli.StencilOp(gl_REPLACE, gl_REPLACE, gl_REPLACE) - // gli.StencilMask(0x01) - - // gli.UseProgram(sr.id) - // gli.Uniform4f(sr.color, 0, 0, 0, 0) - // gli.Uniform2f(sr.canvasSize, float32(cv.fw), float32(cv.fh)) - - // gli.EnableVertexAttribArray(sr.vertex) - // gli.VertexAttribPointer(sr.vertex, 2, gl_FLOAT, false, 0, 0) - // gli.DrawArrays(gl_TRIANGLES, 6, int32(len(tris)/2-6)) - // gli.DisableVertexAttribArray(sr.vertex) - - // gli.ColorMask(true, true, true, true) - - // gli.StencilFunc(gl_EQUAL, 1, 0xFF) - - // vertex := cv.useShader(&cv.state.fill) - // gli.EnableVertexAttribArray(vertex) - // gli.VertexAttribPointer(vertex, 2, gl_FLOAT, false, 0, 0) - // gli.DrawArrays(gl_TRIANGLES, 0, 6) - // gli.DisableVertexAttribArray(vertex) - - // gli.StencilOp(gl_KEEP, gl_KEEP, gl_KEEP) - // gli.StencilFunc(gl_ALWAYS, 0, 0xFF) - - // gli.Clear(gl_STENCIL_BUFFER_BIT) - // gli.StencilMask(0xFF) - // } } func (cv *Canvas) appendSubPathTriangles(tris [][2]float64, path []pathPoint) [][2]float64 { @@ -622,26 +524,10 @@ func (cv *Canvas) FillRect(x, y, w, h float64) { p2 := cv.tf(vec{x + w, y + h}) p3 := cv.tf(vec{x + w, y}) - if cv.state.shadowColor.a != 0 { - tris := [24]float32{ - 0, 0, - float32(cv.fw), 0, - float32(cv.fw), float32(cv.fh), - 0, 0, - float32(cv.fw), float32(cv.fh), - 0, float32(cv.fh), - float32(p0[0]), float32(p0[1]), - float32(p3[0]), float32(p3[1]), - float32(p2[0]), float32(p2[1]), - float32(p0[0]), float32(p0[1]), - float32(p2[0]), float32(p2[1]), - float32(p1[0]), float32(p1[1]), - } - cv.drawShadow(tris[:]) - } - data := [4][2]float64{{p0[0], p0[1]}, {p1[0], p1[1]}, {p2[0], p2[1]}, {p3[0], p3[1]}} + cv.drawShadow2(data[:]) + stl := cv.backendStyle(&cv.state.fill, 1) cv.b.Fill(&stl, data[:]) } diff --git a/shadows.go b/shadows.go index e17f2f8..1ea30c7 100644 --- a/shadows.go +++ b/shadows.go @@ -4,10 +4,39 @@ import ( "image" "math" "unsafe" + + "github.com/tfriedel6/canvas/backend/backendbase" ) +func (cv *Canvas) drawShadow2(pts [][2]float64) { + if cv.state.shadowColor.A == 0 { + return + } + if cv.state.shadowOffsetX == 0 && cv.state.shadowOffsetY == 0 { + return + } + + if cv.shadowBuf == nil || cap(cv.shadowBuf) < len(pts) { + cv.shadowBuf = make([][2]float64, 0, len(pts)+1000) + } + cv.shadowBuf = cv.shadowBuf[:0] + + for _, pt := range pts { + cv.shadowBuf = append(cv.shadowBuf, [2]float64{ + pt[0] + cv.state.shadowOffsetX, + pt[1] + cv.state.shadowOffsetY, + }) + } + + shadow := cv.backendShadow() + if cv.state.shadowBlur == 0 { + style := backendbase.Style{Color: shadow.Color, GlobalAlpha: 1} + cv.b.Fill(&style, cv.shadowBuf) + } +} + func (cv *Canvas) drawShadow(tris []float32) { - if len(tris) == 0 || cv.state.shadowColor.a == 0 { + if len(tris) == 0 || cv.state.shadowColor.A == 0 { return } @@ -48,7 +77,7 @@ func (cv *Canvas) drawShadow(tris []float32) { gli.StencilFunc(gl_EQUAL, 1, 0xFF) var style drawStyle - style.color = colorGLToGo(cv.state.shadowColor) + style.color = cv.state.shadowColor vertex := cv.useShader(&style) gli.EnableVertexAttribArray(vertex) @@ -68,6 +97,10 @@ func (cv *Canvas) drawShadow(tris []float32) { } func (cv *Canvas) drawTextShadow(offset image.Point, strWidth, strHeight int, x, y float64) { + if cv.state.shadowColor.A == 0 { + return + } + x += cv.state.shadowOffsetX y += cv.state.shadowOffsetY @@ -83,7 +116,7 @@ func (cv *Canvas) drawTextShadow(offset image.Point, strWidth, strHeight int, x, gli.BindBuffer(gl_ARRAY_BUFFER, buf) var style drawStyle - style.color = colorGLToGo(cv.state.shadowColor) + style.color = cv.state.shadowColor vertex, alphaTexCoord := cv.useAlphaShader(&style, 1)