Search Unity

Controlling in which shadow cascades objects are rendered

Discussion in 'General Graphics' started by theFrenchDutch, Mar 13, 2016.

  1. theFrenchDutch

    theFrenchDutch

    Joined:
    May 5, 2014
    Posts:
    25
    Hi !

    I am making a terrain engine for unity with very big terrain sizes and 3D forests close to the player. I have my shadow cascades set so that the two first cscades are for very close stuff ( < 200m) and the last two for distant mountains, up to 20km.

    My problem is, the 3d trees close to the player are getting rendered in every cascades, even the 20km one, where they arent relevant enough to even be one pixel wide on the shadow map, so its costing me thousands of useless draw calls.

    Is there a way to decide in which shadow cascades objects are rendered ? This is very important for the performance of my project. Thanks for your help :)
     
    Moon519 and Richounet like this.
  2. theFrenchDutch

    theFrenchDutch

    Joined:
    May 5, 2014
    Posts:
    25
    As I'm finding no other way to do this on my own, I feel like I have to up this post. Is this something that should be integrated into Unity itself to be possible ? Any idea on how I could "hack" that feature in myself ?

    Thanls again :)
     
  3. SchnauzerCorp

    SchnauzerCorp

    Joined:
    Oct 1, 2014
    Posts:
    7
    You could achieve this by adding a LODGroup component to each of your trees, and disable shadow casting on the LODs that get used in the far distance.
     
  4. theFrenchDutch

    theFrenchDutch

    Joined:
    May 5, 2014
    Posts:
    25
    Thanks for the answer !
    I've thought about the LODGroup component but it doesn't achieve what I need. The problem is trees close to the player need shadows, but activating the shadows on them takes up 4 draw call each as they are rendered in each of the 4 shadow cascades. But that shadow mapping information for the trees is only useful in the first two cascades (the last two are so big the trees can't even be seen in them, they are only relevant for terrain shadows).

    I could severely improve performance by disabling these irrelevant draw calls and it seems like it should be a feature for any big open world game, or am I wrong and this is done differently ?
     
  5. theFrenchDutch

    theFrenchDutch

    Joined:
    May 5, 2014
    Posts:
    25
    Up ? Maybe this is a trivial or dumb question and if that is the case I would humbly accept the critism :)
    Maybe someone from the team has looked at that before ?
     
  6. raphael-ernaelsten-heaj

    raphael-ernaelsten-heaj

    Joined:
    Mar 9, 2016
    Posts:
    78
    Hi!
    I already have asked several times if there was a way to get the cascaded information in C#, but apparently Uniteam doesn't want and stays mute about it.

    You problem is however less tricky than mine and I think can be achieve in a more approximate way.
    You can do something like this :
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class ShadowCastingModifier : MonoBehaviour
    5. {
    6.     [Range(1, 4)]
    7.     public int cascadeIndexToStopShadowCasting = 2;
    8.  
    9.     private Transform transformComponent;
    10.     private Renderer rendererComponent;
    11.     private float distanceToCamera;
    12.     private UnityEngine.Rendering.ShadowCastingMode initialShadowCastingMode;
    13.  
    14.     private void Awake()
    15.     {
    16.         transformComponent = GetComponent<Transform>();
    17.         rendererComponent = GetComponent<Renderer>();
    18.         initialShadowCastingMode = rendererComponent.shadowCastingMode;
    19.     }
    20.  
    21.     private void Update()
    22.     {
    23.         distanceToCamera = Vector3.Distance(Camera.main.transform.position, transformComponent.position);
    24.  
    25.         int currentCascade;
    26.         if (distanceToCamera > QualitySettings.shadowDistance)
    27.         {
    28.             currentCascade = 5;
    29.         }
    30.         else if (distanceToCamera > QualitySettings.shadowDistance * QualitySettings.shadowCascade4Split.z)
    31.         {
    32.             currentCascade = 4;
    33.         }
    34.         else if (distanceToCamera > QualitySettings.shadowDistance * QualitySettings.shadowCascade4Split.y)
    35.         {
    36.             currentCascade = 3;
    37.         }
    38.         else if (distanceToCamera > QualitySettings.shadowDistance * QualitySettings.shadowCascade4Split.x)
    39.         {
    40.             currentCascade = 2;
    41.         }
    42.         else
    43.         {
    44.             currentCascade = 1;
    45.         }
    46.  
    47.         if(currentCascade > cascadeIndexToStopShadowCasting)
    48.         {
    49.             rendererComponent.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
    50.         }
    51.         else
    52.         {
    53.             rendererComponent.shadowCastingMode = initialShadowCastingMode;
    54.         }
    55.     }
    56. }
    57.