Yeah. I’m still on HDRP 7, so not sure how different it is in newer versions. But I change all sorts of HDRP settings at runtime based on user options.
There are two main parameters: a VolumeProfile (which contains all of the post-processing and effects) and the HDAdditionalCameraData from the camera you’re using (probably Camera.main), as some settings are applied to the camera itself. Hopefully this gives you a general sense of how you can do this kind of stuff.
All the references you see to “GraphicsPlayerOptions” in this code is just the class I save all the player’s graphics choices into.
public void ApplyGraphicsSettings(VolumeProfile sceneSettingsProfile, HDAdditionalCameraData hdCameraData, bool shouldAdjustHDCameraOverrides = true)
{
// Used for diagnostics.
var startTime = DateTime.Now;
// Apply screen resolution change
if (Screen.currentResolution.height != GraphicsPlayerOptions.ScreenResolutionHeight
|| Screen.currentResolution.width != GraphicsPlayerOptions.ScreenResolutionWidth
|| Screen.currentResolution.refreshRate != GraphicsPlayerOptions.ScreenRefreshRate
|| Screen.fullScreenMode != GraphicsPlayerOptions.FullScreenMode)
{
//Debug.Log($"Changing Screen Resolution to {GraphicsSettings.ScreenResolution.Width} x {GraphicsSettings.ScreenResolution.Height} {(GraphicsPlayerOptions.FullScreen ? "FullScreen" : "Windowed")}");
ScreenUtil.SetScreenResolution(GameSettingsDirector.Instance.GraphicsPlayerOptions);
}
// Apply quality change
if (QualitySettings.GetQualityLevel() != GraphicsPlayerOptions.GraphicsQualityIndex)
{
// Use the lower of the two. This is done in case the quality is set to a very high number
// that isn't available on the target system.
var qualityIndex = Mathf.Min(GraphicsPlayerOptions.GraphicsQualityIndex, QualitySettings.names.Length - 1);
//Debug.Log($"Changing quality level to {GraphicsSettings.GraphicsQualityIndex}");
QualitySettings.SetQualityLevel(qualityIndex, true);
}
// V-Sync.
QualitySettings.vSyncCount = GraphicsPlayerOptions.EnableVSync ? 1 : 0;
// When not using VSync, set target framerate to 60 to avoid inefficient rendering.
Application.targetFrameRate = GraphicsPlayerOptions.TargetFrameRate == 0 ? -1 : GraphicsPlayerOptions.TargetFrameRate;
if (hdCameraData != null && hdCameraData.gameObject.GetComponent<SupportsCustomFOV>() != null)
{
hdCameraData.gameObject.GetComponent<Camera>().fieldOfView = Mathf.Clamp(GraphicsPlayerOptions.FieldOfView, GraphicsConstants.MinFOV, GraphicsConstants.MaxFOV);
}
// SRP Batching
GraphicsSettings.useScriptableRenderPipelineBatching = GraphicsPlayerOptions.EnableSRPBatching;
if (sceneSettingsProfile != null)
{
var ambientOcclusionComponent = sceneSettingsProfile.GetComponent<AmbientOcclusion>();
if (ambientOcclusionComponent != null)
{
//Debug.Log($"Setting Use Ambient Occlusion to {GraphicsSettings.UsePostProcessingAmbientOcclusion}");
if (GraphicsPlayerOptions.AmbientOcclusionQuality == LowMediumHighOff.Off)
{
ambientOcclusionComponent.active = false;
}
else
{
ambientOcclusionComponent.active = true;
// Accepted values are 0, 1, 2, but our enum's values are 1, 2, 3 respectively.
ambientOcclusionComponent.quality.Override((int)GraphicsPlayerOptions.AmbientOcclusionQuality - 1);
}
}
var bloomComponent = sceneSettingsProfile.GetComponent<Bloom>();
if (bloomComponent != null)
{
//Debug.Log($"Setting Use Ambient Occlusion to {GraphicsSettings.UsePostProcessingAmbientOcclusion}");
bloomComponent.active = GraphicsPlayerOptions.EnableBloom;
}
var motionBlurComponent = sceneSettingsProfile.GetComponent<MotionBlur>();
if (motionBlurComponent != null)
{
if (GraphicsPlayerOptions.MotionBlurQuality == LowMediumHighOff.Off)
{
motionBlurComponent.active = false;
}
else
{
motionBlurComponent.active = true;
// Accepted values are 0, 1, 2, but our enum's values are 1, 2, 3 respectively.
motionBlurComponent.quality.Override((int)GraphicsPlayerOptions.MotionBlurQuality - 1);
}
}
var tonemappingComponent = sceneSettingsProfile.GetComponent<Tonemapping>();
if (tonemappingComponent != null)
{
tonemappingComponent.active = GraphicsPlayerOptions.EnableTonemappping;
}
var liftGammaGainComponent = sceneSettingsProfile.GetComponent<LiftGammaGain>();
if (liftGammaGainComponent != null)
{
// The gamma value we receive is normalized, where 0 represents darkest and 1 is brightest.
// 0.5 represents "normal", or a value of "1" in PPS2. So, we denormalize the value here
// to give it a suitable range.
//Debug.Log(liftGammaGainComponent.gamma.value);
liftGammaGainComponent.gamma.Override(new Vector4(1, 1, 1, DenormalizedGamma(Mathf.Clamp(GraphicsPlayerOptions.NormalizedGamma, 0, 1))));
}
SetShadowDistance(sceneSettingsProfile, GraphicsPlayerOptions.ShadowDistance);
//Debug.Log($"AO: {ambientOcclusionComponent.quality.value}; MB: {motionBlurComponent.quality.value}");
}
else
{
// This is the case where no settings have been provided, which means we should look in the
// scene for volume profiles to adjust settings
// foreach (var volumeKeeper in GameObject.FindObjectsOfType<VolumeKeeper>())
// {
// var volumeProfile = volumeKeeper.Volume.profile;
//
// var exposure = volumeProfile.GetComponent<Exposure>();
// if (exposure != null)
// {
// exposure.mode.Override(GraphicsPlayerOptions.EnableDynamicExposure ? ExposureMode.Automatic : ExposureMode.Fixed);
// }
// }
}
if (hdCameraData != null && shouldAdjustHDCameraOverrides)
{
if (hdCameraData.antialiasing != GraphicsPlayerOptions.Antialiasing)
{
//Debug.Log($"Setting Anti-aliasing to to {GraphicsSettings.Antialiasing}");
hdCameraData.antialiasing = GraphicsPlayerOptions.Antialiasing;
// If using SMAA, make sure quality is set to High.
if (GraphicsPlayerOptions.Antialiasing == HDAdditionalCameraData.AntialiasingMode.SubpixelMorphologicalAntiAliasing)
{
hdCameraData.SMAAQuality = HDAdditionalCameraData.SMAAQualityLevel.High;
}
}
// This should probably already be enabled, but just to be safe. This is the "left" checkbox in the
// camera settings, which controls whether to consider the override value. This is always true, even
// when disable shadows, as it controls whether we're allowed to enable/disable shadows.
var frameSettingsOverrideMask = hdCameraData.renderingPathCustomFrameSettingsOverrideMask;
frameSettingsOverrideMask.mask[(uint)FrameSettingsField.ShadowMaps] = true;
frameSettingsOverrideMask.mask[(uint)FrameSettingsField.Distortion] = true;
frameSettingsOverrideMask.mask[(uint)FrameSettingsField.AtmosphericScattering] = true;
frameSettingsOverrideMask.mask[(uint)FrameSettingsField.Volumetrics] = true;
frameSettingsOverrideMask.mask[(uint)FrameSettingsField.LightLayers] = true;
frameSettingsOverrideMask.mask[(uint)FrameSettingsField.ReflectionProbe] = true;
frameSettingsOverrideMask.mask[(uint)FrameSettingsField.SSAO] = true;
frameSettingsOverrideMask.mask[(uint)FrameSettingsField.ReplaceDiffuseForIndirect] = true; // See below
// It's in the frame settings that we actually enable or disable the shadows.
var frameSettings = hdCameraData.renderingPathCustomFrameSettings;
frameSettings.SetEnabled(FrameSettingsField.ShadowMaps, CamerasShouldRenderShadows());
frameSettings.SetEnabled(FrameSettingsField.Distortion, GraphicsPlayerOptions.EnableDistortion);
// Atmospheric Scatter (Fog) and Volumetrics are controlled by the same option.
frameSettings.SetEnabled(FrameSettingsField.AtmosphericScattering, GraphicsPlayerOptions.EnableVolumetrics);
frameSettings.SetEnabled(FrameSettingsField.Volumetrics, GraphicsPlayerOptions.EnableVolumetrics);
frameSettings.SetEnabled(FrameSettingsField.LightLayers, GraphicsPlayerOptions.EnableLightLayers);
frameSettings.SetEnabled(FrameSettingsField.ReflectionProbe, GraphicsPlayerOptions.EnableReflectionProbes);
frameSettings.SetEnabled(FrameSettingsField.SSAO, GraphicsPlayerOptions.AmbientOcclusionQuality != LowMediumHighOff.Off);
frameSettings.SetEnabled(FrameSettingsField.MotionBlur, GraphicsPlayerOptions.MotionBlurQuality != LowMediumHighOff.Off);
// This setting causes metal objects to look less black when reflections are disabled. It looks much better.
frameSettings.SetEnabled(FrameSettingsField.ReplaceDiffuseForIndirect, !GraphicsPlayerOptions.EnableReflectionProbes);
// Applying the frame setting mask back to the camera
hdCameraData.renderingPathCustomFrameSettingsOverrideMask = frameSettingsOverrideMask;
hdCameraData.renderingPathCustomFrameSettings = frameSettings;
}
}