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

v1 code:

    [SerializeField] PostProcessProfile postFX;
    [SerializeField] AnimationCurve DOFDistance;
    void Update()
    {
        var dof = postFX.depthOfField.settings;
        dof.focusDistance = DOFDistance.Evaluate (Time.time - timeStart);
        postFX.depthOfField.settings = dof;
    }

v2:

    [SerializeField] PostProcessProfile postFX;
    [SerializeField] AnimationCurve DOFDistance;
    void Update()
    {
        DepthOfField dof;
        postFX.TryGetSettings<DepthOfField> (out dof);
        dof.focusDistance.Override(DOFDistance.Evaluate (Time.time - timeStart));
//        postFX.depthOfField.settings = dof;
    }

Wrong direction

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:

    public PostProcessProfile postFX;
    public var dof;

    private void Start()
    {
        dof = postFX.depthOfField.settings;
    }

    private void Update()
    {
        // two lines
        dof.focusDistance = something;
        postFX.depthOfField.settings = dof;
    }

After:

    public PostProcessProfile postFX;
    public DepthOfField dof;

    private void Start()
    {
        postFX.TryGetSettings<DepthOfField>(out dof);
    }

    private void Update()
    {       
        // one line
        dof.focusDistance.Override(something);
    }
2 Likes

True that. I think it was more a reaction to the ever changing pattern. Lack of consistency throughout the API.

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…

It’s more easier compare to V1 :

                Bloom b;
                GameObject.Find("Global Volume").GetComponent<PostProcessVolume>().sharedProfile.TryGetSettings(out b);
                b.intensity.value = bIntensity;
                b.color.value = bColor;
                b.enabled.value = true

You must set OverrideState value to the true before changing values for each parameters

Actually the above won’t work as you need to explicitly override the value:

   AmbientOcclusion ao;
                if (profile.TryGetSettings(out ao))
                {
                    ao.enabled.Override(someBoolValue);
                }

Yes you must enable each option in inspector or enabled override state before changing values

ao.enabled.overrideState = true;
ao.enabled.value = true;

Oh I didn’t know that, I always use the Override method as it saves me one line of code ;p

1 Like

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 ?

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:

    public PostProcessProfile postFX;
    public DepthOfField dof;

    private void Start()
    {
        postFX.TryGetSettings<DepthOfField>(out dof); // Good!
    }
    private void Update()
    {
        dof.focusDistance.Override(something);
    }

..and not like this:

    public PostProcessProfile postFX;

    private void Update()
    {
        DepthOfField dof;
        postFX.TryGetSettings<DepthOfField>(out dof); // Bad!
        dof.focusDistance.Override(something);
    }
1 Like

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…

1 Like