@@ -33,10 +33,12 @@ func (b *XMobileBackend) Clear(pts [4][2]float64) {
3333 float32 (pts [2 ][0 ]), float32 (pts [2 ][1 ]),
3434 float32 (pts [3 ][0 ]), float32 (pts [3 ][1 ])}
3535
36- b .glctx .UseProgram (b .sr .ID )
37- b .glctx .Uniform2f (b .sr .CanvasSize , float32 (b .fw ), float32 (b .fh ))
38- b .glctx .Uniform4f (b .sr .Color , 0 , 0 , 0 , 0 )
39- b .glctx .Uniform1f (b .sr .GlobalAlpha , 1 )
36+ b .glctx .UseProgram (b .shd .ID )
37+ b .glctx .Uniform2f (b .shd .CanvasSize , float32 (b .fw ), float32 (b .fh ))
38+ b .glctx .Uniform4f (b .shd .Color , 0 , 0 , 0 , 0 )
39+ b .glctx .Uniform1f (b .shd .GlobalAlpha , 1 )
40+ b .glctx .Uniform1i (b .shd .UseAlphaTex , 0 )
41+ b .glctx .Uniform1i (b .shd .Func , shdFuncSolid )
4042
4143 b .glctx .Disable (gl .BLEND )
4244
@@ -45,10 +47,10 @@ func (b *XMobileBackend) Clear(pts [4][2]float64) {
4547
4648 b .glctx .StencilFunc (gl .EQUAL , 0 , 0xFF )
4749
48- b .glctx .VertexAttribPointer (b .sr .Vertex , 2 , gl .FLOAT , false , 0 , 0 )
49- b .glctx .EnableVertexAttribArray (b .sr .Vertex )
50+ b .glctx .VertexAttribPointer (b .shd .Vertex , 2 , gl .FLOAT , false , 0 , 0 )
51+ b .glctx .EnableVertexAttribArray (b .shd .Vertex )
5052 b .glctx .DrawArrays (gl .TRIANGLE_FAN , 0 , 4 )
51- b .glctx .DisableVertexAttribArray (b .sr .Vertex )
53+ b .glctx .DisableVertexAttribArray (b .shd .Vertex )
5254
5355 b .glctx .StencilFunc (gl .ALWAYS , 0 , 0xFF )
5456
@@ -70,6 +72,8 @@ func (b *XMobileBackend) clearRect(x, y, w, h int) {
7072}
7173
7274func extent (pts [][2 ]float64 ) (min , max vec ) {
75+ max [0 ] = - math .MaxFloat64
76+ max [1 ] = - math .MaxFloat64
7377 min [0 ] = math .MaxFloat64
7478 min [1 ] = math .MaxFloat64
7579 for _ , v := range pts {
@@ -111,7 +115,7 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts [][2]float64, ca
111115 b .glctx .BufferData (gl .ARRAY_BUFFER , byteSlice (unsafe .Pointer (& b .ptsBuf [0 ]), len (b .ptsBuf )* 4 ), gl .STREAM_DRAW )
112116
113117 if ! canOverlap || style .Color .A >= 255 {
114- vertex := b .useShader (style )
118+ vertex , _ := b .useShader (style , false , 0 )
115119
116120 b .glctx .StencilFunc (gl .EQUAL , 0 , 0xFF )
117121 b .glctx .EnableVertexAttribArray (vertex )
@@ -125,21 +129,23 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts [][2]float64, ca
125129 b .glctx .StencilOp (gl .REPLACE , gl .REPLACE , gl .REPLACE )
126130 b .glctx .StencilMask (0x01 )
127131
128- b .glctx .UseProgram (b .sr .ID )
129- b .glctx .Uniform4f (b .sr .Color , 0 , 0 , 0 , 0 )
130- b .glctx .Uniform2f (b .sr .CanvasSize , float32 (b .fw ), float32 (b .fh ))
131- b .glctx .Uniform1f (b .sr .GlobalAlpha , 1 )
132+ b .glctx .UseProgram (b .shd .ID )
133+ b .glctx .Uniform4f (b .shd .Color , 0 , 0 , 0 , 0 )
134+ b .glctx .Uniform2f (b .shd .CanvasSize , float32 (b .fw ), float32 (b .fh ))
135+ b .glctx .Uniform1f (b .shd .GlobalAlpha , 1 )
136+ b .glctx .Uniform1i (b .shd .UseAlphaTex , 0 )
137+ b .glctx .Uniform1i (b .shd .Func , shdFuncSolid )
132138
133- b .glctx .EnableVertexAttribArray (b .sr .Vertex )
134- b .glctx .VertexAttribPointer (b .sr .Vertex , 2 , gl .FLOAT , false , 0 , 0 )
139+ b .glctx .EnableVertexAttribArray (b .shd .Vertex )
140+ b .glctx .VertexAttribPointer (b .shd .Vertex , 2 , gl .FLOAT , false , 0 , 0 )
135141 b .glctx .DrawArrays (mode , 4 , len (pts ))
136- b .glctx .DisableVertexAttribArray (b .sr .Vertex )
142+ b .glctx .DisableVertexAttribArray (b .shd .Vertex )
137143
138144 b .glctx .ColorMask (true , true , true , true )
139145
140146 b .glctx .StencilFunc (gl .EQUAL , 1 , 0xFF )
141147
142- vertex := b .useShader (style )
148+ vertex , _ := b .useShader (style , false , 0 )
143149 b .glctx .EnableVertexAttribArray (vertex )
144150 b .glctx .VertexAttribPointer (vertex , 2 , gl .FLOAT , false , 0 , 0 )
145151
@@ -154,7 +160,7 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts [][2]float64, ca
154160 }
155161
156162 if style .Blur > 0 {
157- b .drawBlurred (style .Blur )
163+ b .drawBlurred (style .Blur , min , max )
158164 }
159165}
160166
@@ -181,7 +187,7 @@ func (b *XMobileBackend) FillImageMask(style *backendbase.FillStyle, mask *image
181187
182188 b .glctx .BindBuffer (gl .ARRAY_BUFFER , b .buf )
183189
184- vertex , alphaTexCoord := b .useAlphaShader (style , 1 )
190+ vertex , alphaTexCoord := b .useShader (style , true , 1 )
185191
186192 b .glctx .EnableVertexAttribArray (vertex )
187193 b .glctx .EnableVertexAttribArray (alphaTexCoord )
@@ -216,105 +222,103 @@ func (b *XMobileBackend) FillImageMask(style *backendbase.FillStyle, mask *image
216222 b .glctx .ActiveTexture (gl .TEXTURE0 )
217223
218224 if style .Blur > 0 {
219- b .drawBlurred (style .Blur )
225+ min , max := extent (pts [:])
226+ b .drawBlurred (style .Blur , min , max )
220227 }
221228}
222229
223- func (b * XMobileBackend ) drawBlurred (blur float64 ) {
224- b .glctx .BlendFunc (gl .ONE , gl .ONE_MINUS_SRC_ALPHA )
230+ func (b * XMobileBackend ) drawBlurred (size float64 , min , max vec ) {
231+ b .offscr1 .alpha = true
232+ b .offscr2 .alpha = true
225233
226- var kernel []float32
227- var kernelBuf [255 ]float32
228- var gs * gaussianShader
229- if blur < 3 {
230- gs = & b .gauss15r
231- kernel = kernelBuf [:15 ]
232- } else if blur < 12 {
233- gs = & b .gauss63r
234- kernel = kernelBuf [:63 ]
235- } else {
236- gs = & b .gauss127r
237- kernel = kernelBuf [:127 ]
234+ // calculate box blur size
235+ fsize := math .Max (1 , math .Floor (size ))
236+ sizea := int (fsize )
237+ sizeb := sizea
238+ sizec := sizea
239+ if size - fsize > 0.333333333 {
240+ sizeb ++
241+ }
242+ if size - fsize > 0.666666666 {
243+ sizec ++
238244 }
239245
240- gaussianKernel ( blur , kernel )
241-
242- b . offscr2 . alpha = true
243- b . enableTextureRenderTarget ( & b . offscr2 )
244- b . glctx . ClearColor ( 0 , 0 , 0 , 0 )
245- b . glctx . Clear ( gl . COLOR_BUFFER_BIT | gl . STENCIL_BUFFER_BIT )
246-
247- b . glctx . StencilFunc ( gl . EQUAL , 0 , 0xFF )
246+ min [ 0 ] -= fsize * 3
247+ min [ 1 ] -= fsize * 3
248+ max [ 0 ] += fsize * 3
249+ max [ 1 ] += fsize * 3
250+ min [ 0 ] = math . Max ( 0. 0 , math . Min ( b . fw , min [ 0 ]) )
251+ min [ 1 ] = math . Max ( 0.0 , math . Min ( b . fh , min [ 1 ]) )
252+ max [ 0 ] = math . Max ( 0.0 , math . Min ( b . fw , max [ 0 ]))
253+ max [ 1 ] = math . Max ( 0.0 , math . Min ( b . fh , max [ 1 ]) )
248254
249255 b .glctx .BindBuffer (gl .ARRAY_BUFFER , b .shadowBuf )
250- data := [16 ]float32 {0 , 0 , 0 , float32 (b .h ), float32 (b .w ), float32 (b .h ), float32 (b .w ), 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 }
256+ data := [16 ]float32 {
257+ float32 (min [0 ]), float32 (min [1 ]),
258+ float32 (min [0 ]), float32 (max [1 ]),
259+ float32 (max [0 ]), float32 (max [1 ]),
260+ float32 (max [0 ]), float32 (min [1 ]),
261+ float32 (min [0 ] / b .fw ), 1 - float32 (min [1 ]/ b .fh ),
262+ float32 (min [0 ] / b .fw ), 1 - float32 (max [1 ]/ b .fh ),
263+ float32 (max [0 ] / b .fw ), 1 - float32 (max [1 ]/ b .fh ),
264+ float32 (max [0 ] / b .fw ), 1 - float32 (min [1 ]/ b .fh ),
265+ }
251266 b .glctx .BufferData (gl .ARRAY_BUFFER , byteSlice (unsafe .Pointer (& data [0 ]), len (data )* 4 ), gl .STREAM_DRAW )
252267
253- b .glctx .ActiveTexture (gl .TEXTURE0 )
254- b .glctx .BindTexture (gl .TEXTURE_2D , b .offscr1 .tex )
255-
256- b .glctx .UseProgram (gs .ID )
257- b .glctx .Uniform1i (gs .Image , 0 )
258- b .glctx .Uniform2f (gs .CanvasSize , float32 (b .fw ), float32 (b .fh ))
259- b .glctx .Uniform2f (gs .KernelScale , 1.0 / float32 (b .fw ), 0.0 )
260- b .glctx .Uniform1fv (gs .Kernel , kernel )
261- b .glctx .VertexAttribPointer (gs .Vertex , 2 , gl .FLOAT , false , 0 , 0 )
262- b .glctx .VertexAttribPointer (gs .TexCoord , 2 , gl .FLOAT , false , 0 , 8 * 4 )
263- b .glctx .EnableVertexAttribArray (gs .Vertex )
264- b .glctx .EnableVertexAttribArray (gs .TexCoord )
265- b .glctx .DrawArrays (gl .TRIANGLE_FAN , 0 , 4 )
266- b .glctx .DisableVertexAttribArray (gs .Vertex )
267- b .glctx .DisableVertexAttribArray (gs .TexCoord )
268+ b .glctx .UseProgram (b .shd .ID )
269+ b .glctx .Uniform1i (b .shd .Image , 0 )
270+ b .glctx .Uniform2f (b .shd .CanvasSize , float32 (b .fw ), float32 (b .fh ))
271+ b .glctx .Uniform1i (b .shd .UseAlphaTex , 0 )
272+ b .glctx .Uniform1i (b .shd .Func , shdFuncBoxBlur )
268273
269- b .glctx .StencilFunc (gl .ALWAYS , 0 , 0xFF )
274+ b .glctx .VertexAttribPointer (b .shd .Vertex , 2 , gl .FLOAT , false , 0 , 0 )
275+ b .glctx .VertexAttribPointer (b .shd .TexCoord , 2 , gl .FLOAT , false , 0 , 8 * 4 )
276+ b .glctx .EnableVertexAttribArray (b .shd .Vertex )
277+ b .glctx .EnableVertexAttribArray (b .shd .TexCoord )
270278
271- b .disableTextureRenderTarget ( )
279+ b .glctx . Disable ( gl . BLEND )
272280
273- b .glctx .StencilFunc (gl .EQUAL , 0 , 0xFF )
281+ b .glctx .ActiveTexture (gl .TEXTURE0 )
274282
275- b .glctx .BindBuffer (gl .ARRAY_BUFFER , b .shadowBuf )
276- data = [16 ]float32 {0 , 0 , 0 , float32 (b .h ), float32 (b .w ), float32 (b .h ), float32 (b .w ), 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 }
277- b .glctx .BufferData (gl .ARRAY_BUFFER , byteSlice (unsafe .Pointer (& data [0 ]), len (data )* 4 ), gl .STREAM_DRAW )
283+ b .glctx .ClearColor (0 , 0 , 0 , 0 )
278284
279- b .glctx .ActiveTexture (gl .TEXTURE0 )
285+ b .enableTextureRenderTarget (& b .offscr2 )
286+ b .glctx .BindTexture (gl .TEXTURE_2D , b .offscr1 .tex )
287+ b .glctx .Clear (gl .COLOR_BUFFER_BIT | gl .STENCIL_BUFFER_BIT )
288+ b .box3 (sizea , 0 , false )
289+ b .enableTextureRenderTarget (& b .offscr1 )
280290 b .glctx .BindTexture (gl .TEXTURE_2D , b .offscr2 .tex )
291+ b .box3 (sizeb , - 0.5 , false )
292+ b .enableTextureRenderTarget (& b .offscr2 )
293+ b .glctx .BindTexture (gl .TEXTURE_2D , b .offscr1 .tex )
294+ b .box3 (sizec , 0 , false )
295+ b .enableTextureRenderTarget (& b .offscr1 )
296+ b .glctx .BindTexture (gl .TEXTURE_2D , b .offscr2 .tex )
297+ b .box3 (sizea , 0 , true )
298+ b .enableTextureRenderTarget (& b .offscr2 )
299+ b .glctx .BindTexture (gl .TEXTURE_2D , b .offscr1 .tex )
300+ b .box3 (sizeb , - 0.5 , true )
301+ b .glctx .Enable (gl .BLEND )
302+ b .glctx .BlendFunc (gl .ONE , gl .ONE_MINUS_SRC_ALPHA )
303+ b .disableTextureRenderTarget ()
304+ b .glctx .BindTexture (gl .TEXTURE_2D , b .offscr2 .tex )
305+ b .box3 (sizec , 0 , true )
281306
282- b .glctx .UseProgram (gs .ID )
283- b .glctx .Uniform1i (gs .Image , 0 )
284- b .glctx .Uniform2f (gs .CanvasSize , float32 (b .fw ), float32 (b .fh ))
285- b .glctx .Uniform2f (gs .KernelScale , 0.0 , 1.0 / float32 (b .fh ))
286- b .glctx .Uniform1fv (gs .Kernel , kernel )
287- b .glctx .VertexAttribPointer (gs .Vertex , 2 , gl .FLOAT , false , 0 , 0 )
288- b .glctx .VertexAttribPointer (gs .TexCoord , 2 , gl .FLOAT , false , 0 , 8 * 4 )
289- b .glctx .EnableVertexAttribArray (gs .Vertex )
290- b .glctx .EnableVertexAttribArray (gs .TexCoord )
291- b .glctx .DrawArrays (gl .TRIANGLE_FAN , 0 , 4 )
292- b .glctx .DisableVertexAttribArray (gs .Vertex )
293- b .glctx .DisableVertexAttribArray (gs .TexCoord )
294-
295- b .glctx .StencilFunc (gl .ALWAYS , 0 , 0xFF )
307+ b .glctx .DisableVertexAttribArray (b .shd .Vertex )
308+ b .glctx .DisableVertexAttribArray (b .shd .TexCoord )
296309
297310 b .glctx .BlendFunc (gl .SRC_ALPHA , gl .ONE_MINUS_SRC_ALPHA )
298311}
299312
300- func gaussianKernel (stddev float64 , target []float32 ) {
301- stddevSqr := stddev * stddev
302- center := float64 (len (target ) / 2 )
303- factor := 1.0 / math .Sqrt (2 * math .Pi * stddevSqr )
304- for i := range target {
305- x := float64 (i ) - center
306- target [i ] = float32 (factor * math .Pow (math .E , - x * x / (2 * stddevSqr )))
307- }
308- // normalizeKernel(target)
309- }
310-
311- func normalizeKernel (kernel []float32 ) {
312- var sum float32
313- for _ , v := range kernel {
314- sum += v
315- }
316- factor := 1.0 / sum
317- for i := range kernel {
318- kernel [i ] *= factor
313+ func (b * XMobileBackend ) box3 (size int , offset float32 , vertical bool ) {
314+ b .glctx .Uniform1i (b .shd .BoxSize , size )
315+ if vertical {
316+ b .glctx .Uniform1i (b .shd .BoxVertical , 1 )
317+ b .glctx .Uniform1f (b .shd .BoxScale , 1 / float32 (b .fh ))
318+ } else {
319+ b .glctx .Uniform1i (b .shd .BoxVertical , 0 )
320+ b .glctx .Uniform1f (b .shd .BoxScale , 1 / float32 (b .fw ))
319321 }
322+ b .glctx .Uniform1f (b .shd .BoxOffset , offset )
323+ b .glctx .DrawArrays (gl .TRIANGLE_FAN , 0 , 4 )
320324}
0 commit comments