HDRP - Change Custom Frame Settings through Scripts

How can I change the Frame Settings of a Camera through Scripting?
I’m trying to have a custom user quality settings, and im looking for ways to toggle the Frame Setting mask through scripting, switching things like SSR or SSAO through a script.
How can I do it? I can’t find detailed enough info through the documentation

up

Also how to make field with custom frame settings like in camera? And why I can’t add more default frame settings? If I have several cameras with custom frame settings I need to manually go over each one and tick or untick a lot of checkboxes.

I made a small CS script to enable some frame settings in runtime if you’d like.

You can find the whole list of fields here.

using System.Collections;
using UnityEngine.Rendering.HighDefinition;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Linq;
using UnityEngine;
using Utilities;
using System;

public class CustomFrameSetting : MonoBehaviour
{
   
    private     HDAdditionalCameraData             _cameraData;
    private     FrameSettings                     _frameSettings;
    private     FrameSettingsOverrideMask         _frameSettingsOverrideMask;
   
    void Start()
    {
        //Getting components
        _cameraData = this.GetComponent<HDAdditionalCameraData>();
        _frameSettings = _cameraData.renderingPathCustomFrameSettings;
        _frameSettingsOverrideMask = _cameraData.renderingPathCustomFrameSettingsOverrideMask;
       
        //Make sure Custom Frame Settings are enabled in the camera
        _cameraData.customRenderingSettings = true;
       
        //Enabling Lit Shader Mode
        _frameSettingsOverrideMask.mask[(uint)FrameSettingsField.LitShaderMode] = true;
        //...
       
        //Applying the frame setting mask back to the camera
        _cameraData.renderingPathCustomFrameSettingsOverrideMask = _frameSettingsOverrideMask;
       
       
    }

    // Update is called once per frame
    void Update()
    {
       
        if(Input.GetKeyDown(KeyCode.F))
        {
            _frameSettings.litShaderMode = LitShaderMode.Forward;
            SetFrameSettings(_frameSettings);
        }
       
        if(Input.GetKeyDown(KeyCode.D))
        {
            _frameSettings.litShaderMode = LitShaderMode.Deferred;
            SetFrameSettings(_frameSettings);
        }

    }
   
    private void SetFrameSettings(FrameSettings frameSettings){
        _cameraData.renderingPathCustomFrameSettings  = frameSettings;
    }
}
6 Likes

Thanks!

Hi, is it possible to directly modify the HDRP default settings instead of doing it on each camera ? I don’t find any acces to it through script.

1 Like

Any news on this? Couldn’t find anything and it’s kind of annoying to change every camera and volume per script. Would be much easier to be able to disable certain features globally. It is really hard to provide a half way decent settings menu for the players. Or did I miss anything and there is a way to achieve it in the meantime?

HDRP Global Settings are set manually and globally (as the name suggests) for the whole project you are working on. For performance (or artistic reasons), those can be overridden per camera as you already understood.

For the concept of menu settings (like graphics quality) for users, the proper and current way to do this, is by having multiple HDRP assets with different features enabled per asset. That way a user could select a quality setting corresponding to an HDRP asset (low / medium / high for exemple). The HDRP template has this already setup if you want an example.

8469494--1125395--upload_2022-9-27_16-41-54.png

Finally some sweet sweet prog.
So it took me forever to figure this out, because there’s no f-----ing documentation explaining this stuff.
But if you want something like custom LOD biases you need to also change the LOD bias mode to overwrite
It may sound straight forward, but with no one explaining this it was confusing as heck.
So for example if we want the LOD bias to = 2.2f

It will look something like the attached file:

8533184–1139366–CustomFrameSetting.cs (2.86 KB)

1 Like

You can control some (many) things with volumes.

One approach that worked for me was to create a global volume with very high priority (like 99). I then add my overrides to that dynamically. Since it’s global and high priority it automatically overrides any other volumes.

Example (generic base class):

using UnityEngine;
using UnityEngine.Rendering;

