diff --git a/backend.go b/backend.go index 28940c2..6b64057 100644 --- a/backend.go +++ b/backend.go @@ -1,5 +1,9 @@ package canvas +import "github.com/tfriedel6/canvas/backend/backendbase" + type Backend interface { ClearRect(x, y, w, h int) + Clear(pts [4][2]float64) + Fill(style *backendbase.Style, pts [4][2]float64) } diff --git a/backend/backendbase/base.go b/backend/backendbase/base.go new file mode 100644 index 0000000..afce75d --- /dev/null +++ b/backend/backendbase/base.go @@ -0,0 +1,11 @@ +package backendbase + +import "image/color" + +type Style struct { + Color color.RGBA + GlobalAlpha float64 + // radialGradient *RadialGradient + // linearGradient *LinearGradient + // image *Image +} diff --git a/backend/gogl/fill.go b/backend/gogl/fill.go new file mode 100644 index 0000000..722c93a --- /dev/null +++ b/backend/gogl/fill.go @@ -0,0 +1,109 @@ +package goglbackend + +import ( + "unsafe" + + "github.com/go-gl/gl/v3.2-core/gl" + "github.com/tfriedel6/canvas/backend/backendbase" +) + +/* +// FillRect fills a rectangle with the active fill style +func (b *GoGLBackend) FillRect(x, y, w, h float64) { + cv.activate() + + p0 := cv.tf(vec{x, y}) + p1 := cv.tf(vec{x, y + h}) + 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[:]) + } + + gl.BindBuffer(gl_ARRAY_BUFFER, buf) + data := [8]float32{float32(p0[0]), float32(p0[1]), float32(p1[0]), float32(p1[1]), float32(p2[0]), float32(p2[1]), float32(p3[0]), float32(p3[1])} + gl.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW) + + gl.StencilFunc(gl_EQUAL, 0, 0xFF) + + vertex := cv.useShader(&cv.state.fill) + gl.VertexAttribPointer(vertex, 2, gl_FLOAT, false, 0, 0) + gl.EnableVertexAttribArray(vertex) + gl.DrawArrays(gl_TRIANGLE_FAN, 0, 4) + gl.DisableVertexAttribArray(vertex) + + gl.StencilFunc(gl_ALWAYS, 0, 0xFF) +} +*/ + +// ClearRect sets the color of the rectangle to transparent black +func (b *GoGLBackend) ClearRect(x, y, w, h int) { + gl.Scissor(int32(x), int32(b.h-y-h), int32(w), int32(h)) + gl.ClearColor(0, 0, 0, 0) + gl.Clear(gl.COLOR_BUFFER_BIT) + // cv.applyScissor() +} + +func (b *GoGLBackend) Clear(pts [4][2]float64) { + data := [8]float32{ + float32(pts[0][0]), float32(pts[0][1]), + float32(pts[1][0]), float32(pts[1][1]), + float32(pts[2][0]), float32(pts[2][1]), + float32(pts[3][0]), float32(pts[3][1])} + + gl.UseProgram(b.sr.ID) + gl.Uniform2f(b.sr.CanvasSize, float32(b.fw), float32(b.fh)) + gl.Uniform4f(b.sr.Color, 0, 0, 0, 0) + gl.Uniform1f(b.sr.GlobalAlpha, 1) + + gl.Disable(gl.BLEND) + + gl.BindBuffer(gl.ARRAY_BUFFER, b.buf) + gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl.STREAM_DRAW) + + gl.StencilFunc(gl.EQUAL, 0, 0xFF) + + gl.VertexAttribPointer(b.sr.Vertex, 2, gl.FLOAT, false, 0, nil) + gl.EnableVertexAttribArray(b.sr.Vertex) + gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) + gl.DisableVertexAttribArray(b.sr.Vertex) + + gl.StencilFunc(gl.ALWAYS, 0, 0xFF) + + gl.Enable(gl.BLEND) +} + +func (b *GoGLBackend) Fill(style *backendbase.Style, pts [4][2]float64) { + gl.BindBuffer(gl.ARRAY_BUFFER, b.buf) + data := [8]float32{ + float32(pts[0][0]), float32(pts[0][1]), + float32(pts[1][0]), float32(pts[1][1]), + float32(pts[2][0]), float32(pts[2][1]), + float32(pts[3][0]), float32(pts[3][1])} + gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl.STREAM_DRAW) + + gl.StencilFunc(gl.EQUAL, 0, 0xFF) + + vertex := b.useShader(style) + gl.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, nil) + gl.EnableVertexAttribArray(vertex) + gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) + gl.DisableVertexAttribArray(vertex) + + gl.StencilFunc(gl.ALWAYS, 0, 0xFF) +} diff --git a/backend/gogl/gogl.go b/backend/gogl/gogl.go index 3ad8158..a8d88c5 100644 --- a/backend/gogl/gogl.go +++ b/backend/gogl/gogl.go @@ -2,9 +2,11 @@ package goglbackend import ( "fmt" + "image/color" "github.com/go-gl/gl/v3.2-core/gl" "github.com/tfriedel6/canvas" + "github.com/tfriedel6/canvas/backend/backendbase" ) const alphaTexSize = 2048 @@ -213,3 +215,150 @@ func glError() error { } return nil } + +type glColor struct { + r, g, b, a float64 +} + +func colorGoToGL(c color.RGBA) glColor { + var glc glColor + glc.r = float64(c.R) / 255 + glc.g = float64(c.G) / 255 + glc.b = float64(c.B) / 255 + glc.a = float64(c.A) / 255 + return glc +} + +func (b *GoGLBackend) useShader(style *backendbase.Style) (vertexLoc uint32) { + // if lg := style.LinearGradient; lg != nil { + // lg.load() + // gl.ActiveTexture(gl.TEXTURE0) + // gl.BindTexture(gl.TEXTURE_2D, lg.tex) + // gl.UseProgram(lgr.id) + // from := cv.tf(lg.from) + // to := cv.tf(lg.to) + // dir := to.sub(from) + // length := dir.len() + // dir = dir.divf(length) + // gl.Uniform2f(lgr.canvasSize, float32(cv.fw), float32(cv.fh)) + // inv := cv.state.transform.invert().f32() + // gl.UniformMatrix3fv(lgr.invmat, 1, false, &inv[0]) + // gl.Uniform2f(lgr.from, float32(from[0]), float32(from[1])) + // gl.Uniform2f(lgr.dir, float32(dir[0]), float32(dir[1])) + // gl.Uniform1f(lgr.len, float32(length)) + // gl.Uniform1i(lgr.gradient, 0) + // gl.Uniform1f(lgr.globalAlpha, float32(cv.state.globalAlpha)) + // return lgr.vertex + // } + // if rg := style.RadialGradient; rg != nil { + // rg.load() + // gl.ActiveTexture(gl.TEXTURE0) + // gl.BindTexture(gl.TEXTURE_2D, rg.tex) + // gl.UseProgram(rgr.id) + // from := cv.tf(rg.from) + // to := cv.tf(rg.to) + // dir := to.sub(from) + // length := dir.len() + // dir = dir.divf(length) + // gl.Uniform2f(rgr.canvasSize, float32(cv.fw), float32(cv.fh)) + // inv := cv.state.transform.invert().f32() + // gl.UniformMatrix3fv(rgr.invmat, 1, false, &inv[0]) + // gl.Uniform2f(rgr.from, float32(from[0]), float32(from[1])) + // gl.Uniform2f(rgr.to, float32(to[0]), float32(to[1])) + // gl.Uniform2f(rgr.dir, float32(dir[0]), float32(dir[1])) + // gl.Uniform1f(rgr.radFrom, float32(rg.radFrom)) + // gl.Uniform1f(rgr.radTo, float32(rg.radTo)) + // gl.Uniform1f(rgr.len, float32(length)) + // gl.Uniform1i(rgr.gradient, 0) + // gl.Uniform1f(rgr.globalAlpha, float32(cv.state.globalAlpha)) + // return rgr.vertex + // } + // if img := style.Image; img != nil { + // gl.UseProgram(ipr.id) + // gl.ActiveTexture(gl.TEXTURE0) + // gl.BindTexture(gl.TEXTURE_2D, img.tex) + // gl.Uniform2f(ipr.canvasSize, float32(cv.fw), float32(cv.fh)) + // inv := cv.state.transform.invert().f32() + // gl.UniformMatrix3fv(ipr.invmat, 1, false, &inv[0]) + // gl.Uniform2f(ipr.imageSize, float32(img.w), float32(img.h)) + // gl.Uniform1i(ipr.image, 0) + // gl.Uniform1f(ipr.globalAlpha, float32(cv.state.globalAlpha)) + // return ipr.vertex + // } + + gl.UseProgram(b.sr.ID) + gl.Uniform2f(b.sr.CanvasSize, float32(b.fw), float32(b.fh)) + c := colorGoToGL(style.Color) + gl.Uniform4f(b.sr.Color, float32(c.r), float32(c.g), float32(c.b), float32(c.a)) + gl.Uniform1f(b.sr.GlobalAlpha, float32(style.GlobalAlpha)) + return b.sr.Vertex +} + +func (b *GoGLBackend) useAlphaShader(style *backendbase.Style, alphaTexSlot int32) (vertexLoc, alphaTexCoordLoc uint32) { + // if lg := style.LinearGradient; lg != nil { + // lg.load() + // gl.ActiveTexture(gl.TEXTURE0) + // gl.BindTexture(gl.TEXTURE_2D, lg.tex) + // gl.UseProgram(lgar.id) + // from := cv.tf(lg.from) + // to := cv.tf(lg.to) + // dir := to.sub(from) + // length := dir.len() + // dir = dir.divf(length) + // gl.Uniform2f(lgar.canvasSize, float32(cv.fw), float32(cv.fh)) + // inv := cv.state.transform.invert().f32() + // gl.UniformMatrix3fv(lgar.invmat, 1, false, &inv[0]) + // gl.Uniform2f(lgar.from, float32(from[0]), float32(from[1])) + // gl.Uniform2f(lgar.dir, float32(dir[0]), float32(dir[1])) + // gl.Uniform1f(lgar.len, float32(length)) + // gl.Uniform1i(lgar.gradient, 0) + // gl.Uniform1i(lgar.alphaTex, alphaTexSlot) + // gl.Uniform1f(lgar.globalAlpha, float32(cv.state.globalAlpha)) + // return lgar.vertex, lgar.alphaTexCoord + // } + // if rg := style.RadialGradient; rg != nil { + // rg.load() + // gl.ActiveTexture(gl.TEXTURE0) + // gl.BindTexture(gl.TEXTURE_2D, rg.tex) + // gl.UseProgram(rgar.id) + // from := cv.tf(rg.from) + // to := cv.tf(rg.to) + // dir := to.sub(from) + // length := dir.len() + // dir = dir.divf(length) + // gl.Uniform2f(rgar.canvasSize, float32(cv.fw), float32(cv.fh)) + // inv := cv.state.transform.invert().f32() + // gl.UniformMatrix3fv(rgar.invmat, 1, false, &inv[0]) + // gl.Uniform2f(rgar.from, float32(from[0]), float32(from[1])) + // gl.Uniform2f(rgar.to, float32(to[0]), float32(to[1])) + // gl.Uniform2f(rgar.dir, float32(dir[0]), float32(dir[1])) + // gl.Uniform1f(rgar.radFrom, float32(rg.radFrom)) + // gl.Uniform1f(rgar.radTo, float32(rg.radTo)) + // gl.Uniform1f(rgar.len, float32(length)) + // gl.Uniform1i(rgar.gradient, 0) + // gl.Uniform1i(rgar.alphaTex, alphaTexSlot) + // gl.Uniform1f(rgar.globalAlpha, float32(cv.state.globalAlpha)) + // return rgar.vertex, rgar.alphaTexCoord + // } + // if img := style.Image; img != nil { + // gl.UseProgram(ipar.id) + // gl.ActiveTexture(gl.TEXTURE0) + // gl.BindTexture(gl.TEXTURE_2D, img.tex) + // gl.Uniform2f(ipar.canvasSize, float32(cv.fw), float32(cv.fh)) + // inv := cv.state.transform.invert().f32() + // gl.UniformMatrix3fv(ipar.invmat, 1, false, &inv[0]) + // gl.Uniform2f(ipar.imageSize, float32(img.w), float32(img.h)) + // gl.Uniform1i(ipar.image, 0) + // gl.Uniform1i(ipar.alphaTex, alphaTexSlot) + // gl.Uniform1f(ipar.globalAlpha, float32(cv.state.globalAlpha)) + // return ipar.vertex, ipar.alphaTexCoord + // } + + gl.UseProgram(b.sar.ID) + gl.Uniform2f(b.sar.CanvasSize, float32(b.fw), float32(b.fh)) + c := colorGoToGL(style.Color) + gl.Uniform4f(b.sar.Color, float32(c.r), float32(c.g), float32(c.b), float32(c.a)) + gl.Uniform1i(b.sar.AlphaTex, alphaTexSlot) + gl.Uniform1f(b.sar.GlobalAlpha, float32(style.GlobalAlpha)) + return b.sar.Vertex, b.sar.AlphaTexCoord +} diff --git a/backend/gogl/rects.go b/backend/gogl/rects.go deleted file mode 100644 index 8c62f08..0000000 --- a/backend/gogl/rects.go +++ /dev/null @@ -1,57 +0,0 @@ -package goglbackend - -import ( - "github.com/go-gl/gl/v3.2-core/gl" -) - -/* -// FillRect fills a rectangle with the active fill style -func (b *GoGLBackend) FillRect(x, y, w, h float64) { - cv.activate() - - p0 := cv.tf(vec{x, y}) - p1 := cv.tf(vec{x, y + h}) - 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[:]) - } - - gl.BindBuffer(gl_ARRAY_BUFFER, buf) - data := [8]float32{float32(p0[0]), float32(p0[1]), float32(p1[0]), float32(p1[1]), float32(p2[0]), float32(p2[1]), float32(p3[0]), float32(p3[1])} - gl.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW) - - gl.StencilFunc(gl_EQUAL, 0, 0xFF) - - vertex := cv.useShader(&cv.state.fill) - gl.VertexAttribPointer(vertex, 2, gl_FLOAT, false, 0, 0) - gl.EnableVertexAttribArray(vertex) - gl.DrawArrays(gl_TRIANGLE_FAN, 0, 4) - gl.DisableVertexAttribArray(vertex) - - gl.StencilFunc(gl_ALWAYS, 0, 0xFF) -} -*/ - -// ClearRect sets the color of the rectangle to transparent black -func (b *GoGLBackend) ClearRect(x, y, w, h int) { - gl.Scissor(int32(x), int32(b.h-y-h), int32(w), int32(h)) - gl.ClearColor(0, 0, 0, 0) - gl.Clear(gl.COLOR_BUFFER_BIT) - // cv.applyScissor() -} diff --git a/canvas.go b/canvas.go index bf23cc7..f8cc405 100644 --- a/canvas.go +++ b/canvas.go @@ -8,6 +8,7 @@ import ( "os" "github.com/golang/freetype/truetype" + "github.com/tfriedel6/canvas/backend/backendbase" "golang.org/x/image/font" ) @@ -36,8 +37,8 @@ type Canvas struct { type drawState struct { transform mat - fill DrawStyle - stroke DrawStyle + fill drawStyle + stroke drawStyle font *Font fontSize float64 fontMetrics font.Metrics @@ -73,11 +74,11 @@ type drawState struct { */ } -type DrawStyle struct { - Color color.RGBA - RadialGradient *RadialGradient - LinearGradient *LinearGradient - Image *Image +type drawStyle struct { + color color.RGBA + radialGradient *RadialGradient + linearGradient *LinearGradient + image *Image } type scissor struct { @@ -147,8 +148,8 @@ func New(backend Backend, x, y, w, h int) *Canvas { cv.state.lineAlpha = 1 cv.state.miterLimitSqr = 100 cv.state.globalAlpha = 1 - cv.state.fill.Color = color.RGBA{A: 255} - cv.state.stroke.Color = color.RGBA{A: 255} + cv.state.fill.color = color.RGBA{A: 255} + cv.state.stroke.color = color.RGBA{A: 255} cv.state.transform = matIdentity() return cv } @@ -455,45 +456,52 @@ func (cv *Canvas) SetStrokeStyle(value ...interface{}) { cv.state.stroke = parseStyle(value...) } -func parseStyle(value ...interface{}) DrawStyle { - var style DrawStyle +func parseStyle(value ...interface{}) drawStyle { + var style drawStyle if len(value) == 1 { switch v := value[0].(type) { case *LinearGradient: - style.LinearGradient = v + style.linearGradient = v return style case *RadialGradient: - style.RadialGradient = v + style.radialGradient = v return style } } c, ok := parseColor(value...) if ok { - style.Color = c + style.color = c } else if len(value) == 1 { switch v := value[0].(type) { case *Image, string: - style.Image = getImage(v) + style.image = getImage(v) } } return style } -func (s *DrawStyle) isOpaque() bool { - if lg := s.LinearGradient; lg != nil { +func (s *drawStyle) isOpaque() bool { + if lg := s.linearGradient; lg != nil { return lg.opaque } - if rg := s.RadialGradient; rg != nil { + if rg := s.radialGradient; rg != nil { return rg.opaque } - if img := s.Image; img != nil { + if img := s.image; img != nil { return img.opaque } - return s.Color.A >= 255 + return s.color.A >= 255 } -func (cv *Canvas) useShader(style *DrawStyle) (vertexLoc uint32) { - if lg := style.LinearGradient; lg != nil { +func (cv *Canvas) backendStyle(s *drawStyle) backendbase.Style { + return backendbase.Style{ + Color: s.color, + GlobalAlpha: cv.state.globalAlpha, + } +} + +func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) { + if lg := style.linearGradient; lg != nil { lg.load() gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_2D, lg.tex) @@ -511,7 +519,7 @@ func (cv *Canvas) useShader(style *DrawStyle) (vertexLoc uint32) { gli.Uniform1f(lgr.globalAlpha, float32(cv.state.globalAlpha)) return lgr.vertex } - if rg := style.RadialGradient; rg != nil { + if rg := style.radialGradient; rg != nil { rg.load() gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_2D, rg.tex) @@ -532,7 +540,7 @@ func (cv *Canvas) useShader(style *DrawStyle) (vertexLoc uint32) { gli.Uniform1f(rgr.globalAlpha, float32(cv.state.globalAlpha)) return rgr.vertex } - if img := style.Image; img != nil { + if img := style.image; img != nil { gli.UseProgram(ipr.id) gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_2D, img.tex) @@ -545,14 +553,14 @@ func (cv *Canvas) useShader(style *DrawStyle) (vertexLoc uint32) { gli.UseProgram(sr.id) gli.Uniform2f(sr.canvasSize, float32(cv.fw), float32(cv.fh)) - c := colorGoToGL(style.Color) + c := colorGoToGL(style.color) gli.Uniform4f(sr.color, float32(c.r), float32(c.g), float32(c.b), float32(c.a)) gli.Uniform1f(sr.globalAlpha, float32(cv.state.globalAlpha)) return sr.vertex } -func (cv *Canvas) useAlphaShader(style *DrawStyle, alphaTexSlot int32) (vertexLoc, alphaTexCoordLoc uint32) { - if lg := style.LinearGradient; lg != nil { +func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLoc, alphaTexCoordLoc uint32) { + if lg := style.linearGradient; lg != nil { lg.load() gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_2D, lg.tex) @@ -571,7 +579,7 @@ func (cv *Canvas) useAlphaShader(style *DrawStyle, alphaTexSlot int32) (vertexLo gli.Uniform1f(lgar.globalAlpha, float32(cv.state.globalAlpha)) return lgar.vertex, lgar.alphaTexCoord } - if rg := style.RadialGradient; rg != nil { + if rg := style.radialGradient; rg != nil { rg.load() gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_2D, rg.tex) @@ -593,7 +601,7 @@ func (cv *Canvas) useAlphaShader(style *DrawStyle, alphaTexSlot int32) (vertexLo gli.Uniform1f(rgar.globalAlpha, float32(cv.state.globalAlpha)) return rgar.vertex, rgar.alphaTexCoord } - if img := style.Image; img != nil { + if img := style.image; img != nil { gli.UseProgram(ipar.id) gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_2D, img.tex) @@ -607,7 +615,7 @@ func (cv *Canvas) useAlphaShader(style *DrawStyle, alphaTexSlot int32) (vertexLo gli.UseProgram(sar.id) gli.Uniform2f(sar.canvasSize, float32(cv.fw), float32(cv.fh)) - c := colorGoToGL(style.Color) + c := colorGoToGL(style.color) gli.Uniform4f(sar.color, float32(c.r), float32(c.g), float32(c.b), float32(c.a)) gli.Uniform1i(sar.alphaTex, alphaTexSlot) gli.Uniform1f(sar.globalAlpha, float32(cv.state.globalAlpha)) diff --git a/paths.go b/paths.go index 4c13fea..547371a 100644 --- a/paths.go +++ b/paths.go @@ -646,19 +646,10 @@ func (cv *Canvas) FillRect(x, y, w, h float64) { cv.drawShadow(tris[:]) } - gli.BindBuffer(gl_ARRAY_BUFFER, buf) - data := [8]float32{float32(p0[0]), float32(p0[1]), float32(p1[0]), float32(p1[1]), float32(p2[0]), float32(p2[1]), float32(p3[0]), float32(p3[1])} - gli.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW) + data := [4][2]float64{{p0[0], p0[1]}, {p1[0], p1[1]}, {p2[0], p2[1]}, {p3[0], p3[1]}} - gli.StencilFunc(gl_EQUAL, 0, 0xFF) - - vertex := cv.useShader(&cv.state.fill) - gli.VertexAttribPointer(vertex, 2, gl_FLOAT, false, 0, 0) - gli.EnableVertexAttribArray(vertex) - gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4) - gli.DisableVertexAttribArray(vertex) - - gli.StencilFunc(gl_ALWAYS, 0, 0xFF) + stl := cv.backendStyle(&cv.state.fill) + cv.b.Fill(&stl, data) } // ClearRect sets the color of the rectangle to transparent black @@ -671,30 +662,12 @@ func (cv *Canvas) ClearRect(x, y, w, h float64) { return } - gli.UseProgram(sr.id) - gli.Uniform2f(sr.canvasSize, float32(cv.fw), float32(cv.fh)) - gli.Uniform4f(sr.color, 0, 0, 0, 0) - gli.Uniform1f(sr.globalAlpha, 1) - - gli.Disable(gl_BLEND) - p0 := cv.tf(vec{x, y}) p1 := cv.tf(vec{x, y + h}) p2 := cv.tf(vec{x + w, y + h}) p3 := cv.tf(vec{x + w, y}) - gli.BindBuffer(gl_ARRAY_BUFFER, buf) - data := [8]float32{float32(p0[0]), float32(p0[1]), float32(p1[0]), float32(p1[1]), float32(p2[0]), float32(p2[1]), float32(p3[0]), float32(p3[1])} - gli.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW) + data := [4][2]float64{{p0[0], p0[1]}, {p1[0], p1[1]}, {p2[0], p2[1]}, {p3[0], p3[1]}} - gli.StencilFunc(gl_EQUAL, 0, 0xFF) - - gli.VertexAttribPointer(sr.vertex, 2, gl_FLOAT, false, 0, 0) - gli.EnableVertexAttribArray(sr.vertex) - gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4) - gli.DisableVertexAttribArray(sr.vertex) - - gli.StencilFunc(gl_ALWAYS, 0, 0xFF) - - gli.Enable(gl_BLEND) + cv.b.Clear(data) } diff --git a/shadows.go b/shadows.go index eb3898b..e17f2f8 100644 --- a/shadows.go +++ b/shadows.go @@ -47,8 +47,8 @@ func (cv *Canvas) drawShadow(tris []float32) { gli.StencilFunc(gl_EQUAL, 1, 0xFF) - var style DrawStyle - style.Color = colorGLToGo(cv.state.shadowColor) + var style drawStyle + style.color = colorGLToGo(cv.state.shadowColor) vertex := cv.useShader(&style) gli.EnableVertexAttribArray(vertex) @@ -82,8 +82,8 @@ 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) + var style drawStyle + style.color = colorGLToGo(cv.state.shadowColor) vertex, alphaTexCoord := cv.useAlphaShader(&style, 1)