From afad74f7b20446b1e92e09c26d0b878f694f4289 Mon Sep 17 00:00:00 2001 From: Thomas Friedel Date: Fri, 27 Jul 2018 15:58:38 +0200 Subject: [PATCH] vary the gaussian shader kernel size depending on the blur radius for better performance --- canvas.go | 25 ++++++++++++++++------ shadows.go | 63 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 57 insertions(+), 31 deletions(-) diff --git a/canvas.go b/canvas.go index 31ca2f7..7885450 100644 --- a/canvas.go +++ b/canvas.go @@ -191,9 +191,9 @@ var ( lgar *linearGradientAlphaShader ipar *imagePatternAlphaShader ir *imageShader - gauss15r *gaussian15Shader - gauss63r *gaussian63Shader - gauss255r *gaussian255Shader + gauss15r *gaussianShader + gauss63r *gaussianShader + gauss255r *gaussianShader offscr1 offscreenBuffer offscr2 offscreenBuffer glChan = make(chan func()) @@ -207,6 +207,16 @@ type offscreenBuffer struct { frameBuf uint32 } +type gaussianShader struct { + id uint32 + vertex uint32 + texCoord uint32 + canvasSize int32 + kernelScale int32 + image int32 + kernel int32 +} + // LoadGL needs to be called once per GL context to load the GL assets // that canvas needs. The parameter is an implementation of the GL interface // in this package that should make this package neutral to GL implementations. @@ -297,7 +307,7 @@ func LoadGL(glimpl GL) (err error) { return } - gauss15r, err = loadGaussian15Shader() + gauss15s, err := loadGaussian15Shader() if err != nil { return } @@ -305,8 +315,9 @@ func LoadGL(glimpl GL) (err error) { if err != nil { return } + gauss15r = (*gaussianShader)(gauss15s) - gauss63r, err = loadGaussian63Shader() + gauss63s, err := loadGaussian63Shader() if err != nil { return } @@ -314,8 +325,9 @@ func LoadGL(glimpl GL) (err error) { if err != nil { return } + gauss63r = (*gaussianShader)(gauss63s) - gauss255r, err = loadGaussian255Shader() + gauss255s, err := loadGaussian255Shader() if err != nil { return } @@ -323,6 +335,7 @@ func LoadGL(glimpl GL) (err error) { if err != nil { return } + gauss255r = (*gaussianShader)(gauss255s) gli.GenBuffers(1, &buf) err = glError() diff --git a/shadows.go b/shadows.go index a79f7bf..e19511f 100644 --- a/shadows.go +++ b/shadows.go @@ -118,8 +118,21 @@ func (cv *Canvas) drawTextShadow(offset image.Point, strWidth, strHeight int, x, func (cv *Canvas) drawBlurredShadow() { gli.BlendFunc(gl_ONE, gl_ONE_MINUS_SRC_ALPHA) - var kernel [255]float32 - gaussianKernel(cv.state.shadowBlur, kernel[:]) + var kernel []float32 + var kernelBuf [255]float32 + var gs *gaussianShader + if cv.state.shadowBlur < 3 { + gs = gauss15r + kernel = kernelBuf[:15] + } else if cv.state.shadowBlur < 12 { + gs = gauss63r + kernel = kernelBuf[:63] + } else { + gs = gauss255r + kernel = kernelBuf[:255] + } + + gaussianKernel(cv.state.shadowBlur, kernel) cv.enableTextureRenderTarget(&offscr2) gli.ClearColor(0, 0, 0, 0) @@ -134,18 +147,18 @@ func (cv *Canvas) drawBlurredShadow() { gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_2D, offscr1.tex) - gli.UseProgram(gauss255r.id) - gli.Uniform1i(gauss255r.image, 0) - gli.Uniform2f(gauss255r.canvasSize, float32(cv.fw), float32(cv.fh)) - gli.Uniform2f(gauss255r.kernelScale, 1.0/float32(cv.fw), 0.0) - gli.Uniform1fv(gauss255r.kernel, int32(len(kernel)), &kernel[0]) - gli.VertexAttribPointer(gauss255r.vertex, 2, gl_FLOAT, false, 0, 0) - gli.VertexAttribPointer(gauss255r.texCoord, 2, gl_FLOAT, false, 0, 8*4) - gli.EnableVertexAttribArray(gauss255r.vertex) - gli.EnableVertexAttribArray(gauss255r.texCoord) + gli.UseProgram(gs.id) + gli.Uniform1i(gs.image, 0) + gli.Uniform2f(gs.canvasSize, float32(cv.fw), float32(cv.fh)) + gli.Uniform2f(gs.kernelScale, 1.0/float32(cv.fw), 0.0) + gli.Uniform1fv(gs.kernel, int32(len(kernel)), &kernel[0]) + gli.VertexAttribPointer(gs.vertex, 2, gl_FLOAT, false, 0, 0) + gli.VertexAttribPointer(gs.texCoord, 2, gl_FLOAT, false, 0, 8*4) + gli.EnableVertexAttribArray(gs.vertex) + gli.EnableVertexAttribArray(gs.texCoord) gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4) - gli.DisableVertexAttribArray(gauss255r.vertex) - gli.DisableVertexAttribArray(gauss255r.texCoord) + gli.DisableVertexAttribArray(gs.vertex) + gli.DisableVertexAttribArray(gs.texCoord) gli.StencilFunc(gl_ALWAYS, 0, 0xFF) @@ -160,18 +173,18 @@ func (cv *Canvas) drawBlurredShadow() { gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_2D, offscr2.tex) - gli.UseProgram(gauss255r.id) - gli.Uniform1i(gauss255r.image, 0) - gli.Uniform2f(gauss255r.canvasSize, float32(cv.fw), float32(cv.fh)) - gli.Uniform2f(gauss255r.kernelScale, 0.0, 1.0/float32(cv.fh)) - gli.Uniform1fv(gauss255r.kernel, int32(len(kernel)), &kernel[0]) - gli.VertexAttribPointer(gauss255r.vertex, 2, gl_FLOAT, false, 0, 0) - gli.VertexAttribPointer(gauss255r.texCoord, 2, gl_FLOAT, false, 0, 8*4) - gli.EnableVertexAttribArray(gauss255r.vertex) - gli.EnableVertexAttribArray(gauss255r.texCoord) + gli.UseProgram(gs.id) + gli.Uniform1i(gs.image, 0) + gli.Uniform2f(gs.canvasSize, float32(cv.fw), float32(cv.fh)) + gli.Uniform2f(gs.kernelScale, 0.0, 1.0/float32(cv.fh)) + gli.Uniform1fv(gs.kernel, int32(len(kernel)), &kernel[0]) + gli.VertexAttribPointer(gs.vertex, 2, gl_FLOAT, false, 0, 0) + gli.VertexAttribPointer(gs.texCoord, 2, gl_FLOAT, false, 0, 8*4) + gli.EnableVertexAttribArray(gs.vertex) + gli.EnableVertexAttribArray(gs.texCoord) gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4) - gli.DisableVertexAttribArray(gauss255r.vertex) - gli.DisableVertexAttribArray(gauss255r.texCoord) + gli.DisableVertexAttribArray(gs.vertex) + gli.DisableVertexAttribArray(gs.texCoord) gli.StencilFunc(gl_ALWAYS, 0, 0xFF) @@ -186,7 +199,7 @@ func gaussianKernel(stddev float64, target []float32) { x := float64(i) - center target[i] = float32(factor * math.Pow(math.E, -x*x/(2*stddevSqr))) } - normalizeKernel(target) + // normalizeKernel(target) } func normalizeKernel(kernel []float32) {