Search Unity

Change shadow resolution from script

Discussion in 'Universal Render Pipeline' started by wahntin, Nov 28, 2019.

  1. alan-lawrance

    alan-lawrance

    Joined:
    Feb 1, 2013
    Posts:
    360
    Found this thread looking for a way to dynamically turn shadows on/off in URP.

    It's 2022 and is seems this is still not possible (at least in 2020.3 that I'm using). The original question was posted Nov 2019. If it's not added yet, what are the chances it will ever get added?
     
    zalogic likes this.
  2. Xtro

    Xtro

    Joined:
    Apr 17, 2013
    Posts:
    610
    Can't you just toggle shadows on the light source?
     
  3. alan-lawrance

    alan-lawrance

    Joined:
    Feb 1, 2013
    Posts:
    360
    You can do that, but it is not a good solution to dynamically turning shadows on/off globally at any time (ie via in-game settings).
     
  4. Xtro

    Xtro

    Joined:
    Apr 17, 2013
    Posts:
    610
    This above ^ sounds like you want to "dynamically turn shadows on/off globally at any time".

    Sorry if I don't understand what you mean.
     
  5. alan-lawrance

    alan-lawrance

    Joined:
    Feb 1, 2013
    Posts:
    360
    It's common for games (especially on PC) to provide graphics related settings such as turning shadows on/off, etc. Without having this functionality exposed in URP through script, the workaround is a URP asset for every combination of settings, which is not scalable.
     
    homemacai and Ruslank100 like this.
  6. Xtro

    Xtro

    Joined:
    Apr 17, 2013
    Posts:
    610
    Oh ok. You want to toggle the shadows globally for game settings purposes.

    Yes. URP doesn't provide an easy way to change settings as mentioned in this original thread.

    As I suggested earlier, you can find all lights and toggle shadows globally according to the game settings but I understand that this is not a nice solution.

    The other solution which was proposed by other people in this thread is not perfect but it's simple enough to use.

    My implementation goes like this, you can modify it for your own use:

    (trimmed down version; may not compile as is)

    Code (CSharp):
    1.  
    2. using System.Reflection;
    3. using UnityEngine;
    4. using UnityEngine.Rendering;
    5. using UnityEngine.Rendering.Universal;
    6.  
    7. public class GameMaster : MonoBehaviour
    8. {
    9.     static readonly FieldInfo ShadowDistanceField;
    10.  
    11.     RenderPipelineAsset RenderPipeline;
    12.  
    13.     static GameMaster()
    14.     {
    15.         var RenderPipelineAssetClassType = typeof(UniversalRenderPipelineAsset);
    16.         const BindingFlags PrivateInstanceBindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
    17.         ShadowDistanceField = RenderPipelineAssetClassType.GetField("m_ShadowDistance", PrivateInstanceBindingFlags);
    18.     }
    19.  
    20.     void Start()
    21.     {
    22.         // Must clone the render pipeline asset to protect project level settings from runtime value changes.
    23.         RenderPipeline = Instantiate(QualitySettings.renderPipeline);
    24.     }
    25.  
    26.     void Update()
    27.     {
    28.         if (Application.isEditor) GameMaster.FixRenderPipelineReferenceInEditor();
    29.     }
    30.  
    31.     public void SetShadowDistance(float Value)
    32.     {
    33.         ShadowDistanceField.SetValue(RenderPipeline, Value);
    34.     }
    35.  
    36.     public void FixRenderPipelineReferenceInEditor()
    37.     {
    38.         // UNITY BUG: Unity loses the references to the cloned render pipeline assets when Quality Settings window shown in Unity inspector. We re-assign them here.
    39.         if (!QualitySettings.renderPipeline) QualitySettings.renderPipeline = RenderPipeline;
    40.     }
    41. }
    42.  
    You can implement your own ToggleShadows method similar to SetShadowDistance above.
     
  7. michalpiatek

    michalpiatek

    Joined:
    Feb 26, 2021
    Posts:
    81
    Looking at this as well. Unity 2022 still won't let me change main shadow resolution. Swapping render pipeline assets is an acceptable solution but also a pain in the bum. This workflow isn't very flexible and results in myriads of permutations of the pipeline asset.

    Any news if we can get a setter for main shadowmap resolution? :confused:
     
    Ruslank100 and zalogic like this.
  8. wwWwwwW1

    wwWwwwW1

    Joined:
    Oct 31, 2021
    Posts:
    769
    Hey, have you tried Inc8877's URP Graphic Configurator (MIT License)?

    To Unity: It's a 3rd-party solution (using reflection, no update guarantees) so we're still expecting URP to expose these settings.
     
    Ruslank100 likes this.
  9. michalpiatek

    michalpiatek

    Joined:
    Feb 26, 2021
    Posts:
    81
    I'm not a huge fan of reflections, but thanks for the link. I know how to change the shadow resolution in URP, I'm just dissatisfied with the lack of a simpler, built-in solution.
     
    Ruslank100 and wwWwwwW1 like this.
  10. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    191
    You can just change the shadow resolution like so (it's publicly available):

    Code (CSharp):
    1. QualitySettings.shadowResolution = ShadowResolution.High;
    Or am I missing something here?
     
    Sky77 likes this.
  11. homemacai

    homemacai

    Joined:
    Jul 22, 2020
    Posts:
    74
    The previous answer is kinda right but it doesnt update the URP asset values when using that, also there is a weird code in URP, specifically in UnityEditor.Rendering.Universal.Converter, which has the GetEquivalentMainlightShadowResolution function below:
    Code (CSharp):
    1.         private static int GetEquivalentShadowResolution(int value)
    2.         {
    3.             switch (value)
    4.             {
    5.                 case 0: // low
    6.                     return 1024;
    7.                 case 1: // med
    8.                     return 2048;
    9.                 case 2: // high
    10.                     return 4096;
    11.                 case 3: // very high
    12.                     return 4096;
    13.                 default: // backup
    14.                     return 1024;
    15.             }
    16.         }
    As you can see high and very high both return 4k resolutions , and the low is not low at all, also in the URP asset you can (manually) set the resolution to 5 different values: 256, 512, 1024, 2048, 4096 which is not possible using this function. And I would like to give that option to my players, since I am having issues with the shadows performance (notebook GPU) and players will most likely have them too. Is there any plans to change this? Or would it break anything?
     
    Last edited: Dec 20, 2022
  12. Michiel-Frankfort

    Michiel-Frankfort

    Joined:
    Sep 7, 2014
    Posts:
    218

    How is that setter going? 2 years have passed...
     
    Ruslank100, zalogic, cxode and 2 others like this.
  13. homemacai

    homemacai

    Joined:
    Jul 22, 2020
    Posts:
    74
    Also using this :
    Code (CSharp):
    1.             QualitySettings.antiAliasing = value;        
    2.             QualitySettings.SetQualityLevel(0);
    Does not change the value on the URP asset, I have only one quality level land only one URP asset to prevent confusion correctly set in the project settings at the 0 index, but the only values I can update are the ones directly accesssible in the asset, and things like AntiAlias , shadow resolution and many others only accessible through QualitySettings, do not update the URP asset at all.
     
  14. Michiel-Frankfort

    Michiel-Frankfort

    Joined:
    Sep 7, 2014
    Posts:
    218

    Yeah I used the reflections workaround, still silly that after two years there is still no setter
     
    Ruslank100 likes this.
  15. homemacai

    homemacai

    Joined:
    Jul 22, 2020
    Posts:
    74
    Yes it is very weird that such a simple thing is left out like that, also they could just change in the UniversalRenderPipelineAsset all these internal set, to regular setter, or any other way to just set this values directly in the pipeline asset.:
    Code (CSharp):
    1.         public int mainLightShadowmapResolution
    2.         {
    3.             get { return (int)m_MainLightShadowmapResolution; }
    4.             internal set { m_MainLightShadowmapResolution = (ShadowResolution)value; }
    5.         }
    Above is the Shadow Resolution, for example, we could set it to all 5 resolutions if only changing this variable was possible
     
    zalogic likes this.
  16. zalogic

    zalogic

    Joined:
    Oct 6, 2010
    Posts:
    273
    Hey guys, just wanted to add a simplified version of the URP asset extra exposed properties. The approach of course is still by using runtime reflection wrapped in simple extension methods for the URP asset.
    I added the extra public properties I needed besides the ones already available in Unity 2022.2.2f1 so feel free to add other properties/fields you need exposed.
    It offers a bit of an extra compiler safety for URP asset properties that already have a private/internal setter and in-case Unity changes their names in a SRP update at least the compiler will scream about them. ✌

    To use the extension methods provided, just drop this script in your project and call the extra provided setters on your active URP asset instance from:
    Code (CSharp):
    1. (UniversalRenderPipelineAsset)GraphicsSettings.renderPipelineAsset
    The script was tested only on Unity 2022.2.2f1.
     

    Attached Files:

    Last edited: Jan 21, 2023
    Benfont and Michiel-Frankfort like this.
  17. Kristapsmadeapp

    Kristapsmadeapp

    Joined:
    Jul 10, 2019
    Posts:
    9
    You can change URP shadow resolution like this (tested in unity 2019.4.40f1 & 2020.3.46f1):
    This example changes resolution to 256

    using UnityEngine;

    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    using System.Reflection;



    public class SettingsButtonsScript : MonoBehaviour
    {



    private System.Type universalRenderPipelineAssetType;
    private FieldInfo mainLightShadowmapResolutionFieldInfo;
    private FieldInfo additionalLightShadowmapResolutionFieldInfo;


    public void ChangeShadowQuality()
    {

    universalRenderPipelineAssetType = (GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset).GetType();

    mainLightShadowmapResolutionFieldInfo = universalRenderPipelineAssetType.GetField("m_MainLightShadowmapResolution", BindingFlags.Instance | BindingFlags.NonPublic);
    additionalLightShadowmapResolutionFieldInfo = universalRenderPipelineAssetType.GetField("m_AdditionalLightsShadowmapResolution", BindingFlags.Instance | BindingFlags.NonPublic);


    mainLightShadowmapResolutionFieldInfo.SetValue(GraphicsSettings.currentRenderPipeline, 256);
    additionalLightShadowmapResolutionFieldInfo.SetValue(GraphicsSettings.currentRenderPipeline, 256);



    }


    }
     
    zhuhaiyia1, homemacai and Mallninja like this.
  18. Leslie-Young

    Leslie-Young

    Joined:
    Dec 24, 2008
    Posts:
    1,148
    2023 called and asked about that option to globally disable/enable shadows at runtime.. .guess it won't happen. .time for hacky solutions.
     
    Ruslank100 likes this.
  19. funkyCoty

    funkyCoty

    Joined:
    May 22, 2018
    Posts:
    727
    There should be a toggle "dont strip shadow variants" right next to the options for shadows. And all of the options should have public setters. Insane that this is even an issue.
     
    AndrewCzarnietzki and Ruslank100 like this.
  20. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    864
    Unbelievable. I've used URP for just one day and I'm already doing hacks to get what I want. I just wanted a shadow resolution of 8192. Thanks for the tip @Kristapsmadeapp.

    Code (CSharp):
    1. using UnityEngine.Rendering;
    2. using UnityEngine.Rendering.Universal;
    3. using System.Reflection;
    4. using UnityEngine;
    5. using System;
    6.  
    7. [ExecuteInEditMode]
    8. public class OverrideUrpShadowResolution : MonoBehaviour
    9. {
    10.     [SerializeField] Resolution _mainLightShadowmapResolution = Resolution._8192;
    11.     [SerializeField] Resolution _additionalLightsShadowmapResolution = Resolution._4096;
    12.  
    13.     FieldInfo _mainLightShadowmapResolutionFieldInfo;
    14.     FieldInfo _additionalLightShadowmapResolutionFieldInfo;
    15.  
    16.  
    17.     public Resolution mainLightShadowmapResolution {
    18.         get { return _mainLightShadowmapResolution; }
    19.         set {
    20.             _mainLightShadowmapResolution = value;
    21.             if( _mainLightShadowmapResolutionFieldInfo == null ){
    22.                 _mainLightShadowmapResolutionFieldInfo = typeof( UniversalRenderPipelineAsset ).GetField( "m_MainLightShadowmapResolution", BindingFlags.Instance | BindingFlags.NonPublic );
    23.             }
    24.             _mainLightShadowmapResolutionFieldInfo.SetValue( GraphicsSettings.currentRenderPipeline, ParseResolution( _mainLightShadowmapResolution ) );
    25.         }
    26.     }
    27.  
    28.     public Resolution additionalLightsShadowmapResolution {
    29.         get { return _additionalLightsShadowmapResolution; }
    30.         set {
    31.             _additionalLightsShadowmapResolution = value;
    32.             if( _additionalLightShadowmapResolutionFieldInfo == null ){
    33.                 _additionalLightShadowmapResolutionFieldInfo = typeof( UniversalRenderPipelineAsset ).GetField( "m_AdditionalLightsShadowmapResolution", BindingFlags.Instance | BindingFlags.NonPublic );
    34.             }
    35.             _additionalLightShadowmapResolutionFieldInfo.SetValue( GraphicsSettings.currentRenderPipeline, ParseResolution( _additionalLightsShadowmapResolution ) );
    36.         }
    37.     }
    38.  
    39.  
    40.     [Serializable]
    41.     public enum Resolution { _256, _512, _1024, _2048, _4096, _8192, _16384 }
    42.  
    43.  
    44.     void OnValidate()
    45.     {
    46.         mainLightShadowmapResolution = _mainLightShadowmapResolution;
    47.         additionalLightsShadowmapResolution = _additionalLightsShadowmapResolution;
    48.     }
    49.  
    50.  
    51.     int ParseResolution( Resolution r ) => int.Parse( _mainLightShadowmapResolution.ToString().Substring( 1 ) );
    52. }
     
  21. Keep-Frame

    Keep-Frame

    Joined:
    Sep 7, 2017
    Posts:
    5
    Удивительно, что они с этим облажались, спасибо, сэр, за ваше решение, оно помогло мне, и я уверен, что оно поможет и другим.
     
    cxode likes this.
  22. jwlondon98

    jwlondon98

    Joined:
    Mar 27, 2015
    Posts:
    12
    You know Unity's going downhill when after nearly 4 years users still have to rely on a reflection-dependent hack cooked up by someone in the community...
     
    Gravesend likes this.
  23. Xtro

    Xtro

    Joined:
    Apr 17, 2013
    Posts:
    610
    They will announce something very big in this upcoming Unite. I want to believe it.
     
  24. Yeah, only Unity Pro will contain any kind of proper shadow, Personal and Plus will only have blob shadow. Or something.
     
  25. MicheleGiornetta

    MicheleGiornetta

    Joined:
    Nov 10, 2016
    Posts:
    1
    4 years and still nothing :)
     
    Hades714, cxode and Strom_CL like this.
  26. Carrion-Crow

    Carrion-Crow

    Joined:
    Apr 3, 2015
    Posts:
    15
    Нашел лучший вариант.

    public class GraphicSettings : MenuScreen
    {
    [SerializeField] private HDRenderPipelineAsset setting;

    private void Start()
    {
    var hdrpRenderPipelineSettings = settings.currentPlatformRenderPipelineSettings;

    hdrpRenderPipelineSettings.hdShadowInitParams.maxDirectionalShadowMapResolution = 1024; // рарешение карты

    settings.currentPlatformRenderPipelineSettings = hdrpRenderPipelineSettings;
    }
    }

    так же можно и все остальные параметры крутить.
     
  27. doomcityofkings

    doomcityofkings

    Joined:
    Apr 11, 2020
    Posts:
    8
    what i think too Unity should put 0.01% of their effort on small stuff that could make us much happier
     
  28. baggyg

    baggyg

    Joined:
    Nov 21, 2013
    Posts:
    30
    Edit: Just figured out this is retrievable by the AdditionalLightData. Be aware though that a GetComponent call will fail on this if shadows are turned off (even though the component is actually there)

    Just dropping in in 2024 to say even the "get" accessor of .shadowResolution is wrong, it just returns VeryHigh for every light regardless of the setting. Even that would be something.

    I really don't understand why its possible to run this in the editor & retrieve / change the resolution via inspector, but not possible from a script.
     
    Last edited: Apr 12, 2024