Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

post process stack v2 changing settings in code is getting increasingly convoluted

Discussion in 'Graphics Experimental Previews' started by laurentlavigne, Jul 22, 2017.

  1. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,327
    v1 code:
    Code (CSharp):
    1.     [SerializeField] PostProcessProfile postFX;
    2.     [SerializeField] AnimationCurve DOFDistance;
    3.     void Update()
    4.     {
    5.         var dof = postFX.depthOfField.settings;
    6.         dof.focusDistance = DOFDistance.Evaluate (Time.time - timeStart);
    7.         postFX.depthOfField.settings = dof;
    8.     }
    v2:
    Code (CSharp):
    1.     [SerializeField] PostProcessProfile postFX;
    2.     [SerializeField] AnimationCurve DOFDistance;
    3.     void Update()
    4.     {
    5.         DepthOfField dof;
    6.         postFX.TryGetSettings<DepthOfField> (out dof);
    7.         dof.focusDistance.Override(DOFDistance.Evaluate (Time.time - timeStart));
    8. //        postFX.depthOfField.settings = dof;
    9.     }
    Wrong direction
     
  2. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I'd argue that if it has any kind of performance/extensibility benefit, such small extra work is well worth it.

    The TryGetSettings is probably because you can then add your own custom effects to the stack (just a guess). Also you only have to do that whole thing once, and then cache your 'DepthOfField' somewhere publicly accessible

    Now that I think about it, the workflow has actually improved....

    Before:
    Code (CSharp):
    1.  
    2.     public PostProcessProfile postFX;
    3.     public var dof;
    4.  
    5.     private void Start()
    6.     {
    7.         dof = postFX.depthOfField.settings;
    8.     }
    9.  
    10.     private void Update()
    11.     {
    12.         // two lines
    13.         dof.focusDistance = something;
    14.         postFX.depthOfField.settings = dof;
    15.     }
    After:
    Code (CSharp):
    1.  
    2.     public PostProcessProfile postFX;
    3.     public DepthOfField dof;
    4.  
    5.     private void Start()
    6.     {
    7.         postFX.TryGetSettings<DepthOfField>(out dof);
    8.     }
    9.  
    10.     private void Update()
    11.     {      
    12.         // one line
    13.         dof.focusDistance.Override(something);
    14.     }
     
    Last edited: Aug 4, 2017
    Harinezumi and dadude123 like this.
  3. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,327
    True that. I think it was more a reaction to the ever changing pattern. Lack of consistency throughout the API.
     
  4. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    715
    The advantages of using volumes and their weight vastly outbalance the added complexity of changing things in code. At least now it is easy to animate/blend effects...
     
  5. UnityLighting

    UnityLighting

    Joined:
    Mar 31, 2015
    Posts:
    3,874
    It's more easier compare to V1 :

    Code (CSharp):
    1.                 Bloom b;
    2.                 GameObject.Find("Global Volume").GetComponent<PostProcessVolume>().sharedProfile.TryGetSettings(out b);
    3.                 b.intensity.value = bIntensity;
    4.                 b.color.value = bColor;
    5.                 b.enabled.value = true
    You must set OverrideState value to the true before changing values for each parameters
     
  6. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    715
    Actually the above won't work as you need to explicitly override the value:
    Code (CSharp):
    1.    AmbientOcclusion ao;
    2.                 if (profile.TryGetSettings(out ao))
    3.                 {
    4.                     ao.enabled.Override(someBoolValue);
    5.                 }
     
  7. UnityLighting

    UnityLighting

    Joined:
    Mar 31, 2015
    Posts:
    3,874
    Yes you must enable each option in inspector or enabled override state before changing values

    Code (CSharp):
    1. ao.enabled.overrideState = true;
    2. ao.enabled.value = true;
     
  8. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    715
    Oh I didn't know that, I always use the Override method as it saves me one line of code ;p
     
    UnityLighting likes this.
  9. unisip

    unisip

    Joined:
    Sep 15, 2010
    Posts:
    340
    This override state design decision seems odd to me. I don't understand how settings are overriden per volume when the values are actually changed in the profile asset.
    Plus it has a serious impact on runtime performance, as can be seen in the profiler timeline.

    Has anyone else had concerns with that too ?
     
  10. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    If you want it to be per-volume, make sure to duplicate the volume's Profile on start, so that it'll be independant. Much like you'd duplicate a sharedMaterial if you want it to be independant. Otherwise it'll affect all volumes (or at least I suppose so). Both scenarios (per-profile changes and per-volume changes) can be desired, so I think it's good that it works like that

    Do you cache the settings on start, or do you do a TryGetSettings<> at each frame?

    You should work like this:
    Code (CSharp):
    1.  
    2.  
    3.     public PostProcessProfile postFX;
    4.     public DepthOfField dof;
    5.  
    6.     private void Start()
    7.     {
    8.         postFX.TryGetSettings<DepthOfField>(out dof); // Good!
    9.     }
    10.     private void Update()
    11.     {
    12.         dof.focusDistance.Override(something);
    13.     }
    14.  
    ..and not like this:
    Code (CSharp):
    1.  
    2.  
    3.     public PostProcessProfile postFX;
    4.  
    5.     private void Update()
    6.     {
    7.         DepthOfField dof;
    8.         postFX.TryGetSettings<DepthOfField>(out dof); // Bad!
    9.         dof.focusDistance.Override(something);
    10.     }
    11.  
     
    Last edited: Feb 9, 2018
    Alverik likes this.
  11. unisip

    unisip

    Joined:
    Sep 15, 2010
    Posts:
    340
    Well I don't do ANYTHING in code. I just profiled a very simple test case with a single fx volume, with a single profile that has several overriding settings. It's a typical real world scenario with bloom, AO, color grading.
    And it turns out that it is eating up about 0.6ms in PostProcessLayer.OnPreCull, half of which seems to be spent on fetching parameters.
    I am really surprised that it would take that much, it's not really doing anything clever...
     
    one_one likes this.