vary the gaussian shader kernel size depending on the blur radius for better performance

This commit is contained in:
Thomas Friedel 2018-07-27 15:58:38 +02:00
parent f2225e857a
commit afad74f7b2
2 changed files with 57 additions and 31 deletions

View file

@ -191,9 +191,9 @@ var (
lgar *linearGradientAlphaShader lgar *linearGradientAlphaShader
ipar *imagePatternAlphaShader ipar *imagePatternAlphaShader
ir *imageShader ir *imageShader
gauss15r *gaussian15Shader gauss15r *gaussianShader
gauss63r *gaussian63Shader gauss63r *gaussianShader
gauss255r *gaussian255Shader gauss255r *gaussianShader
offscr1 offscreenBuffer offscr1 offscreenBuffer
offscr2 offscreenBuffer offscr2 offscreenBuffer
glChan = make(chan func()) glChan = make(chan func())
@ -207,6 +207,16 @@ type offscreenBuffer struct {
frameBuf uint32 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 // 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 // that canvas needs. The parameter is an implementation of the GL interface
// in this package that should make this package neutral to GL implementations. // in this package that should make this package neutral to GL implementations.
@ -297,7 +307,7 @@ func LoadGL(glimpl GL) (err error) {
return return
} }
gauss15r, err = loadGaussian15Shader() gauss15s, err := loadGaussian15Shader()
if err != nil { if err != nil {
return return
} }
@ -305,8 +315,9 @@ func LoadGL(glimpl GL) (err error) {
if err != nil { if err != nil {
return return
} }
gauss15r = (*gaussianShader)(gauss15s)
gauss63r, err = loadGaussian63Shader() gauss63s, err := loadGaussian63Shader()
if err != nil { if err != nil {
return return
} }
@ -314,8 +325,9 @@ func LoadGL(glimpl GL) (err error) {
if err != nil { if err != nil {
return return
} }
gauss63r = (*gaussianShader)(gauss63s)
gauss255r, err = loadGaussian255Shader() gauss255s, err := loadGaussian255Shader()
if err != nil { if err != nil {
return return
} }
@ -323,6 +335,7 @@ func LoadGL(glimpl GL) (err error) {
if err != nil { if err != nil {
return return
} }
gauss255r = (*gaussianShader)(gauss255s)
gli.GenBuffers(1, &buf) gli.GenBuffers(1, &buf)
err = glError() err = glError()

View file

@ -118,8 +118,21 @@ func (cv *Canvas) drawTextShadow(offset image.Point, strWidth, strHeight int, x,
func (cv *Canvas) drawBlurredShadow() { func (cv *Canvas) drawBlurredShadow() {
gli.BlendFunc(gl_ONE, gl_ONE_MINUS_SRC_ALPHA) gli.BlendFunc(gl_ONE, gl_ONE_MINUS_SRC_ALPHA)
var kernel [255]float32 var kernel []float32
gaussianKernel(cv.state.shadowBlur, kernel[:]) 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) cv.enableTextureRenderTarget(&offscr2)
gli.ClearColor(0, 0, 0, 0) gli.ClearColor(0, 0, 0, 0)
@ -134,18 +147,18 @@ func (cv *Canvas) drawBlurredShadow() {
gli.ActiveTexture(gl_TEXTURE0) gli.ActiveTexture(gl_TEXTURE0)
gli.BindTexture(gl_TEXTURE_2D, offscr1.tex) gli.BindTexture(gl_TEXTURE_2D, offscr1.tex)
gli.UseProgram(gauss255r.id) gli.UseProgram(gs.id)
gli.Uniform1i(gauss255r.image, 0) gli.Uniform1i(gs.image, 0)
gli.Uniform2f(gauss255r.canvasSize, float32(cv.fw), float32(cv.fh)) gli.Uniform2f(gs.canvasSize, float32(cv.fw), float32(cv.fh))
gli.Uniform2f(gauss255r.kernelScale, 1.0/float32(cv.fw), 0.0) gli.Uniform2f(gs.kernelScale, 1.0/float32(cv.fw), 0.0)
gli.Uniform1fv(gauss255r.kernel, int32(len(kernel)), &kernel[0]) gli.Uniform1fv(gs.kernel, int32(len(kernel)), &kernel[0])
gli.VertexAttribPointer(gauss255r.vertex, 2, gl_FLOAT, false, 0, 0) gli.VertexAttribPointer(gs.vertex, 2, gl_FLOAT, false, 0, 0)
gli.VertexAttribPointer(gauss255r.texCoord, 2, gl_FLOAT, false, 0, 8*4) gli.VertexAttribPointer(gs.texCoord, 2, gl_FLOAT, false, 0, 8*4)
gli.EnableVertexAttribArray(gauss255r.vertex) gli.EnableVertexAttribArray(gs.vertex)
gli.EnableVertexAttribArray(gauss255r.texCoord) gli.EnableVertexAttribArray(gs.texCoord)
gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4) gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4)
gli.DisableVertexAttribArray(gauss255r.vertex) gli.DisableVertexAttribArray(gs.vertex)
gli.DisableVertexAttribArray(gauss255r.texCoord) gli.DisableVertexAttribArray(gs.texCoord)
gli.StencilFunc(gl_ALWAYS, 0, 0xFF) gli.StencilFunc(gl_ALWAYS, 0, 0xFF)
@ -160,18 +173,18 @@ func (cv *Canvas) drawBlurredShadow() {
gli.ActiveTexture(gl_TEXTURE0) gli.ActiveTexture(gl_TEXTURE0)
gli.BindTexture(gl_TEXTURE_2D, offscr2.tex) gli.BindTexture(gl_TEXTURE_2D, offscr2.tex)
gli.UseProgram(gauss255r.id) gli.UseProgram(gs.id)
gli.Uniform1i(gauss255r.image, 0) gli.Uniform1i(gs.image, 0)
gli.Uniform2f(gauss255r.canvasSize, float32(cv.fw), float32(cv.fh)) gli.Uniform2f(gs.canvasSize, float32(cv.fw), float32(cv.fh))
gli.Uniform2f(gauss255r.kernelScale, 0.0, 1.0/float32(cv.fh)) gli.Uniform2f(gs.kernelScale, 0.0, 1.0/float32(cv.fh))
gli.Uniform1fv(gauss255r.kernel, int32(len(kernel)), &kernel[0]) gli.Uniform1fv(gs.kernel, int32(len(kernel)), &kernel[0])
gli.VertexAttribPointer(gauss255r.vertex, 2, gl_FLOAT, false, 0, 0) gli.VertexAttribPointer(gs.vertex, 2, gl_FLOAT, false, 0, 0)
gli.VertexAttribPointer(gauss255r.texCoord, 2, gl_FLOAT, false, 0, 8*4) gli.VertexAttribPointer(gs.texCoord, 2, gl_FLOAT, false, 0, 8*4)
gli.EnableVertexAttribArray(gauss255r.vertex) gli.EnableVertexAttribArray(gs.vertex)
gli.EnableVertexAttribArray(gauss255r.texCoord) gli.EnableVertexAttribArray(gs.texCoord)
gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4) gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4)
gli.DisableVertexAttribArray(gauss255r.vertex) gli.DisableVertexAttribArray(gs.vertex)
gli.DisableVertexAttribArray(gauss255r.texCoord) gli.DisableVertexAttribArray(gs.texCoord)
gli.StencilFunc(gl_ALWAYS, 0, 0xFF) gli.StencilFunc(gl_ALWAYS, 0, 0xFF)
@ -186,7 +199,7 @@ func gaussianKernel(stddev float64, target []float32) {
x := float64(i) - center x := float64(i) - center
target[i] = float32(factor * math.Pow(math.E, -x*x/(2*stddevSqr))) target[i] = float32(factor * math.Pow(math.E, -x*x/(2*stddevSqr)))
} }
normalizeKernel(target) // normalizeKernel(target)
} }
func normalizeKernel(kernel []float32) { func normalizeKernel(kernel []float32) {