Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Apply normal map to map at runtime URP not render until material opened in inspector

Discussion in 'Universal Render Pipeline' started by Tarrag, Jan 24, 2020.

  1. Tarrag

    Tarrag

    Joined:
    Nov 7, 2016
    Posts:
    215
    Hi

    I am finding applying a normal map at runtime to a material with URP does not render on the object until I open to see the properties of the material in the inspector. Behaviour extends to AO.

    Affects both Editor and Play mode, so play mode the normal map never renders.

    Here code I'm using:
    Code (CSharp):
    1. public Texture2D normalSourceTex;//attach in inspector normal map classified with Texture Type "Normal map"
    2. thisMaterial.SetTexture("_BumpMap", normalSourceTex);
    Here's a video to show: https://drive.google.com/open?id=1TL9CeTAupcV0JZpvs2SV6lZKt1CoezNz

    Tested on freshly created project URP 7.1.6 , Unity 2019.3.0f3 and 2019.3.0f5, Unity 2020.1.0a20.254.

    Anyone experiencing similar behaviour and found a solution to this?

    Thank you for your help
     
  2. BattleAngelAlita

    BattleAngelAlita

    Joined:
    Nov 20, 2016
    Posts:
    400
    In the URP Lit shader, keyword which is responsible for the presence of the normal map setted as a shader_feature
    Code (CSharp):
    1.  
    2.             ...
    3.             #pragma exclude_renderers d3d11_9x
    4.             #pragma target 2.0
    5.  
    6.             // -------------------------------------
    7.             // Material Keywords
    8. -------->#pragma shader_feature _NORMALMAP <----------
    9.             #pragma shader_feature _ALPHATEST_ON
    10.             #pragma shader_feature _ALPHAPREMULTIPLY_ON
    11.             ...
    12.  
    This means that if there is no material with normal map in your project, unity will not compile shader variant with this option. Setup a normal map in material inspector toggles unity to compile this variant.
    Code (CSharp):
    1.  
    2.             // Normal Map
    3.             if(material.HasProperty("_BumpMap"))
    4.                 CoreUtils.SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap"));
    5.  
    Setting up it's manually with script - will not.
    You can try to setting up "_NORMALMAP" keyword by your self. In 2017 and below this is forces unity to compile this variant at runtime, afaik in 2018 and above runtime compilation doesn't work.
    Also, you can modify URP shader, and change keyword to be a multi_compile instead of a shader_feature.
     
    MichaelEGA, Tarrag and phil_lira like this.
  3. Tarrag

    Tarrag

    Joined:
    Nov 7, 2016
    Posts:
    215
    thanks a bunch for the leads @BattleAngelAlita ,

    After testing your suggestions this did it for me :)

    thisMaterial.EnableKeyword("_NORMALMAP");
    thisMaterial.SetTexture("_BumpMap", normalSourceTex);
     
    Last edited: Jan 24, 2020
    Propagant and AaronBalint like this.
  4. BattleAngelAlita

    BattleAngelAlita

    Joined:
    Nov 20, 2016
    Posts:
    400
    Test this in build. In Editor unity can recompile shader, but i don't sure about build. Last time this is not working for me, and i just replace all shader_feature in my shader to multi_compile:)(and get 19000 shader variants :()
     
  5. Tarrag

    Tarrag

    Joined:
    Nov 7, 2016
    Posts:
    215
    Oh @BattleAngelAlita that's right, it works on editor but not on build :eek:

    Thank you so much for explaining the background. It appears that at the cost of performance I can attach a dummy normal map and switch at runtime - e.g. Start/thereafter and it works but player has to wait a bit longer :(

    Unfortunately I'm not a shader guru at all :oops:
    Cheers!
     
  6. BattleAngelAlita

    BattleAngelAlita

    Joined:
    Nov 20, 2016
    Posts:
    400
    You can create dummy material with normal map attached, and put it somewhere in your scene to force unity compile that shader variant.
     
    MichaelEGA, gnostici and Tarrag like this.
  7. GurnoorRana

    GurnoorRana

    Joined:
    Apr 13, 2019
    Posts:
    1
    Hi,
    I was creating a new Material through script in runtime in URP, but when it is applied, it doesn't render, probably because of the reason of unity not force compiling shader until I click on it. Is it possible to do compile shader manually through script like a function to make it work after creating it?

    Thanks in advance
     
  8. MichaelEGA

    MichaelEGA

    Joined:
    Oct 11, 2019
    Posts:
    39
    Any chance you'd be able to give me a bit more detail?

    I'm generating normal maps at runtime and adding them to a pre-existing material which has a normal map when it was compiled, but the generated normal map still doesn't appear in the build.

    SOLVED:

    The solution was stated above:

    For those who want a bit more detail, I did the following:
    1. Made a new shader
    2. Copied all the code from the standard URP Lit Shader
    3. Edited the following line, from this:
    // Material Keywords
    #pragma shader_feature_local _NORMALMAP

    to this:
    // Material Keywords
    #pragma multi_compile_local _NORMALMAP

    And this line:
    Shader "Universal Render Pipeline/Lit"

    to this:
    Shader "Custom/NewLit"

    4. Saved new shader
    5. Made a dummy object that used this shader as a material with a dummy normal map texture.

    This forces Unity to compile multiply variants of this particular shader for use at runtime. It also increases build times a little bit, but not too much.
     
    Last edited: Oct 2, 2022