Search Unity

Question Shader Graph and UI Mask

Discussion in 'Shader Graph' started by CaptainOtter, Sep 18, 2019.

  1. CaptainOtter

    CaptainOtter

    Joined:
    Aug 27, 2016
    Posts:
    11
    Is it currently so that for the UI Shaders to "respect" UI Masks, use of stencil buffers is needed? In other words this is currently not supported in Shader Graph?
     
  2. AladinoTrent

    AladinoTrent

    Joined:
    Nov 7, 2016
    Posts:
    3
    I would like to know this too.
    Is it somehow possible to create/use a Shader for Images(UI's) with Mask?

    An answer would be Great!
     
  3. MiguelBest

    MiguelBest

    Joined:
    Oct 22, 2018
    Posts:
    17
    Also would like to know this.
     
  4. qoobit

    qoobit

    Joined:
    Aug 19, 2014
    Posts:
    51
    The way to do this currently is described in this video:


    The general workflow is you need to export your final unlit master node to shader code.

    From there you need to add the following:

    Properties
    --------------

    Code (CSharp):
    1. _Stencil("Stencil ID", Float) = 0
    2. _StencilComp("StencilComp", Float) = 8
    3. _StencilOp("StencilOp", Float) = 0
    4. _StencilReadMask("StencilReadMask", Float) = 255
    5. _StencilWriteMask("StencilWriteMask", Float) = 255
    6. _ColorMask("ColorMask", Float) = 15

    Pass
    -------


    Code (CSharp):
    1.  
    2. ZTest [unity_GUIZTestMode]
    3.  
    4. ...
    5.  
    6. Stencil{
    7.     Ref [_Stencil]
    8.     Comp [_StencilComp]
    9.     Pass [_StencilOp]
    10.     ReadMask [_StencilReadMask]
    11.     WriteMask [_StencilWriteMask]
    12. }
    13. ColorMask [_ColorMask]
    14.  
    After doing so, reassign your material to this newly build scripted unlit shader and it should work with UIMask for UGUI
     
    Last edited: Jun 4, 2020
  5. WalterKavalri

    WalterKavalri

    Joined:
    Jan 22, 2019
    Posts:
    3
    I hade some problems making this work for me. NOTE: This would'nt work with a Rect2DMask! You need to use Mask for it to work on Unity 2019.3.15f1.
     
  6. jleemans

    jleemans

    Joined:
    Apr 22, 2020
    Posts:
    19
    Thx it works for me.
    It would have been great if Unity make an awesome checkbox in shader graph that made this little change automatic to have better iteration work.
     
  7. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,092
    DavidZobrist likes this.
  8. Shonnyy

    Shonnyy

    Joined:
    Aug 24, 2018
    Posts:
    3
    In case this helps anyone else, followed these steps and manually added the above code into the code shader graph generated and it still didn't work for me. I eventually found that the code generated by shader graph had 2 places where it defined SubShaders. If this solution doesn't work for you the first time be sure to look through the generated code and copy the above stencil code into the other subheader sections too.
     
  9. yyylny

    yyylny

    Joined:
    Sep 19, 2015
    Posts:
    93
    Thanks, ItsNotAGoodTime, using the second SubShader helps but now the masked image appears inside the bounding box of the mask image, ignoring the mask's transparent areas.
     
    bartouvMonkey and DavidZobrist like this.
  10. Kazeon

    Kazeon

    Joined:
    May 22, 2017
    Posts:
    41
    This is working perfectly in editor. But when my game is built to android, the material simply doesn't get rendered at all. I searched and found that it could be an issue between stencil and either URP or android device in general, I could've understood it wrongly tho. Anyone encountered the same issue and found the solution to this? Thanks in advance!

    I've attempted several tricks like:

    #1 - Using stencil override in the render pipeline setting (layer mask method). This method doesn't work for UGUI components.

    #2 - Moving the stencil portions (in the copied shader script) before the each "Pass" section. This method doesn't fix it neither.

    I'll keep updating this post for each of my fix attempt. Hopefully I can find the one that works.

    EDIT:

    So I found the actual cause & the solution, it was rather silly. The problem was actually Unity for some reason decides not to include my custom shaders into the build. The solution is of course adding all of the corresponding shaders to the project setting menu > always included shader list
     
    Last edited: Dec 24, 2021
    finerace and DavidZobrist like this.
  11. DavidZobrist

    DavidZobrist

    Joined:
    Sep 3, 2017
    Posts:
    234
    Can we please get an official solution for that. So we dont have to change stuff in the shader code but can handle it via shadergraph?
     
  12. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,092
    Like I mentioned, Unity has it on the Shader Graph roadmap "under consideration". Though it has been there now for almost 2 years. So they don't seem to really pay attention to it sadly.
    UI Toolkit has it on the roadmap as well under "planned".
     
    DavidZobrist likes this.
  13. DavidZobrist

    DavidZobrist

    Joined:
    Sep 3, 2017
    Posts:
    234
    talhakaya and --julian95-- like this.
  14. bestknighter

    bestknighter

    Joined:
    Dec 2, 2014
    Posts:
    18
    I created a custom UI shader so I could recreate Window's spotlight-like nearby-hover behaviour but I was facing problems with it not being maskable. This thread helped me get a looong way solving it but I still had some issues to work through. I'll describe what happened and what I did to make it work here for documentation purposes. Maybe someone is facing a similar issue.

    My custom shader has a float4 input called _MousePos where, every frame, I update it with the current mouse screen position. It uses this position to calculate the alpha of all Images that uses the material, changing the alpha so only those near the mouse becomes visible.

    The problem with this solution is that, when you set "Maskable" to true on a given component, Unity DOES NOT use the material that you created. It uses a internal copy with different values to the variables that we create doing workaround described in this thread. Since the copy is internal, every time my code tries to change _MousePos value, it access only the public one. The observed effect of this is that all Images with Maskable set to false works fine, the spotlight position follows the mouse correctly. But also, all images with Maskable set to true, the spotlight position is never updated.

    My solution was to create two materials, one where the masking would never occur and another one where the masking would always occur, ignoring the Maskable setting on the component.
    In my scene, ALL image components that use this material have maskable set to false. If I want them to be maskable, I DO NOT set it to true, instead I swap the material to the forced masking one. This way, every component is actually using the material created, instead of a internal copy. Allowing me to keep _MousePos updated.

    Following are the material settings to force a material to always be masked even if maskable is to to false on the component.

    Stencil ID: 1
    Stencil Comp: 3
    Stencil Op: 0
    Stencil Read Mask: 1
    Stencil Write Mask: 0
    Color Mask: 15


    For the Always Non-Maskable material I simply set its shader to be the original shadergraph.
     
    LeafesMan likes this.
  15. Gasiek

    Gasiek

    Joined:
    Feb 18, 2019
    Posts:
    2
    This worked like a charm for me <3
    Thank you
     
  16. Zephirka

    Zephirka

    Joined:
    May 19, 2016
    Posts:
    3
    Thanks a lot, you really saved me!! (I was happy when it finally worked)
     
  17. pndeveloper

    pndeveloper

    Joined:
    Dec 7, 2015
    Posts:
    29
    CRITICAL!

    Found more "Pass" methods, and more "ZTest" calls.
     
  18. rasmuskidmosebendtsen

    rasmuskidmosebendtsen

    Joined:
    Jun 17, 2021
    Posts:
    5
    Still, after 3 years this hasn't been fixed.
    And thx a lot, spent 5 hours trying to fix it but this saved my life.
     
  19. rasmuskidmosebendtsen

    rasmuskidmosebendtsen

    Joined:
    Jun 17, 2021
    Posts:
    5
    For anyone struggling with the newer versions you have to do this
    * Important * Dont use the code when you click "View generated code" or "Compile and show code" this will not work and as an other person said earlier remember only masks work not rect masks
     
    Ninquiet likes this.
  20. pepsipwns92

    pepsipwns92

    Joined:
    Jul 29, 2020
    Posts:
    9
    Bump this old thread. Ive been trying to convert my Shader Graph shader which changes the skin colour of my sprites into a regular shader to use it in my UI so that I can use masks with it (as it seems impossible with shader graph still). I've added all the above code to my shader, but it has a massive section with HLSLPROGRAM code below (from the Shader Graph) and I believe thats messing up the masking somewhere.

    I can't use a 2D Rect Mask or a regular mask (although the mask component looks so bare? nothing there) while using this material. Its weird because regular UI/Unlit/Transparent works fine in terms of masking it, but doesn't have my skin colour changing effect of course. Its something with the HLSLPROGRAMbit but I'm clueless with shaders.

    Here is my shader code: https://pastebin.com/KrQRt2s3
     
    Last edited: May 6, 2023
  21. Viva-La-Baz

    Viva-La-Baz

    Joined:
    Jun 21, 2014
    Posts:
    50
    Bumping old thread. followed this and it looks fine in Editor, but in game all my sprites are red.
     
  22. unity_0EA00B829DBFD05AD93D

    unity_0EA00B829DBFD05AD93D

    Joined:
    Sep 4, 2022
    Posts:
    1
    Same here...
     
  23. Necrospasm

    Necrospasm

    Joined:
    Apr 17, 2016
    Posts:
    9
    Logged in to purely say thank you! You just saved me days of work coz I was ready to give up. Didn't even notice they do generate more SubShaders in there.