Search Unity

Question Shader I created causes very low fps on Android

Discussion in 'Shaders' started by said123sawn, Nov 15, 2022.

  1. said123sawn

    said123sawn

    Joined:
    Oct 31, 2019
    Posts:
    26
    After much effort, I created a shader and my game gives about 200 fps on the computer with the shader. However, it gives 10 fps on a powerful Android device and the device starts to heat up immediately.

    1.Is this a normal thing and is there a common solution for this?
    2.How much are the shaders updated every second? Maybe if I reduce the update frequency it will work (If there is such a thing)
     
  2. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,411
    What does the shader do?
    App works fine without that shader?

    Check with profiler from device if it shows other things that are slow too?
    https://docs.unity3d.com/Manual/profiler-profiling-applications.html

    Check device log if theres error spam/warnings
    https://answers.unity.com/questions/492681/how-to-use-adb-logcat.html#answer-571021

    You can set framerate
    https://forum.unity.com/threads/set-the-target-frame-rate-to-60-on-android.720584/

    Lowering resolution helps also
    https://docs.unity3d.com/ScriptReference/Screen.SetResolution.html
     
  3. said123sawn

    said123sawn

    Joined:
    Oct 31, 2019
    Posts:
    26
    Thank you for your interest.

    The app runs fine without this shader(these shaders only applies to UI objects). Actually there are two shaders one takes the image behind the UI element (which I don't think slows down) the second takes that image via script and adds a Windows 11 similar blur effect to that Image (like a color mixer)
     
  4. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,411
    those kinds of blurs and grabs can be expensive on android..
    (that's why asset store and forums and filled with fast mobile blur and related assets/questions)

    i guess you'd need to show some parts of those scripts / shaders,
    so people can comment if they can be optimized or adjusted.
    (or google for those optimized mobile blurs, and compare)
     
  5. said123sawn

    said123sawn

    Joined:
    Oct 31, 2019
    Posts:
    26
    The problem is that I couldn't find this shader anywhere, people only made it for 3d objects, so I combined a lot of things and made this shader that works for UI objects. But I'll add these shaders and script here in a few hours, I hope someone can point out my mistake. Thanks again.
     
  6. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    Modifying the texture from a script means the data has to be read from the GPU to CPU RAM, this requires a lot of bandwidth, which mobile devices don't have much of due to their low-power nature. You then also have to send it back to the GPU, making matters worse.

    For the shader that reads the background color, you're not using GrabPass right? As that will be expensive on mobile. If you're using URP you can enable the "Opaque Texture" in your pipeline settings and sample that using _CameraOpaqueTexture in your shader.

    You can do the blurring by simply doing multiple offset samples of your UI texture and background, all in 1 shader pass. Look up examples of "gaussian blur" or similar in shader.
     
  7. said123sawn

    said123sawn

    Joined:
    Oct 31, 2019
    Posts:
    26
    The problem is that all searches for "gaussian blur" only apply to 3D Objects (i.e. scene) but I want it to only apply to UI Images.

    First Shader:
    Background.shader
    Second Shader:
    GaussianBlur.shader

    Also this is my code:
    Code (CSharp):
    1.     public Image Second;
    2.     public Material m;
    3.     public Material m2;
    4.     public Shader s;
    5.     public Shader s2;
    6.     public Vector3 vc;
    7.  
    8.     void Start()
    9.     {
    10.         m = new Material(s);
    11.         m2 = new Material(s2);
    12.         m.SetFloat("_Iterations", 25);
    13.         m.SetFloat("_Lightness", 1.1f);
    14.         m.SetTexture("_AltTexture", null);
    15.         GetComponent<Image>().material = m2;
    16.         Second.material = m;
    17.     }
    18.  
    19.  
    20.     void Update()
    21.     {
    22.         if (m == null || m2 == null)
    23.         {
    24.             m = new Material(s);
    25.             m2 = new Material(s2);
    26.             m.SetFloat("_Iterations", 25);
    27.             m.SetFloat("_Lightness", 1.1f);
    28.             m.SetTexture("_AltTexture", null);
    29.             GetComponent<Image>().material = m2;
    30.             Second.material = m;
    31.         }
    32.         else
    33.         {
    34.             if (transform.position != vc || m.GetTexture("_AltTexture") == null)
    35.             {
    36.                 Debug.Log("started");
    37.                 RenderTexture buffer = new RenderTexture(1920, 1080, 0, RenderTextureFormat.ARGB32);
    38.                 Graphics.Blit(null, buffer, m2);
    39.                 RenderTexture.active = buffer;
    40.                 buffer.wrapMode = TextureWrapMode.Repeat;
    41.                 m.SetTexture("_AltTexture", buffer);
    42.                 vc = transform.position;
    43.             }
    44.         }
    45.     }
    :confused:

    The reason the code is so long is because I want the object to create the effect only when it is moved (Maybe it's good for performance)

    Example:
    Blur Example.png

    :(:(:(:(
     

    Attached Files:

  8. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    UI is still a 3D object, it's a quad being rendered on the screen. All that matters is sampling the texture that will be behind it, at different offsets. Example here:
    https://forum.unity.com/threads/gaussian-blur-not-working-on-regular-texture.623176/

    Basically just sample your UI _MainTex with that, as well as the background texture and then blend the result.
     
  9. said123sawn

    said123sawn

    Joined:
    Oct 31, 2019
    Posts:
    26
    Actually, I'm not good with shaders. I didn't quite understand where exactly my mistake was.
     
    Last edited: Nov 16, 2022
  10. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,411
    for the blur, this is expensive for mobile (doing that many texture samples in for loops)
    upload_2022-11-16_10-7-25.png

    usually those mobile blur shaders only do as few samples as possible (the tex2d() line)
    *of course it wont look as good then..

    this one does only few samples on 2 directions
    https://github.com/luluco250/unity-ui-blur/tree/master/Assets/UIBlur/Materials

    this one has more options (how many "taps" it does)
    https://github.com/PavelDoGreat/Super-Blur

    this one does quite many
    https://github.com/rygo6/MobileBlur...master/Assets/Shaders/BlurryRefraction.shader

    this ones free, havent checked
    https://learn.jettelly.com/ui-blur-shader/

    this asset plugin also mentions, that the blur works well in higher end devices only
    https://assetstore.unity.com/packages/tools/gui/translucent-image-fast-ui-background-blur-78464