From 359b52f473509b3c0efd674b52343dccebb7797a Mon Sep 17 00:00:00 2001 From: Thomas Friedel Date: Sun, 17 Feb 2019 11:52:53 +0100 Subject: [PATCH] more general backend fill function --- backend.go | 2 +- backend/gogl/fill.go | 70 ++++++++++++++++++++++++++++++++++++++++---- backend/gogl/gogl.go | 11 ++++--- canvas.go | 4 +-- paths.go | 4 +-- 5 files changed, 76 insertions(+), 15 deletions(-) diff --git a/backend.go b/backend.go index 6b64057..e3639a8 100644 --- a/backend.go +++ b/backend.go @@ -5,5 +5,5 @@ 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) + Fill(style *backendbase.Style, pts [][2]float64) } diff --git a/backend/gogl/fill.go b/backend/gogl/fill.go index 722c93a..bf52a29 100644 --- a/backend/gogl/fill.go +++ b/backend/gogl/fill.go @@ -35,19 +35,19 @@ func (b *GoGLBackend) FillRect(x, y, w, h float64) { cv.drawShadow(tris[:]) } - gl.BindBuffer(gl_ARRAY_BUFFER, buf) + 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.BufferData(gl.ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl.STREAM_DRAW) - gl.StencilFunc(gl_EQUAL, 0, 0xFF) + gl.StencilFunc(gl.EQUAL, 0, 0xFF) vertex := cv.useShader(&cv.state.fill) - gl.VertexAttribPointer(vertex, 2, gl_FLOAT, false, 0, 0) + gl.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, 0) gl.EnableVertexAttribArray(vertex) - gl.DrawArrays(gl_TRIANGLE_FAN, 0, 4) + gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4) gl.DisableVertexAttribArray(vertex) - gl.StencilFunc(gl_ALWAYS, 0, 0xFF) + gl.StencilFunc(gl.ALWAYS, 0, 0xFF) } */ @@ -88,6 +88,7 @@ func (b *GoGLBackend) Clear(pts [4][2]float64) { 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{ @@ -107,3 +108,60 @@ func (b *GoGLBackend) Fill(style *backendbase.Style, pts [4][2]float64) { gl.StencilFunc(gl.ALWAYS, 0, 0xFF) } +*/ + +func (b *GoGLBackend) Fill(style *backendbase.Style, pts [][2]float64) { + b.ptsBuf = b.ptsBuf[:0] + for _, pt := range pts { + b.ptsBuf = append(b.ptsBuf, float32(pt[0]), float32(pt[1])) + } + + mode := uint32(gl.TRIANGLES) + if len(pts) == 4 { + mode = gl.TRIANGLE_FAN + } + + gl.BindBuffer(gl.ARRAY_BUFFER, b.buf) + gl.BufferData(gl.ARRAY_BUFFER, len(b.ptsBuf)*4, unsafe.Pointer(&b.ptsBuf[0]), gl.STREAM_DRAW) + + if style.GlobalAlpha >= 1 { // && cv.state.fill.isOpaque() { + vertex := b.useShader(style) + + gl.EnableVertexAttribArray(vertex) + gl.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, nil) + gl.DrawArrays(mode, 0, int32(len(b.ptsBuf)/2)) + gl.DisableVertexAttribArray(vertex) + } else { + gl.ColorMask(false, false, false, false) + gl.StencilFunc(gl.ALWAYS, 1, 0xFF) + gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE) + gl.StencilMask(0x01) + + gl.UseProgram(b.sr.ID) + gl.Uniform4f(b.sr.Color, 0, 0, 0, 0) + gl.Uniform2f(b.sr.CanvasSize, float32(b.fw), float32(b.fh)) + + gl.EnableVertexAttribArray(b.sr.Vertex) + gl.VertexAttribPointer(b.sr.Vertex, 2, gl.FLOAT, false, 0, nil) + gl.DrawArrays(mode, 0, int32(len(b.ptsBuf)/2)) + 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) + } +} diff --git a/backend/gogl/gogl.go b/backend/gogl/gogl.go index a8d88c5..6450559 100644 --- a/backend/gogl/gogl.go +++ b/backend/gogl/gogl.go @@ -33,6 +33,8 @@ type GoGLBackend struct { offscr1 offscreenBuffer offscr2 offscreenBuffer glChan chan func() + + ptsBuf []float32 } type offscreenBuffer struct { @@ -53,10 +55,11 @@ func New(x, y, w, h int) (canvas.Backend, error) { gl.GetError() // clear error state b := &GoGLBackend{ - w: w, - h: h, - fw: float64(w), - fh: float64(h), + w: w, + h: h, + fw: float64(w), + fh: float64(h), + ptsBuf: make([]float32, 0, 4096), } err = loadShader(solidVS, solidFS, &b.sr.shaderProgram) diff --git a/canvas.go b/canvas.go index f8cc405..cdfbb4b 100644 --- a/canvas.go +++ b/canvas.go @@ -493,10 +493,10 @@ func (s *drawStyle) isOpaque() bool { return s.color.A >= 255 } -func (cv *Canvas) backendStyle(s *drawStyle) backendbase.Style { +func (cv *Canvas) backendStyle(s *drawStyle, alpha float64) backendbase.Style { return backendbase.Style{ Color: s.color, - GlobalAlpha: cv.state.globalAlpha, + GlobalAlpha: cv.state.globalAlpha * alpha, } } diff --git a/paths.go b/paths.go index 547371a..a8813fd 100644 --- a/paths.go +++ b/paths.go @@ -648,8 +648,8 @@ func (cv *Canvas) FillRect(x, y, w, h float64) { data := [4][2]float64{{p0[0], p0[1]}, {p1[0], p1[1]}, {p2[0], p2[1]}, {p3[0], p3[1]}} - stl := cv.backendStyle(&cv.state.fill) - cv.b.Fill(&stl, data) + stl := cv.backendStyle(&cv.state.fill, 1) + cv.b.Fill(&stl, data[:]) } // ClearRect sets the color of the rectangle to transparent black