1. Hey! Guest! The 34th GMC Jam will take place between August 22nd, 12:00 UTC (Thursday noon) and August 26th, 12:00 UTC (Monday noon). Why not join in! Click here to find out more!
    Dismiss Notice

Performace issue with blur shader

Discussion in 'Programming' started by streng, Aug 8, 2019.

  1. streng

    streng Member

    Joined:
    Jun 10, 2019
    Posts:
    12
    Hi I’m facing a huge performance drop when I use blur shader on the layer.

    If using shader only for text in standard draw event, then working fine, but when I using it on layer respectively 9 different layers a massive slowdown occur. The frame drop is from 60 to 10 FPS. Real FPS don’t drop it runs around 4000 – meaning that a shader is the issue, because real FPS counting only CPU steps.

    Here is my code:

    Shader vertex:
    Code:
    attribute vec3 in_Position;                  // (x,y,z)
    //attribute vec3 in_Normal;                  // (x,y,z)     unused in this shader.   
    attribute vec4 in_Colour;                    // (r,g,b,a)
    attribute vec2 in_TextureCoord;              // (u,v)
    
    varying vec2 v_vTexcoord;
    varying vec4 v_vColour;
    
    void main()
    {
        vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
        gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
        
        v_vColour = in_Colour;
        v_vTexcoord = in_TextureCoord;
    }
    
    Shader fragment:
    Code:
    varying vec2 v_vTexcoord;
    varying vec4 v_vColour;
    uniform vec3 size;//width,height,radius
    
    const int Quality = 8;
    const int Directions = 16;
    const float Pi = 6.28318530718;//pi * 2
    
    void main()
    {
        vec2 radius = size.z/size.xy;
        vec4 Color = texture2D( gm_BaseTexture, v_vTexcoord);
        for( float d=0.0;d<Pi;d+=Pi/float(Directions) )
        {
            for( float i=1.0/float(Quality);i<=1.0;i+=1.0/float(Quality) )
            {
                    Color += texture2D( gm_BaseTexture, v_vTexcoord+vec2(cos(d),sin(d))*radius*i);
            }
        }
        Color /= float(Quality)*float(Directions)+1.0;
        gl_FragColor =  Color *  v_vColour;
    }
    Then in my control object using shader activation on layer like this:
    Code:
    //initialise pause blur shader
    layer_script_begin("Backgrounds", scr_BlurPause_Start);
    layer_script_end("Backgrounds", scr_Blur_End);
    layer_script_begin("Backgrounds_1", scr_BlurPause_Start);
    layer_script_end("Backgrounds_1", scr_Blur_End);
    layer_script_begin("Backgrounds_2", scr_BlurPause_Start);
    layer_script_end("Backgrounds_2", scr_Blur_End);
    layer_script_begin("Backgrounds_3", scr_BlurPause_Start);
    layer_script_end("Backgrounds_3", scr_Blur_End);
    layer_script_begin("Backgrounds_4", scr_BlurPause_Start);
    layer_script_end("Backgrounds_4", scr_Blur_End);
    layer_script_begin("Backgrounds_5", scr_BlurPause_Start);
    layer_script_end("Backgrounds_5", scr_Blur_End);
    layer_script_begin("Backgrounds_6", scr_BlurPause_Start);
    layer_script_end("Backgrounds_6", scr_Blur_End);
    layer_script_begin("Backgrounds_7", scr_BlurPause_Start);
    layer_script_end("Backgrounds_7", scr_Blur_End);
    layer_script_begin("Instances", scr_BlurPause_Start);
    layer_script_end("Instances", scr_Blur_End);
    And the scripts which handle shader activation/deactivation
    scr_BlurPause_Start
    Code:
    if event_type == ev_draw
       {
    
            if instance_exists(obj_controller_pause)
                {
                    if (obj_controller_pause.pause == true)
                        {
        
                            usize = shader_get_uniform(shd_gausian,"size");//uniform for width, height, radius
                            shader_set(shd_gausian)
                            shader_set_uniform_f(usize,1920,1080,1.75)//width,height,radius
                        }
                }   
            else if instance_exists(o_control)
                {   
                    
                    if (o_control.victory != -1)
                
                        {
                            usize = shader_get_uniform(shd_gausian,"size");//uniform for width, height, radius
                            shader_set(shd_gausian)
                            shader_set_uniform_f(usize,1920,1080,stage_finish.backround_alpha*4)//width,height,radius
                        
                        }   
                }
        }
    scr_Blur_End
    Code:
    if event_type == ev_draw
       {
    shader_reset()
    }
    Is there any way how to optimize it?
    Is it a bad way to use shader on such many layers?


    I just want to achieve, if player pause button, i want to blur all objects and backgrounds except the pause object, which work but at the cost of performance, so is there any other way how to do it better?


    Thank you for your answers
     
  2. flyingsaucerinvasion

    flyingsaucerinvasion Member

    Joined:
    Jun 20, 2016
    Posts:
    2,088
    You're doing 129 texture samples, and 256 trig functions per fragment. There are two main things you can do to improve this situation. 1) Draw to a downscaled surface to reduce the number of fragments that run this shader. 2) Consider breaking up the blur into two phases, horizontal, and vertical. With the same level of quality you can thus reduce the number of samples from 129 per fragment to something more like 34.
     
  3. The Reverend

    The Reverend Member

    Joined:
    Sep 8, 2016
    Posts:
    548
    Do you really absolutely need to draw each background blurred or could you draw all backgrounds onto a surface and then draw that blurred? That could also be a performance boost.
    But the main two general improvements on blur performance are what flyingsaucerinvasion already mentioned.

    If you want to learn more about blurring with shaders I made a video tutorial series on shaders and video 15a to 15e are about getting from a horribly slow to a very performant blur shader. But still if you draw every background separately by the blur shader you'll still have performance issues - especially on odler machines or mobiles:
    https://www.youtube.com/playlist?list=PL0kTSdIvQNCNE-BDKOlYu628AalMmXy_P
     
  4. streng

    streng Member

    Joined:
    Jun 10, 2019
    Posts:
    12
    The reason, why I’m trying to draw blur shader on 9 different layers is that, many of the layers are background tiled layer which are responsible for parallax effect. If I draw these sprites not on the background layer, but in the standard draw event with correct order, I will be facing issues with tiling, but it can be probably fixed in code.

    I also tried draw background as surface but without success. Maybe I just don’t know how to properly using surface. Can you point me to right direction using surfaces on background?

    Also, thanks for attached link, I will watch the video.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice