@@ -37,6 +37,9 @@ struct gl_blur_context {
3737 /// How much do we need to resize the damaged region for blurring.
3838 int resize_width , resize_height ;
3939
40+ int noise_radius ;
41+ float noise_scale ;
42+
4043 int npasses ;
4144
4245 enum backend_image_format format ;
@@ -82,12 +85,8 @@ gl_kernel_blur(double opacity, struct gl_blur_context *bctx,
8285 glBindTexture (GL_TEXTURE_2D , src_texture );
8386 glBindSampler (0 , blur_sampler );
8487 glUseProgram (p -> prog );
85- if (p -> uniform_bitmask & (1 << UNIFORM_PIXEL_NORM_LOC )) {
86- // If the last pass is a trivial blend pass, it will not have
87- // pixel_norm.
88- glUniform2f (UNIFORM_PIXEL_NORM_LOC , 1.0F / (GLfloat )tex_width ,
89- 1.0F / (GLfloat )tex_height );
90- }
88+ glUniform2f (UNIFORM_PIXEL_NORM_LOC , 1.0F / (GLfloat )tex_width ,
89+ 1.0F / (GLfloat )tex_height );
9190
9291 glActiveTexture (GL_TEXTURE1 );
9392 glBindTexture (GL_TEXTURE_2D , default_mask );
@@ -118,6 +117,8 @@ gl_kernel_blur(double opacity, struct gl_blur_context *bctx,
118117 }
119118
120119 glUniform1f (UNIFORM_OPACITY_LOC , 1.0F );
120+ glUniform1i (UNIFORM_BLUR_NOISE_RADIUS_LOC , 0 );
121+ glUniform1f (UNIFORM_BLUR_NOISE_SCALE_LOC , 0.0F );
121122 } else {
122123 // last pass, draw directly into the back buffer, with origin
123124 // regions. And apply mask if requested
@@ -139,6 +140,8 @@ gl_kernel_blur(double opacity, struct gl_blur_context *bctx,
139140 glBindFramebuffer (GL_FRAMEBUFFER , target_fbo );
140141
141142 glUniform1f (UNIFORM_OPACITY_LOC , (float )opacity );
143+ glUniform1i (UNIFORM_BLUR_NOISE_RADIUS_LOC , bctx -> noise_radius );
144+ glUniform1f (UNIFORM_BLUR_NOISE_SCALE_LOC , bctx -> noise_scale );
142145 glBlendFunc (GL_ONE , GL_ONE_MINUS_SRC_ALPHA );
143146 }
144147
@@ -224,6 +227,8 @@ bool gl_dual_kawase_blur(double opacity, struct gl_blur_context *bctx,
224227 glUniform1f (UNIFORM_MASK_CORNER_RADIUS_LOC , 0.0F );
225228 glUniform2f (UNIFORM_MASK_SCALE_LOC , 1.0F , 1.0F );
226229 glUniform1f (UNIFORM_OPACITY_LOC , 1.0F );
230+ glUniform1i (UNIFORM_BLUR_NOISE_RADIUS_LOC , 0 );
231+ glUniform1f (UNIFORM_BLUR_NOISE_SCALE_LOC , 0.0F );
227232
228233 for (int i = iterations - 1 ; i >= 0 ; -- i ) {
229234 // Scale output width / height back by two in each iteration
@@ -267,6 +272,8 @@ bool gl_dual_kawase_blur(double opacity, struct gl_blur_context *bctx,
267272 glBindFramebuffer (GL_DRAW_FRAMEBUFFER , target_fbo );
268273
269274 glUniform1f (UNIFORM_OPACITY_LOC , (GLfloat )opacity );
275+ glUniform1i (UNIFORM_BLUR_NOISE_RADIUS_LOC , bctx -> noise_radius );
276+ glUniform1f (UNIFORM_BLUR_NOISE_SCALE_LOC , bctx -> noise_scale );
270277 glBlendFunc (GL_ONE , GL_ONE_MINUS_SRC_ALPHA );
271278 }
272279
@@ -534,18 +541,22 @@ bool gl_create_kernel_blur_context(void *blur_context, GLfloat *projection,
534541
535542 // clang-format off
536543 static const char * FRAG_SHADER_BLUR = GLSL (330 ,
537- %s \n // other extension pragmas
538544 layout (location = UNIFORM_TEX_SRC_LOC )
539545 uniform sampler2D tex_src ;
540546 layout (location = UNIFORM_PIXEL_NORM_LOC )
541547 uniform vec2 pixel_norm ;
542548 layout (location = UNIFORM_OPACITY_LOC )
543549 uniform float opacity ;
550+ layout (location = UNIFORM_BLUR_NOISE_RADIUS_LOC )
551+ uniform int noise_radius ;
552+ layout (location = UNIFORM_BLUR_NOISE_SCALE_LOC )
553+ uniform float noise_scale ;
544554 in vec2 texcoord ;
545555 out vec4 out_color ;
546556 float mask_factor ();
557+ vec2 perturb (vec2 , float , float );
547558 void main () {
548- vec2 uv = texcoord * pixel_norm ;
559+ vec2 uv = perturb ( texcoord , noise_radius , noise_scale ) * pixel_norm ;
549560 vec4 sum = vec4 (0.0 , 0.0 , 0.0 , 0.0 );
550561 %s //body of the convolution
551562 out_color = sum / float (%.7 g ) * opacity * mask_factor ();
@@ -557,7 +568,6 @@ bool gl_create_kernel_blur_context(void *blur_context, GLfloat *projection,
557568 // clang-format on
558569
559570 const char * shader_add = FRAG_SHADER_BLUR_ADD ;
560- char * extension = strdup ("" );
561571
562572 for (int i = 0 ; i < nkernels ; i ++ ) {
563573 auto kern = kernels [i ];
@@ -628,27 +638,25 @@ bool gl_create_kernel_blur_context(void *blur_context, GLfloat *projection,
628638 }
629639
630640 auto pass = ctx -> blur_shader + i ;
631- size_t shader_len = strlen (FRAG_SHADER_BLUR ) + strlen (extension ) +
632- strlen (shader_body ) + 10 /* sum */ +
633- 1 /* null terminator */ ;
641+ size_t shader_len = strlen (FRAG_SHADER_BLUR ) + strlen (shader_body ) +
642+ 10 /* sum */ + 1 /* null terminator */ ;
634643 char * shader_str = ccalloc (shader_len , char );
635- auto real_shader_len = snprintf ( shader_str , shader_len , FRAG_SHADER_BLUR ,
636- extension , shader_body , sum );
644+ auto real_shader_len =
645+ snprintf ( shader_str , shader_len , FRAG_SHADER_BLUR , shader_body , sum );
637646 CHECK (real_shader_len >= 0 );
638647 CHECK ((size_t )real_shader_len < shader_len );
639648 free (shader_body );
640649
641650 // Build program
642651 pass -> prog = gl_create_program_from_strv (
643652 (const char * []){vertex_shader , NULL },
644- (const char * []){shader_str , scaled_masking_glsl , NULL });
653+ (const char * []){shader_str , scaled_masking_glsl , perturb_glsl , NULL });
645654 free (shader_str );
646655 if (!pass -> prog ) {
647656 log_error ("Failed to create GLSL program." );
648657 success = false;
649658 goto out ;
650659 }
651- pass -> uniform_bitmask = 1 << UNIFORM_PIXEL_NORM_LOC ;
652660 glBindFragDataLocation (pass -> prog , 0 , "out_color" );
653661
654662 // Setup projection matrix
@@ -666,7 +674,8 @@ bool gl_create_kernel_blur_context(void *blur_context, GLfloat *projection,
666674 auto pass = & ctx -> blur_shader [1 ];
667675 pass -> prog = gl_create_program_from_strv (
668676 (const char * []){vertex_shader , NULL },
669- (const char * []){blend_with_mask_frag , scaled_masking_glsl , NULL });
677+ (const char * []){blend_with_mask_frag , scaled_masking_glsl ,
678+ perturb_glsl , NULL });
670679
671680 // Setup projection matrix
672681 glUseProgram (pass -> prog );
@@ -688,7 +697,6 @@ bool gl_create_kernel_blur_context(void *blur_context, GLfloat *projection,
688697 free (kernels );
689698 }
690699
691- free (extension );
692700 // Restore LC_NUMERIC
693701 setlocale (LC_NUMERIC , lc_numeric_old );
694702 free (lc_numeric_old );
@@ -784,12 +792,17 @@ bool gl_create_dual_kawase_blur_context(void *blur_context, GLfloat *projection,
784792 uniform vec2 pixel_norm ;
785793 layout (location = UNIFORM_OPACITY_LOC )
786794 uniform float opacity ;
795+ layout (location = UNIFORM_BLUR_NOISE_RADIUS_LOC )
796+ uniform int noise_radius ;
797+ layout (location = UNIFORM_BLUR_NOISE_SCALE_LOC )
798+ uniform float noise_scale ;
787799 in vec2 texcoord ;
788800 out vec4 out_color ;
789801 float mask_factor ();
802+ vec2 perturb (vec2 , float , float );
790803 void main () {
791804 vec2 offset = %.7 g * pixel_norm ;
792- vec2 uv = texcoord * pixel_norm / (2 * scale );
805+ vec2 uv = perturb ( texcoord , noise_radius , noise_scale ) * pixel_norm / (2 * scale );
793806 vec4 sum = texture2D (tex_src , uv + vec2 (-1.0 , 0.0 ) * offset );
794807 sum += texture2D (tex_src , uv + vec2 (-0.5 , 0.5 ) * offset ) * 2.0 ;
795808 sum += texture2D (tex_src , uv + vec2 (0.0 , 1.0 ) * offset );
@@ -815,7 +828,7 @@ bool gl_create_dual_kawase_blur_context(void *blur_context, GLfloat *projection,
815828 // Build program
816829 up_pass -> prog = gl_create_program_from_strv (
817830 (const char * []){vertex_shader , NULL },
818- (const char * []){shader_str , scaled_masking_glsl , NULL });
831+ (const char * []){shader_str , scaled_masking_glsl , perturb_glsl , NULL });
819832 free (shader_str );
820833 if (!up_pass -> prog ) {
821834 log_error ("Failed to create GLSL program." );
@@ -834,10 +847,6 @@ bool gl_create_dual_kawase_blur_context(void *blur_context, GLfloat *projection,
834847out :
835848 free (blur_params );
836849
837- if (!success ) {
838- ctx = NULL ;
839- }
840-
841850 // Restore LC_NUMERIC
842851 setlocale (LC_NUMERIC , lc_numeric_old );
843852 free (lc_numeric_old );
@@ -846,7 +855,7 @@ bool gl_create_dual_kawase_blur_context(void *blur_context, GLfloat *projection,
846855}
847856
848857void * gl_create_blur_context (backend_t * base , enum blur_method method ,
849- enum backend_image_format format , void * args ) {
858+ enum backend_image_format format , struct blur_args * args ) {
850859 bool success ;
851860 auto gd = (struct gl_data * )base ;
852861
@@ -878,6 +887,12 @@ void *gl_create_blur_context(backend_t *base, enum blur_method method,
878887 goto out ;
879888 }
880889
890+ ctx -> noise_radius = args -> noise_radius ;
891+ ctx -> noise_scale = (float )args -> noise_scale ;
892+ // Expand the blur region to account for noise samples
893+ ctx -> resize_width = max2 (ctx -> resize_width , ctx -> noise_radius );
894+ ctx -> resize_height = max2 (ctx -> resize_height , ctx -> noise_radius );
895+
881896 // Texture size will be defined by gl_blur
882897 ctx -> blur_textures = ccalloc (ctx -> blur_texture_count , GLuint );
883898 ctx -> texture_sizes = ccalloc (ctx -> blur_texture_count , struct texture_size );
0 commit comments