public abstract class SettingsVolume<T> : MonoBehaviour where T : SettingsVolume<T>
{
    private static T _instance;
    public static T Instance
    {
        get
        {
            if (!_instance)
            {
                _instance = new GameObject().AddComponent<T>();
                _instance.name = _instance.GetType().ToString();
                _instance.createVolume();
                _instance.init();

                DontDestroyOnLoad(_instance.gameObject);
            }
            return _instance;
        }
    }

    protected Volume volume;

    protected virtual int getPriority()
    {
        return 99;
    }

    protected virtual void createVolume()
    {
        volume = gameObject.AddComponent<Volume>();
        volume.priority = getPriority();
        volume.profile = ScriptableObject.CreateInstance<VolumeProfile>();
    }

    protected abstract void init();
}

Example of a concrete override volume that disables or enables shadows.

using UnityEngine.Rendering.HighDefinition;

public class SettingsVolumeShadowsHDRP : SettingsVolume<SettingsVolumeShadowsHDRP>
{
    protected HDShadowSettings shadowSettings;
    protected ContactShadows contactShadows;

    public bool Shadows
    {
        get
        {
            return !shadowSettings.maxShadowDistance.overrideState;
        }

        set
        {
            shadowSettings.maxShadowDistance.overrideState = !value;
            contactShadows.enable.overrideState = !value;
        }
    }

    override protected void init()
    {

        // Setup to disable shadows via max distance = 0.
        shadowSettings = volume.profile.Add<HDShadowSettings>();
        shadowSettings.Override(shadowSettings, 1f);
        shadowSettings.maxShadowDistance.value = 0f;
        shadowSettings.maxShadowDistance.overrideState = false;

        // Setup to disable contact shadows
        contactShadows = volume.profile.Add<ContactShadows>();
        contactShadows.enable.value = false;
        contactShadows.enable.overrideState = false;
    }
}

Usage:
SettingsVolumeShadowsHDRP.Instance.Shadows = false;

You may end up with quite some GOs in the scene using this but if that’s a problem then you can always combine them into one. Not sure if that’s the way to go but it worked for me and I need not worry about which volumes or cameras are active at the moment. Of course this only work for things controllable by volumes.

Is there really no way to globally toggle quality features at runtime? Without the hacky use of global volumes and per camera scripts.

This can’t possibly be the “proper” way.

What If I want the user to control different bloom settings globally, and also different ambient occlusion settings? (like exists in every game)

Global low/medium/high settings are not granular enough, and if anything just get in the way of/add complication to achieving the desired granular settings.

Thanks :slight_smile:

In order to get granular quality settings, we are using a combination of a high priority global profile, which applies the quality indices, and per camera frame settings, to actually enable/disable the features.

This seems to work in theory, but we are seeing some strange issues when attempting to set the quality index on various effects.

For example, on a fresh volume, I add a ScreenSpaceAmbientOcclusion, and set the quality override to 1, desiring “Medium” Settings.

I am doing it like this

screenSpaceAmbientOcclusion.quality.Override(1);

I would expect the volume to look like this, with only the quality level overridden.

Instead I am seeing this, where the quality level is set, but various sub settings are incorrectly set. This incorrectly applies the quality level, and it sometimes has the incorrect values here, according to the quality level set on the HDRP asset.

Is there something silly I am doing?

Thanks,
Chris

Strangely, I have noticed that sometimes it works as expected, with no sub setting overrides.

Another thing I am not to sure on is how to globally set shadow quality. You cant seem to set this with a volume, and you cant set this with frame settings. What is the recommended way to change between low/medium/high resolution and filtering settings?

Surely we don’t need to add a script to every single light?

For shadow quality, you are supposed to set on your light the quality you desire and then you can manage this quality (resolution) in each HDRP settings like in the screenshots. Depending on which quality settings is set, a different HDRP asset is assigned to it and Medium will correspond to a specific resolution.

Sorry I should have clarified in my post that I want to change these settings at runtime, for user exposed quality settings.

The per camera script workaround is still the only working method, since the renderpipeline asset settings cannot be changed at runtime (for now!)
https://discussions.unity.com/t/915203

1 Like