diff --git a/com.unity.render-pipelines.high-definition/Documentation~/Images/RayTracedSubsurfaceScattering.PNG b/com.unity.render-pipelines.high-definition/Documentation~/Images/RayTracedSubsurfaceScattering.png similarity index 100% rename from com.unity.render-pipelines.high-definition/Documentation~/Images/RayTracedSubsurfaceScattering.PNG rename to com.unity.render-pipelines.high-definition/Documentation~/Images/RayTracedSubsurfaceScattering.png diff --git a/com.unity.render-pipelines.high-definition/Editor/Lighting/AmbientOcclusionEditor.cs b/com.unity.render-pipelines.high-definition/Editor/Lighting/AmbientOcclusionEditor.cs index dbfb814846f..092031e5475 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Lighting/AmbientOcclusionEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Lighting/AmbientOcclusionEditor.cs @@ -37,8 +37,6 @@ class AmbientOcclusionEditor : VolumeComponentWithQualityEditor public override void OnEnable() { - base.OnEnable(); - var o = new PropertyFetcher(serializedObject); m_Intensity = Unpack(o.Find(x => x.intensity)); @@ -61,6 +59,8 @@ public override void OnEnable() m_Denoise = Unpack(o.Find(x => x.denoise)); m_SampleCount = Unpack(o.Find(x => x.sampleCount)); m_DenoiserRadius = Unpack(o.Find(x => x.denoiserRadius)); + + base.OnEnable(); } public override void OnInspectorGUI() @@ -84,61 +84,111 @@ public override void OnInspectorGUI() { PropertyField(m_LayerMask, EditorGUIUtility.TrTextContent("Layer Mask", "Layer mask used to include the objects for ambient occlusion.")); base.OnInspectorGUI(); // Quality Setting - using (new EditorGUI.DisabledScope(!useCustomValue)) + using (new QualityScope(this)) { - EditorGUI.indentLevel++; - PropertyField(m_RayLength, EditorGUIUtility.TrTextContent("Max Ray Length", "Controls the maximal length of ambient occlusion rays. The higher this value is, the more expensive ray traced ambient occlusion is.")); - PropertyField(m_SampleCount, EditorGUIUtility.TrTextContent("Sample Count", "Number of samples for ray traced ambient occlusion.")); - PropertyField(m_Denoise, EditorGUIUtility.TrTextContent("Denoise", "Enable denoising on the ray traced ambient occlusion.")); + using (new HDEditorUtils.IndentScope()) { - EditorGUI.indentLevel++; - PropertyField(m_DenoiserRadius, EditorGUIUtility.TrTextContent("Denoiser Radius", "Radius parameter for the denoising.")); - EditorGUI.indentLevel--; + PropertyField(m_RayLength, EditorGUIUtility.TrTextContent("Max Ray Length", "Controls the maximal length of ambient occlusion rays. The higher this value is, the more expensive ray traced ambient occlusion is.")); + PropertyField(m_SampleCount, EditorGUIUtility.TrTextContent("Sample Count", "Number of samples for ray traced ambient occlusion.")); + PropertyField(m_Denoise, EditorGUIUtility.TrTextContent("Denoise", "Enable denoising on the ray traced ambient occlusion.")); + { + using (new HDEditorUtils.IndentScope()) + PropertyField(m_DenoiserRadius, EditorGUIUtility.TrTextContent("Denoiser Radius", "Radius parameter for the denoising.")); + } } - EditorGUI.indentLevel--; } } else { - PropertyField(m_Radius, EditorGUIUtility.TrTextContent("Radius", "Sampling radius. Bigger the radius, wider AO will be achieved, risking to lose fine details and increasing cost of the effect due to increasing cache misses.")); base.OnInspectorGUI(); // Quality Setting - using (new EditorGUI.DisabledScope(!useCustomValue)) + + using (new QualityScope(this)) { PropertyField(m_MaximumRadiusInPixels, EditorGUIUtility.TrTextContent("Maximum Radius In Pixels", "This poses a maximum radius in pixels that we consider. It is very important to keep this as tight as possible to preserve good performance. Note that this is the value used for 1080p when *not* running the effect at full resolution, it will be scaled accordingly for other resolutions.")); PropertyField(m_FullResolution, EditorGUIUtility.TrTextContent("Full Resolution", "The effect runs at full resolution. This increases quality, but also decreases performance significantly.")); PropertyField(m_StepCount, EditorGUIUtility.TrTextContent("Step Count", "Number of steps to take along one signed direction during horizon search (this is the number of steps in positive and negative direction).")); - } - PropertyField(m_TemporalAccumulation, EditorGUIUtility.TrTextContent("Temporal Accumulation", "Whether the results are accumulated over time or not. This can get better results cheaper, but it can lead to temporal artifacts. Requires Motion Vectors to be enabled.")); - EditorGUI.indentLevel++; - if(!m_TemporalAccumulation.value.boolValue) - { - using (new EditorGUI.DisabledScope(!useCustomValue)) - { - PropertyField(m_DirectionCount, EditorGUIUtility.TrTextContent("Direction Count", "Number of directions searched for occlusion at each each pixel.")); - } - if (m_DirectionCount.value.intValue > 3) - { - EditorGUILayout.HelpBox("Performance will be seriously impacted by high direction count.", MessageType.Warning, wide: true); - } - PropertyField(m_BlurSharpness, EditorGUIUtility.TrTextContent("Blur sharpness", "Modify the non-temporal blur to change how sharp features are preserved. Lower values blurrier/softer, higher values sharper but with risk of noise.")); - } - else - { - PropertyField(m_SpatialBilateralAggressiveness, EditorGUIUtility.TrTextContent("Bilateral Aggressiveness", "Higher this value, the less lenient with depth differences the spatial filter is. Increase if for example noticing white halos where AO should be.")); - PropertyField(m_GhostingAdjustement, EditorGUIUtility.TrTextContent("Ghosting reduction", "Moving this factor closer to 0 will increase the amount of accepted samples during temporal accumulation, increasing the ghosting, but reducing the temporal noise.")); - if (isInAdvancedMode && !m_FullResolution.value.boolValue) + PropertyField(m_TemporalAccumulation, EditorGUIUtility.TrTextContent("Temporal Accumulation", "Whether the results are accumulated over time or not. This can get better results cheaper, but it can lead to temporal artifacts. Requires Motion Vectors to be enabled.")); + + using (new HDEditorUtils.IndentScope()) { - using (new EditorGUI.DisabledScope(!useCustomValue)) + if(!m_TemporalAccumulation.value.boolValue) { - PropertyField(m_BilateralUpsample, EditorGUIUtility.TrTextContent("Bilateral Upsample", "This upsample method preserves sharp edges better, however can result in visible aliasing and it is slightly more expensive.")); + PropertyField(m_DirectionCount, EditorGUIUtility.TrTextContent("Direction Count", "Number of directions searched for occlusion at each each pixel.")); + + if (m_DirectionCount.value.intValue > 3) + { + EditorGUILayout.HelpBox("Performance will be seriously impacted by high direction count.", MessageType.Warning, wide: true); + } + PropertyField(m_BlurSharpness, EditorGUIUtility.TrTextContent("Blur sharpness", "Modify the non-temporal blur to change how sharp features are preserved. Lower values blurrier/softer, higher values sharper but with risk of noise.")); + } + else + { + PropertyField(m_SpatialBilateralAggressiveness, EditorGUIUtility.TrTextContent("Bilateral Aggressiveness", "Higher this value, the less lenient with depth differences the spatial filter is. Increase if for example noticing white halos where AO should be.")); + PropertyField(m_GhostingAdjustement, EditorGUIUtility.TrTextContent("Ghosting reduction", "Moving this factor closer to 0 will increase the amount of accepted samples during temporal accumulation, increasing the ghosting, but reducing the temporal noise.")); + if (isInAdvancedMode && !m_FullResolution.value.boolValue) + { + PropertyField(m_BilateralUpsample, EditorGUIUtility.TrTextContent("Bilateral Upsample", "This upsample method preserves sharp edges better, however can result in visible aliasing and it is slightly more expensive.")); + } } } } - EditorGUI.indentLevel--; } } + + public override QualitySettingsBlob SaveCustomQualitySettingsAsObject(QualitySettingsBlob settings = null) + { + if (settings == null) + settings = new QualitySettingsBlob(); + + // RTAO + settings.Save(m_RayLength); + settings.Save(m_SampleCount); + settings.Save(m_Denoise); + settings.Save(m_DenoiserRadius); + + // SSAO + settings.Save(m_MaximumRadiusInPixels); + settings.Save(m_FullResolution); + settings.Save(m_StepCount); + settings.Save(m_DirectionCount); + settings.Save(m_BilateralUpsample); + + return settings; + } + + public override void LoadSettingsFromObject(QualitySettingsBlob settings) + { + // RTAO + settings.TryLoad(ref m_RayLength); + settings.TryLoad(ref m_SampleCount); + settings.TryLoad(ref m_Denoise); + settings.TryLoad(ref m_DenoiserRadius); + + // SSAO + settings.TryLoad(ref m_MaximumRadiusInPixels); + settings.TryLoad(ref m_FullResolution); + settings.TryLoad(ref m_StepCount); + settings.TryLoad(ref m_DirectionCount); + settings.TryLoad(ref m_BilateralUpsample); + } + + public override void LoadSettingsFromQualityPreset(RenderPipelineSettings settings, int level) + { + // RTAO + CopySetting(ref m_RayLength, settings.lightingQualitySettings.RTAORayLength[level]); + CopySetting(ref m_SampleCount, settings.lightingQualitySettings.RTAOSampleCount[level]); + CopySetting(ref m_Denoise, settings.lightingQualitySettings.RTAODenoise[level]); + CopySetting(ref m_DenoiserRadius, settings.lightingQualitySettings.RTAODenoiserRadius[level]); + + // SSAO + CopySetting(ref m_MaximumRadiusInPixels, settings.lightingQualitySettings.AOMaximumRadiusPixels[level]); + CopySetting(ref m_FullResolution, settings.lightingQualitySettings.AOFullRes[level]); + CopySetting(ref m_StepCount, settings.lightingQualitySettings.AOStepCount[level]); + CopySetting(ref m_DirectionCount, settings.lightingQualitySettings.AODirectionCount[level]); + CopySetting(ref m_BilateralUpsample, settings.lightingQualitySettings.AOBilateralUpsample[level]); + } } } diff --git a/com.unity.render-pipelines.high-definition/Editor/Lighting/Reflection/HDScreenSpaceReflectionEditor.cs b/com.unity.render-pipelines.high-definition/Editor/Lighting/Reflection/HDScreenSpaceReflectionEditor.cs index fa449727f64..78cfaa72336 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Lighting/Reflection/HDScreenSpaceReflectionEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Lighting/Reflection/HDScreenSpaceReflectionEditor.cs @@ -39,8 +39,6 @@ class HDScreenSpaceReflectionEditor : VolumeComponentWithQualityEditor public override void OnEnable() { - base.OnEnable(); - var o = new PropertyFetcher(serializedObject); m_Enable = Unpack(o.Find(x => x.enabled)); m_RayTracing = Unpack(o.Find(x => x.rayTracing)); @@ -70,6 +68,8 @@ public override void OnEnable() // Quality m_SampleCount = Unpack(o.Find(x => x.sampleCount)); m_BounceCount = Unpack(o.Find(x => x.bounceCount)); + + base.OnEnable(); } static public readonly GUIContent k_RayTracingText = EditorGUIUtility.TrTextContent("Ray Tracing (Preview)", "Enable ray traced reflections."); @@ -100,10 +100,9 @@ void RayTracingQualityModeGUI() PropertyField(m_SampleCount, k_SampleCountText); PropertyField(m_BounceCount, k_BounceCountText); PropertyField(m_Denoise, k_DenoiseText); + using (new HDEditorUtils.IndentScope()) { - EditorGUI.indentLevel++; PropertyField(m_DenoiserRadius, k_DenoiseRadiusText); - EditorGUI.indentLevel--; } } @@ -111,9 +110,10 @@ void RayTracingQualityModeGUI() void RayTracingPerformanceModeGUI() { base.OnInspectorGUI(); - using (new EditorGUI.DisabledScope(!useCustomValue)) + + using (new HDEditorUtils.IndentScope()) + using (new QualityScope(this)) { - EditorGUI.indentLevel++; PropertyField(m_MinSmoothness, k_MinimumSmoothnessText); PropertyField(m_SmoothnessFadeStart, k_SmoothnessFadeStartText); m_SmoothnessFadeStart.value.floatValue = Mathf.Max(m_MinSmoothness.value.floatValue, m_SmoothnessFadeStart.value.floatValue); @@ -122,12 +122,10 @@ void RayTracingPerformanceModeGUI() PropertyField(m_UpscaleRadius, k_UpscaleRadiusText); PropertyField(m_FullResolution, k_FullResolutionText); PropertyField(m_Denoise, k_DenoiseText); + using (new HDEditorUtils.IndentScope()) { - EditorGUI.indentLevel++; PropertyField(m_DenoiserRadius, k_DenoiseRadiusText); - EditorGUI.indentLevel--; } - EditorGUI.indentLevel--; } } @@ -140,21 +138,23 @@ void RayTracedReflectionGUI() if (currentAsset.currentPlatformRenderPipelineSettings.supportedRayTracingMode == RenderPipelineSettings.SupportedRayTracingMode.Both) { PropertyField(m_Mode, k_ModeText); - EditorGUI.indentLevel++; - switch (m_Mode.value.GetEnumValue()) + + using (new HDEditorUtils.IndentScope()) { - case RayTracingMode.Performance: - { - RayTracingPerformanceModeGUI(); - } - break; - case RayTracingMode.Quality: + switch (m_Mode.value.GetEnumValue()) { - RayTracingQualityModeGUI(); + case RayTracingMode.Performance: + { + RayTracingPerformanceModeGUI(); + } + break; + case RayTracingMode.Quality: + { + RayTracingQualityModeGUI(); + } + break; } - break; } - EditorGUI.indentLevel--; } else if (currentAsset.currentPlatformRenderPipelineSettings.supportedRayTracingMode == RenderPipelineSettings.SupportedRayTracingMode.Quality) { @@ -202,14 +202,78 @@ public override void OnInspectorGUI() m_DepthBufferThickness.value.floatValue = Mathf.Clamp(m_DepthBufferThickness.value.floatValue, 0.001f, 1.0f); base.OnInspectorGUI(); - using (new EditorGUI.DisabledScope(!useCustomValue)) + + using (new HDEditorUtils.IndentScope()) + using (new QualityScope(this)) { - EditorGUI.indentLevel++; PropertyField(m_RayMaxIterations, k_RayMaxIterationsText); m_RayMaxIterations.value.intValue = Mathf.Max(0, m_RayMaxIterations.value.intValue); - EditorGUI.indentLevel--; } } } + public override QualitySettingsBlob SaveCustomQualitySettingsAsObject(QualitySettingsBlob settings = null) + { + if (settings == null) + settings = new QualitySettingsBlob(); + + // RTR + if (HDRenderPipeline.pipelineSupportsRayTracing && m_RayTracing.overrideState.boolValue && + m_RayTracing.value.boolValue) + { + settings.Save(m_MinSmoothness); + settings.Save(m_SmoothnessFadeStart); + settings.Save(m_RayLength); + settings.Save(m_ClampValue); + settings.Save(m_UpscaleRadius); + settings.Save(m_FullResolution); + settings.Save(m_Denoise); + settings.Save(m_DenoiserRadius); + } + // SSR + else + settings.Save(m_RayMaxIterations); + + return settings; + } + + public override void LoadSettingsFromObject(QualitySettingsBlob settings) + { + // RTR + if (HDRenderPipeline.pipelineSupportsRayTracing && m_RayTracing.overrideState.boolValue && + m_RayTracing.value.boolValue) + { + settings.TryLoad(ref m_MinSmoothness); + settings.TryLoad(ref m_SmoothnessFadeStart); + settings.TryLoad(ref m_RayLength); + settings.TryLoad(ref m_ClampValue); + settings.TryLoad(ref m_UpscaleRadius); + settings.TryLoad(ref m_FullResolution); + settings.TryLoad(ref m_Denoise); + settings.TryLoad(ref m_DenoiserRadius); + } + // SSR + else + settings.TryLoad(ref m_RayMaxIterations); + } + + public override void LoadSettingsFromQualityPreset(RenderPipelineSettings settings, int level) + { + // RTR + if (HDRenderPipeline.pipelineSupportsRayTracing && m_RayTracing.overrideState.boolValue && + m_RayTracing.value.boolValue) + { + CopySetting(ref m_MinSmoothness, settings.lightingQualitySettings.RTRMinSmoothness[level]); + CopySetting(ref m_SmoothnessFadeStart, settings.lightingQualitySettings.RTRSmoothnessFadeStart[level]); + CopySetting(ref m_RayLength, settings.lightingQualitySettings.RTRRayLength[level]); + CopySetting(ref m_ClampValue, settings.lightingQualitySettings.RTRClampValue[level]); + CopySetting(ref m_UpscaleRadius, settings.lightingQualitySettings.RTRUpScaleRadius[level]); + CopySetting(ref m_FullResolution, settings.lightingQualitySettings.RTRFullResolution[level]); + CopySetting(ref m_Denoise, settings.lightingQualitySettings.RTRDenoise[level]); + CopySetting(ref m_DenoiserRadius, settings.lightingQualitySettings.RTRDenoiserRadius[level]); + } + // SSR + else + CopySetting(ref m_RayMaxIterations, settings.lightingQualitySettings.SSRMaxRaySteps[level]); + } } } diff --git a/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs b/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs index a421e349ebe..7c8b178cd5f 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Lighting/Shadow/ContactShadowsEditor.cs @@ -21,8 +21,6 @@ class ContactShadowsEditor : VolumeComponentWithQualityEditor public override void OnEnable() { - base.OnEnable(); - var o = new PropertyFetcher(serializedObject); m_Enable = Unpack(o.Find(x => x.enable)); @@ -36,6 +34,8 @@ public override void OnEnable() m_Opacity = Unpack(o.Find(x => x.opacity)); m_Bias = Unpack(o.Find(x => x.rayBias)); m_Thickness = Unpack(o.Find(x => x.thicknessScale)); + + base.OnEnable(); } public override void OnInspectorGUI() @@ -57,11 +57,31 @@ public override void OnInspectorGUI() PropertyField(m_Thickness, EditorGUIUtility.TrTextContent("Thickness", "Controls the thickness of the objects found along the ray, essentially thickening the contact shadows.")); base.OnInspectorGUI(); - using (new EditorGUI.DisabledScope(!useCustomValue)) + + using (new QualityScope(this)) { PropertyField(m_SampleCount, EditorGUIUtility.TrTextContent("Sample Count", "Controls the number of samples HDRP uses for ray casting.")); } } } + public override QualitySettingsBlob SaveCustomQualitySettingsAsObject(QualitySettingsBlob settings = null) + { + if (settings == null) + settings = new QualitySettingsBlob(); + + settings.Save(m_SampleCount); + + return settings; + } + + public override void LoadSettingsFromObject(QualitySettingsBlob settings) + { + settings.TryLoad(ref m_SampleCount); + } + + public override void LoadSettingsFromQualityPreset(RenderPipelineSettings settings, int level) + { + CopySetting(ref m_SampleCount, settings.lightingQualitySettings.ContactShadowSampleCount[level]); + } } } diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/BloomEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/BloomEditor.cs index 12ff10becad..175dca79415 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/BloomEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/BloomEditor.cs @@ -24,8 +24,6 @@ sealed class BloomEditor : VolumeComponentWithQualityEditor public override void OnEnable() { - base.OnEnable(); - var o = new PropertyFetcher(serializedObject); m_Threshold = Unpack(o.Find(x => x.threshold)); @@ -39,6 +37,8 @@ public override void OnEnable() m_HighQualityFiltering = Unpack(o.Find("m_HighQualityFiltering")); m_Resolution = Unpack(o.Find("m_Resolution")); m_Anamorphic = Unpack(o.Find(x => x.anamorphic)); + + base.OnEnable(); } public override void OnInspectorGUI() @@ -58,14 +58,41 @@ public override void OnInspectorGUI() if (isInAdvancedMode) { EditorGUILayout.LabelField("Advanced Tweaks", EditorStyles.miniLabel); - using (new EditorGUI.DisabledScope(!useCustomValue)) + + using (new QualityScope(this)) { PropertyField(m_Resolution); PropertyField(m_HighQualityPrefiltering); PropertyField(m_HighQualityFiltering); } + PropertyField(m_Anamorphic); } } + public override QualitySettingsBlob SaveCustomQualitySettingsAsObject(QualitySettingsBlob settings = null) + { + if (settings == null) + settings = new QualitySettingsBlob(); + + settings.Save(m_Resolution); + settings.Save(m_HighQualityPrefiltering); + settings.Save(m_HighQualityFiltering); + + return settings; + } + + public override void LoadSettingsFromObject(QualitySettingsBlob settings) + { + settings.TryLoad(ref m_Resolution); + settings.TryLoad(ref m_HighQualityPrefiltering); + settings.TryLoad(ref m_HighQualityFiltering); + } + + public override void LoadSettingsFromQualityPreset(RenderPipelineSettings settings, int level) + { + CopySetting(ref m_Resolution, (int)settings.postProcessQualitySettings.BloomRes[level]); + CopySetting(ref m_HighQualityPrefiltering, settings.postProcessQualitySettings.BloomHighQualityPrefiltering[level]); + CopySetting(ref m_HighQualityFiltering, settings.postProcessQualitySettings.BloomHighQualityFiltering[level]); + } } } diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ChromaticAberrationEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ChromaticAberrationEditor.cs index 2c47a2493bf..82d10e6bfc1 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ChromaticAberrationEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ChromaticAberrationEditor.cs @@ -13,25 +13,46 @@ sealed class ChromaticAberrationEditor : VolumeComponentWithQualityEditor public override void OnEnable() { - base.OnEnable(); - var o = new PropertyFetcher(serializedObject); + m_SpectralLUT = Unpack(o.Find(x => x.spectralLut)); m_Intensity = Unpack(o.Find(x => x.intensity)); m_MaxSamples = Unpack(o.Find("m_MaxSamples")); + + base.OnEnable(); } public override void OnInspectorGUI() { - base.OnInspectorGUI(); - PropertyField(m_SpectralLUT); PropertyField(m_Intensity); - using (new EditorGUI.DisabledScope(!useCustomValue)) + + base.OnInspectorGUI(); + + using (new QualityScope(this)) { PropertyField(m_MaxSamples); } } + public override QualitySettingsBlob SaveCustomQualitySettingsAsObject(QualitySettingsBlob settings = null) + { + if (settings == null) + settings = new QualitySettingsBlob(); + + settings.Save(m_MaxSamples); + + return settings; + } + + public override void LoadSettingsFromObject(QualitySettingsBlob settings) + { + settings.TryLoad(ref m_MaxSamples); + } + + public override void LoadSettingsFromQualityPreset(RenderPipelineSettings settings, int level) + { + CopySetting(ref m_MaxSamples, settings.postProcessQualitySettings.ChromaticAberrationMaxSamples[level]); + } } } diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs index db30ba65be2..37721c3ef0b 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs @@ -50,8 +50,6 @@ static partial class Styles public override void OnEnable() { - base.OnEnable(); - var o = new PropertyFetcher(serializedObject); m_FocusMode = Unpack(o.Find(x => x.focusMode)); @@ -71,6 +69,8 @@ public override void OnEnable() m_HighQualityFiltering = Unpack(o.Find("m_HighQualityFiltering")); m_Resolution = Unpack(o.Find("m_Resolution")); m_PhysicallyBased = Unpack(o.Find("m_PhysicallyBased")); + + base.OnEnable(); } public override void OnInspectorGUI() @@ -81,71 +81,103 @@ public override void OnInspectorGUI() if (mode == (int)DepthOfFieldMode.Off) return; + using (new HDEditorUtils.IndentScope()) + { + // Draw the focus mode controls + DrawFocusSettings(mode); + } + + EditorGUILayout.Space(); + base.OnInspectorGUI(); - bool advanced = isInAdvancedMode; + using (new HDEditorUtils.IndentScope()) + { + // Draw the quality controls + GUI.enabled = GUI.enabled && base.overrideState; + DrawQualitySettings(); + GUI.enabled = true; + } + } + void DrawFocusSettings(int mode) + { if (mode == (int)DepthOfFieldMode.UsePhysicalCamera) { PropertyField(m_FocusDistance); - - if (advanced) - { - using (new EditorGUI.DisabledScope(!useCustomValue)) - { - EditorGUILayout.LabelField("Near Blur", EditorStyles.miniLabel); - PropertyField(m_NearSampleCount, Styles.k_NearSampleCount); - PropertyField(m_NearMaxBlur, Styles.k_NearMaxBlur); - - EditorGUILayout.LabelField("Far Blur", EditorStyles.miniLabel); - PropertyField(m_FarSampleCount, Styles.k_FarSampleCount); - PropertyField(m_FarMaxBlur, Styles.k_FarMaxBlur); - } - } } else if (mode == (int)DepthOfFieldMode.Manual) { - EditorGUILayout.Space(); - - EditorGUILayout.LabelField("Near Blur", EditorStyles.miniLabel); + EditorGUILayout.LabelField("Near Range", EditorStyles.miniLabel); PropertyField(m_NearFocusStart, Styles.k_NearFocusStart); PropertyField(m_NearFocusEnd, Styles.k_NearFocusEnd); - if (advanced) - { - using (new EditorGUI.DisabledScope(!useCustomValue)) - { - PropertyField(m_NearSampleCount, Styles.k_NearSampleCount); - PropertyField(m_NearMaxBlur, Styles.k_NearMaxBlur); - } - } - - EditorGUILayout.LabelField("Far Blur", EditorStyles.miniLabel); + EditorGUILayout.LabelField("Far Range", EditorStyles.miniLabel); PropertyField(m_FarFocusStart, Styles.k_FarFocusStart); PropertyField(m_FarFocusEnd, Styles.k_FarFocusEnd); - - if (advanced) - { - using (new EditorGUI.DisabledScope(!useCustomValue)) - { - PropertyField(m_FarSampleCount, Styles.k_FarSampleCount); - PropertyField(m_FarMaxBlur, Styles.k_FarMaxBlur); - } - } } + } - if (advanced) + void DrawQualitySettings() + { + using (new QualityScope(this)) { - using (new EditorGUI.DisabledScope(!useCustomValue)) + EditorGUILayout.LabelField("Near Blur", EditorStyles.miniLabel); + PropertyField(m_NearSampleCount, Styles.k_NearSampleCount); + PropertyField(m_NearMaxBlur, Styles.k_NearMaxBlur); + + EditorGUILayout.LabelField("Far Blur", EditorStyles.miniLabel); + PropertyField(m_FarSampleCount, Styles.k_FarSampleCount); + PropertyField(m_FarMaxBlur, Styles.k_FarMaxBlur); + + if (isInAdvancedMode) { EditorGUILayout.LabelField("Advanced Tweaks", EditorStyles.miniLabel); PropertyField(m_Resolution); PropertyField(m_HighQualityFiltering); - PropertyField(m_PhysicallyBased, Styles.k_PhysicallyBased); - if(m_PhysicallyBased.value.boolValue == true) + PropertyField(m_PhysicallyBased); + if (m_PhysicallyBased.value.boolValue == true) EditorGUILayout.HelpBox(Styles.InfoBox, MessageType.Info); } } } + + public override QualitySettingsBlob SaveCustomQualitySettingsAsObject(QualitySettingsBlob settings = null) + { + if (settings == null) + settings = new QualitySettingsBlob(); + + settings.Save(m_NearSampleCount); + settings.Save(m_NearMaxBlur); + settings.Save(m_FarSampleCount); + settings.Save(m_FarMaxBlur); + settings.Save(m_Resolution); + settings.Save(m_HighQualityFiltering); + settings.Save(m_PhysicallyBased); + + return settings; + } + + public override void LoadSettingsFromObject(QualitySettingsBlob settings) + { + settings.TryLoad(ref m_NearSampleCount); + settings.TryLoad(ref m_NearMaxBlur); + settings.TryLoad(ref m_FarSampleCount); + settings.TryLoad(ref m_FarMaxBlur); + settings.TryLoad(ref m_Resolution); + settings.TryLoad(ref m_HighQualityFiltering); + settings.TryLoad(ref m_PhysicallyBased); + } + + public override void LoadSettingsFromQualityPreset(RenderPipelineSettings settings, int level) + { + CopySetting(ref m_NearSampleCount, settings.postProcessQualitySettings.NearBlurSampleCount[level]); + CopySetting(ref m_NearMaxBlur, settings.postProcessQualitySettings.NearBlurMaxRadius[level]); + CopySetting(ref m_FarSampleCount, settings.postProcessQualitySettings.FarBlurSampleCount[level]); + CopySetting(ref m_FarMaxBlur, settings.postProcessQualitySettings.FarBlurMaxRadius[level]); + CopySetting(ref m_Resolution, (int)settings.postProcessQualitySettings.DoFResolution[level]); + CopySetting(ref m_HighQualityFiltering, settings.postProcessQualitySettings.DoFHighQualityFiltering[level]); + CopySetting(ref m_PhysicallyBased, settings.postProcessQualitySettings.DoFPhysicallyBased[level]); + } } } diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/MotionBlurEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/MotionBlurEditor.cs index 101b8f173ee..5add879a6d9 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/MotionBlurEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/MotionBlurEditor.cs @@ -14,7 +14,7 @@ sealed class MotionBlurEditor : VolumeComponentWithQualityEditor SerializedDataParameter m_MaxVelocityInPixels; SerializedDataParameter m_MinVelInPixels; - // Advanced properties + // Advanced properties SerializedDataParameter m_CameraRotClamp; SerializedDataParameter m_DepthCmpScale; SerializedDataParameter m_CameraMotionBlur; @@ -23,8 +23,6 @@ sealed class MotionBlurEditor : VolumeComponentWithQualityEditor public override void OnEnable() { - base.OnEnable(); - var o = new PropertyFetcher(serializedObject); m_Intensity = Unpack(o.Find(x => x.intensity)); @@ -34,6 +32,8 @@ public override void OnEnable() m_CameraRotClamp = Unpack(o.Find(x => x.cameraRotationVelocityClamp)); m_DepthCmpScale = Unpack(o.Find(x => x.depthComparisonExtent)); m_CameraMotionBlur = Unpack(o.Find(x => x.cameraMotionBlur)); + + base.OnEnable(); } public override void OnInspectorGUI() @@ -44,7 +44,7 @@ public override void OnInspectorGUI() base.OnInspectorGUI(); - using (new EditorGUI.DisabledScope(!useCustomValue)) + using (new QualityScope(this)) { PropertyField(m_SampleCount); } @@ -59,5 +59,24 @@ public override void OnInspectorGUI() PropertyField(m_CameraMotionBlur); } } + public override QualitySettingsBlob SaveCustomQualitySettingsAsObject(QualitySettingsBlob settings = null) + { + if (settings == null) + settings = new QualitySettingsBlob(); + + settings.Save(m_SampleCount); + + return settings; + } + + public override void LoadSettingsFromObject(QualitySettingsBlob settings) + { + settings.TryLoad(ref m_SampleCount); + } + + public override void LoadSettingsFromQualityPreset(RenderPipelineSettings settings, int level) + { + CopySetting(ref m_SampleCount, settings.postProcessQualitySettings.MotionBlurSampleCount[level]); + } } } diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDEditorUtils.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDEditorUtils.cs index 26db50d6c56..48538af38d3 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDEditorUtils.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDEditorUtils.cs @@ -242,7 +242,7 @@ internal static void DrawDecalLayerMask_Internal(Rect rect, GUIContent label, Se EditorGUI.EndProperty(); } - + /// /// Should be placed between BeginProperty / EndProperty @@ -293,6 +293,29 @@ internal static void HandlePrefixLabelWithIndent(Rect totalPosition, Rect labelP labelPosition.x += EditorGUI.indentLevel * 15; EditorGUI.HandlePrefixLabel(totalPosition, labelPosition, label); } + + /// + /// Like EditorGUI.IndentLevelScope but this one will also indent the override checkboxes. + /// + internal class IndentScope : GUI.Scope + { + public IndentScope(int offset = 16) + { + // When using EditorGUI.indentLevel++, the clicking on the checkboxes does not work properly due to some issues on the C++ side. + // This scope is a work-around for this issue. + GUILayout.BeginHorizontal(); + EditorGUILayout.Space(offset, false); + GUILayout.BeginVertical(); + EditorGUIUtility.labelWidth -= offset; + } + + protected override void CloseScope() + { + EditorGUIUtility.labelWidth = 0f; + GUILayout.EndVertical(); + GUILayout.EndHorizontal(); + } + } } internal static partial class SerializedPropertyExtension diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/GlobalIlluminationEditor.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/GlobalIlluminationEditor.cs index 2c7cb031ecd..f49e3b8484e 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/GlobalIlluminationEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Raytracing/GlobalIlluminationEditor.cs @@ -41,8 +41,6 @@ class GlobalIlluminatorEditor : VolumeComponentWithQualityEditor public override void OnEnable() { - base.OnEnable(); - var o = new PropertyFetcher(serializedObject); m_Enable = Unpack(o.Find(x => x.enable)); @@ -73,6 +71,8 @@ public override void OnEnable() m_HalfResolutionDenoiser = Unpack(o.Find(x => x.halfResolutionDenoiser)); m_DenoiserRadius = Unpack(o.Find(x => x.denoiserRadius)); m_SecondDenoiserPass = Unpack(o.Find(x => x.secondDenoiserPass)); + + base.OnEnable(); } static public readonly GUIContent k_RayLengthText = EditorGUIUtility.TrTextContent("Max Ray Length", "Controls the maximal length of global illumination rays. The higher this value is, the more expensive ray traced global illumination is."); @@ -81,12 +81,12 @@ public override void OnEnable() public void DenoiserGUI() { PropertyField(m_Denoise); + + using (new HDEditorUtils.IndentScope()) { - EditorGUI.indentLevel++; PropertyField(m_HalfResolutionDenoiser); PropertyField(m_DenoiserRadius); PropertyField(m_SecondDenoiserPass); - EditorGUI.indentLevel--; } } @@ -102,7 +102,7 @@ public override void OnInspectorGUI() } PropertyField(m_Enable); - + // If ray tracing is supported display the content of the volume component if (HDRenderPipeline.pipelineSupportsRayTracing) { @@ -112,91 +112,154 @@ public override void OnInspectorGUI() // Flag to track if the ray tracing parameters were displayed bool rayTracingSettingsDisplayed = false; - EditorGUI.indentLevel++; - if (HDRenderPipeline.pipelineSupportsRayTracing) + using (new HDEditorUtils.IndentScope()) { - if (m_RayTracing.overrideState.boolValue && m_RayTracing.value.boolValue) + if (HDRenderPipeline.pipelineSupportsRayTracing) { - rayTracingSettingsDisplayed = true; - PropertyField(m_LayerMask); - if (currentAsset.currentPlatformRenderPipelineSettings.supportedRayTracingMode == RenderPipelineSettings.SupportedRayTracingMode.Both) + if (m_RayTracing.overrideState.boolValue && m_RayTracing.value.boolValue) { - PropertyField(m_Mode); - EditorGUI.indentLevel++; - switch (m_Mode.value.GetEnumValue()) + rayTracingSettingsDisplayed = true; + PropertyField(m_LayerMask); + if (currentAsset.currentPlatformRenderPipelineSettings.supportedRayTracingMode == + RenderPipelineSettings.SupportedRayTracingMode.Both) { - case RayTracingMode.Performance: + PropertyField(m_Mode); + + using (new HDEditorUtils.IndentScope()) { - base.OnInspectorGUI(); // Quality Setting - EditorGUI.indentLevel++; - using (new EditorGUI.DisabledScope(!useCustomValue)) + switch (m_Mode.value.GetEnumValue()) { - PropertyField(m_RayLength, k_RayLengthText); - PropertyField(m_RayLength); - PropertyField(m_ClampValue); - PropertyField(m_FullResolution); - PropertyField(m_UpscaleRadius); - DenoiserGUI(); - } - EditorGUI.indentLevel--; + case RayTracingMode.Performance: + { + base.OnInspectorGUI(); // Quality Setting + using (new HDEditorUtils.IndentScope()) + using (new QualityScope(this)) + { + PropertyField(m_RayLength, k_RayLengthText); + PropertyField(m_RayLength); + PropertyField(m_ClampValue); + PropertyField(m_FullResolution); + PropertyField(m_UpscaleRadius); + DenoiserGUI(); + } + } + break; + case RayTracingMode.Quality: + { + PropertyField(m_RayLength, k_RayLengthText); + PropertyField(m_ClampValue); + PropertyField(m_SampleCount); + PropertyField(m_BounceCount); + DenoiserGUI(); + } + break; + } } - break; - case RayTracingMode.Quality: + } + else if (currentAsset.currentPlatformRenderPipelineSettings.supportedRayTracingMode == + RenderPipelineSettings.SupportedRayTracingMode.Quality) + { + PropertyField(m_RayLength, k_RayLengthText); + PropertyField(m_ClampValue); + PropertyField(m_SampleCount); + PropertyField(m_BounceCount); + DenoiserGUI(); + } + else + { + base.OnInspectorGUI(); // Quality Setting + EditorGUI.indentLevel++; + using (new QualityScope(this)) { PropertyField(m_RayLength, k_RayLengthText); + PropertyField(m_RayLength); PropertyField(m_ClampValue); - PropertyField(m_SampleCount); - PropertyField(m_BounceCount); + PropertyField(m_FullResolution); + PropertyField(m_UpscaleRadius); DenoiserGUI(); } - break; + + EditorGUI.indentLevel--; } - EditorGUI.indentLevel--; - } - else if (currentAsset.currentPlatformRenderPipelineSettings.supportedRayTracingMode == RenderPipelineSettings.SupportedRayTracingMode.Quality) - { - PropertyField(m_RayLength, k_RayLengthText); - PropertyField(m_ClampValue); - PropertyField(m_SampleCount); - PropertyField(m_BounceCount); - DenoiserGUI(); + } - else + } + + // If we dit not display the ray tracing parameter, we display the ssgi ones + if (!rayTracingSettingsDisplayed) + { + base.OnInspectorGUI(); // Quality Setting + + using (new HDEditorUtils.IndentScope()) + using (new QualityScope(this)) { - base.OnInspectorGUI(); // Quality Setting - EditorGUI.indentLevel++; - using (new EditorGUI.DisabledScope(!useCustomValue)) - { - PropertyField(m_RayLength, k_RayLengthText); - PropertyField(m_RayLength); - PropertyField(m_ClampValue); - PropertyField(m_FullResolution); - PropertyField(m_UpscaleRadius); - DenoiserGUI(); - } - EditorGUI.indentLevel--; + PropertyField(m_FullResolutionSS,EditorGUIUtility.TrTextContent("Full Resolution", "Enables full resolution mode.")); + PropertyField(m_RaySteps); + PropertyField(m_FilterRadius); } + PropertyField(m_DepthBufferThickness, k_DepthBufferThicknessText); } } + } + public override QualitySettingsBlob SaveCustomQualitySettingsAsObject(QualitySettingsBlob settings = null) + { + if (settings == null) + settings = new QualitySettingsBlob(); - // If we dit not display the ray tracing parameter, we display the ssgi ones - if (!rayTracingSettingsDisplayed) - { - base.OnInspectorGUI(); // Quality Setting - EditorGUI.indentLevel++; - using (new EditorGUI.DisabledScope(!useCustomValue)) - { - PropertyField(m_FullResolutionSS, EditorGUIUtility.TrTextContent("Full Resolution", "Enables full resolution mode.")); - PropertyField(m_RaySteps); - PropertyField(m_FilterRadius); - } - EditorGUI.indentLevel--; - PropertyField(m_DepthBufferThickness, k_DepthBufferThicknessText); - } + // RTGI + settings.Save(m_RayLength); + settings.Save(m_ClampValue); + settings.Save(m_FullResolution); + settings.Save(m_UpscaleRadius); + settings.Save(m_Denoise); + settings.Save(m_HalfResolutionDenoiser); + settings.Save(m_DenoiserRadius); + settings.Save(m_SecondDenoiserPass); + + // SSGI + settings.Save(m_FullResolutionSS); + settings.Save(m_RaySteps); + settings.Save(m_FilterRadius); + + return settings; + } + + public override void LoadSettingsFromObject(QualitySettingsBlob settings) + { + // RTGI + settings.TryLoad(ref m_RayLength); + settings.TryLoad(ref m_ClampValue); + settings.TryLoad(ref m_FullResolution); + settings.TryLoad(ref m_UpscaleRadius); + settings.TryLoad(ref m_Denoise); + settings.TryLoad(ref m_HalfResolutionDenoiser); + settings.TryLoad(ref m_DenoiserRadius); + settings.TryLoad(ref m_SecondDenoiserPass); + + // SSGI + settings.TryLoad(ref m_FullResolutionSS); + settings.TryLoad(ref m_RaySteps); + settings.TryLoad(ref m_FilterRadius); + } + + public override void LoadSettingsFromQualityPreset(RenderPipelineSettings settings, int level) + { + // RTGI + CopySetting(ref m_RayLength, settings.lightingQualitySettings.RTGIRayLength[level]); + CopySetting(ref m_ClampValue, settings.lightingQualitySettings.RTGIClampValue[level]); + CopySetting(ref m_FullResolution, settings.lightingQualitySettings.RTGIFullResolution[level]); + CopySetting(ref m_UpscaleRadius, settings.lightingQualitySettings.RTGIUpScaleRadius[level]); + CopySetting(ref m_Denoise, settings.lightingQualitySettings.RTGIDenoise[level]); + CopySetting(ref m_HalfResolutionDenoiser, settings.lightingQualitySettings.RTGIHalfResDenoise[level]); + CopySetting(ref m_DenoiserRadius, settings.lightingQualitySettings.RTGIDenoiserRadius[level]); + CopySetting(ref m_SecondDenoiserPass, settings.lightingQualitySettings.RTGISecondDenoise[level]); - EditorGUI.indentLevel--; + // SSGI + CopySetting(ref m_FullResolutionSS, settings.lightingQualitySettings.SSGIFullResolution[level]); + CopySetting(ref m_RaySteps, settings.lightingQualitySettings.SSGIRaySteps[level]); + CopySetting(ref m_FilterRadius, settings.lightingQualitySettings.SSGIFilterRadius[level]); } } } diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/VolumeComponentWithQualityEditor.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/VolumeComponentWithQualityEditor.cs index c790e1c7918..0c6eafaa9ed 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/VolumeComponentWithQualityEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/VolumeComponentWithQualityEditor.cs @@ -1,3 +1,7 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; namespace UnityEditor.Rendering.HighDefinition @@ -7,15 +11,238 @@ internal abstract class VolumeComponentWithQualityEditor : VolumeComponentEditor // Quality settings SerializedDataParameter m_QualitySetting; + /// + /// An opaque blob storing preset settings (used to remember what were the last custom settings that were used). + /// + internal class QualitySettingsBlob + { + private struct QualitySetting + { + public bool state; + public object value; + } + + Dictionary settings = new Dictionary(); + + public static bool IsEqual (QualitySettingsBlob left, QualitySettingsBlob right) + { + if (right == null && left == null) + { + return true; + } + + if ((right == null && left != null) || (right != null && left == null)) + { + return false; + } + + if (left.settings.Count != right.settings.Count) + { + return false; + } + + foreach (var key in left.settings.Keys) + { + if (!left.settings[key].Equals(right.settings[key])) + { + return false; + } + } + + return true; + } + + // TODO: Should be an override of GetHashCode (in core)? + int Hash(SerializedDataParameter setting) + { + int hash = setting.GetHashCode(); + + unchecked + { + hash = 23 * setting.value.GetHashCode(); + hash = 23 * setting.overrideState.GetHashCode(); + } + + return hash; + } + + // Save a setting to the quality blob. + public void Save(SerializedDataParameter setting) where T : struct + { + QualitySetting s; + s.state = setting.overrideState.boolValue; + s.value = setting.value.GetInline(); + + int key = Hash(setting); + + if (settings.ContainsKey(key)) + { + // If the setting exists, overwrite the value + settings[key] = s; + } + else + { + // Otherwise, cache a new setting + settings.Add(key, s); + } + } + + // Attempts to fill a quality setting with its custom value and override state. + public void TryLoad(ref SerializedDataParameter setting) where T : struct + { + if (settings.TryGetValue(Hash(setting), out QualitySetting s)) + { + setting.value.SetInline((T)s.value); + setting.overrideState.boolValue = s.state; + } + } + } + + /// + /// Scoped quality setting change checker. + /// + public struct QualityScope : IDisposable + { + VolumeComponentWithQualityEditor m_QualityComponent; + QualitySettingsBlob m_Settings; + + // Cache the quality setting + public QualityScope(VolumeComponentWithQualityEditor component) + { + m_QualityComponent = component; + m_Settings = m_QualityComponent.SaveCustomQualitySettingsAsObject(); + EditorGUI.BeginChangeCheck(); + } + + public void Dispose() + { + if (EditorGUI.EndChangeCheck()) + { + QualitySettingsBlob newSettings = m_QualityComponent?.SaveCustomQualitySettingsAsObject(); + + if (!QualitySettingsBlob.IsEqual(m_Settings, newSettings)) + m_QualityComponent?.QualitySettingsWereChanged(); + } + } + } + + // Note: Editors are refreshed on gui changes by the volume system, so any state that we want to store here needs to be a static (or in a serialized variable) + // We use ConditionalWeakTable instead of a Dictionary of InstanceIDs to get automatic clean-up of dead entries in the table + static ConditionalWeakTable s_CustomSettingsHistory = new ConditionalWeakTable(); + + static readonly int k_CustomQuality = ScalableSettingLevelParameter.LevelCount; + public override void OnEnable() { var o = new PropertyFetcher(serializedObject); m_QualitySetting = Unpack(o.Find(x => x.quality)); + + // Ensure we reflect presets in the pipeline asset, not the hardcoded defaults. + // Warning: base.OnEnable must be called after VolumeComponentWithQuality has unpacked SerializedData. + var pipeline = (HDRenderPipeline)RenderPipelineManager.currentPipeline; + if (pipeline != null) + { + serializedObject.Update(); + + if (m_QualitySetting.value.intValue < k_CustomQuality) + LoadSettingsFromQualityPreset(pipeline.currentPlatformRenderPipelineSettings, m_QualitySetting.value.intValue); + + serializedObject.ApplyModifiedProperties(); + } + } + + public override void OnInspectorGUI() + { + int prevQualityLevel = m_QualitySetting.value.intValue; + + EditorGUI.BeginChangeCheck(); + PropertyField(m_QualitySetting); + + // When a quality preset changes, we want to detect and reflect the settings in the UI. PropertyFields mirror the contents of one memory loccation, so + // the idea is that we copy the presets to that location. This logic is optional, if volume components don't override the helper functions at the end, + // they will continue to work, but the preset settings will not be reflected in the UI. + if (EditorGUI.EndChangeCheck()) + { + int newQualityLevel = m_QualitySetting.value.intValue; + + if (newQualityLevel == k_CustomQuality) + { + // If we have switched to custom quality from a preset, then load the last custom quality settings the user has used in this volume + if (prevQualityLevel != k_CustomQuality) + { + QualitySettingsBlob history = null; + s_CustomSettingsHistory.TryGetValue(serializedObject.targetObject, out history); + if (history != null) + { + LoadSettingsFromObject(history); + } + } + } + else + { + // If we are going to use a quality preset, then load the preset values so they are reflected in the UI + var pipeline = (HDRenderPipeline)RenderPipelineManager.currentPipeline; + if (pipeline != null) + { + // If we switch from a custom quality level, then save these values so we can re-use them if teh user switches back + if (prevQualityLevel == k_CustomQuality) + { + QualitySettingsBlob history = null; + s_CustomSettingsHistory.TryGetValue(serializedObject.targetObject, out history); + if (history != null) + { + SaveCustomQualitySettingsAsObject(history); + } + else + { + // Only keep track of custom settings for components that implement the new interface (and return not null) + history = SaveCustomQualitySettingsAsObject(); + if (history != null) + { + s_CustomSettingsHistory.Add(serializedObject.targetObject, history); + } + + } + } + LoadSettingsFromQualityPreset(pipeline.currentPlatformRenderPipelineSettings, newQualityLevel); + } + } + } + } + + protected bool useCustomValue => m_QualitySetting.value.intValue == k_CustomQuality; + protected bool overrideState => m_QualitySetting.overrideState.boolValue; + + /// + /// This utility can be used to copy a value into a volume component setting visible in the inspector. + /// + protected static void CopySetting(ref SerializedDataParameter setting, T value) where T : struct + { + setting.value.SetInline(value); + + // Force enable the override state, to indicate that these values are actually used. + setting.overrideState.boolValue = true; } - public override void OnInspectorGUI() =>PropertyField(m_QualitySetting); + /// + /// This should be called after the user manually edits a quality setting that appears in a preset. After calling this function, the quality preset will change to Custom. + /// + public void QualitySettingsWereChanged() { m_QualitySetting.value.intValue = k_CustomQuality; } + + /// + /// This function should be overriden by a volume component to load preset settings from RenderPipelineSettings + /// + public virtual void LoadSettingsFromQualityPreset(RenderPipelineSettings settings, int level) { } + + /// + /// This function should be overriden by a volume component to return an opaque object (binary blob) with the custom quality settings currently in use. + /// + public virtual QualitySettingsBlob SaveCustomQualitySettingsAsObject(QualitySettingsBlob history = null) { return null; } - protected bool useCustomValue => m_QualitySetting.value.intValue == ScalableSettingLevelParameter.LevelCount; + /// + /// This function should be overriden by a volume component to load a custom preset setting from an opaque binary blob (as returned from SaveCustomQualitySettingsAsObject) + /// + public virtual void LoadSettingsFromObject(QualitySettingsBlob settings) { } } } diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Deferred/RaytracingGBuffer.raytrace b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Deferred/RaytracingGBuffer.raytrace index 47d3f61cea7..b964e85ffe2 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Deferred/RaytracingGBuffer.raytrace +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Deferred/RaytracingGBuffer.raytrace @@ -32,7 +32,7 @@ // Raytracing includes #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Deferred/RaytracingIntersectonGBuffer.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingSampling.hlsl" -#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingCommon.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RayTracing/Shaders/Common/AtmosphericScatteringRayTracing.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/RayCountManager.cs.hlsl" @@ -85,7 +85,7 @@ void RayGenGBuffer() // Read the depth value float depthValue = _DepthTexture[COORD_TEXTURE2D_X(currentPixelCoord)].x; - // If this is the background, or UnL is null or this pixel has been flagged as invalid, no + // If this is the background, or UnL is null or this pixel has been flagged as invalid, no if (depthValue == UNITY_RAW_FAR_CLIP_VALUE || _RaytracingDirectionBuffer[COORD_TEXTURE2D_X(currentPixelCoord)].w < 0.0) { _RaytracingDistanceBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = _RaytracingRayMaxLength; @@ -132,7 +132,7 @@ void RayGenGBuffer() // Evaluate the ray visibility term and PDF TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, _RayTracingLayerMask, 0, 1, 0, rayDescriptor, rayIntersection); - // Output the gbuffer + // Output the gbuffer _GBufferTexture0RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(LinearToSRGB(rayIntersection.gbuffer0.xyz), rayIntersection.gbuffer0.w); _GBufferTexture1RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(rayIntersection.gbuffer1); _GBufferTexture2RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(rayIntersection.gbuffer2); @@ -180,7 +180,7 @@ void RayGenGBufferBinned() // Read the depth value float depthValue = _DepthTexture[COORD_TEXTURE2D_X(currentPixelCoord)].x; - // If this is the background, or UnL is null or this pixel has been flagged as invalid, no + // If this is the background, or UnL is null or this pixel has been flagged as invalid, no if (depthValue == UNITY_RAW_FAR_CLIP_VALUE || _RaytracingDirectionBuffer[COORD_TEXTURE2D_X(currentPixelCoord)].w < 0.0) { _RaytracingDistanceBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = _RaytracingRayMaxLength; @@ -204,7 +204,7 @@ void RayGenGBufferBinned() uint3 counterIdx = uint3(currentPixelCoord, INDEX_TEXTURE2D_ARRAY_X(_RayCountType)); _RayCountTexture[counterIdx] = _RayCountTexture[counterIdx] + 1; } - + // Read the ray distance float3 rayDirection = _RaytracingDirectionBuffer[COORD_TEXTURE2D_X(currentPixelCoord)].xyz; @@ -228,10 +228,10 @@ void RayGenGBufferBinned() // Evaluate the ray visibility term and PDF TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, _RayTracingLayerMask, 0, 1, 0, rayDescriptor, rayIntersection); - // Output the gbuffer + // Output the gbuffer _GBufferTexture0RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(LinearToSRGB(rayIntersection.gbuffer0.xyz), rayIntersection.gbuffer0.w); _GBufferTexture1RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(rayIntersection.gbuffer1); _GBufferTexture2RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(rayIntersection.gbuffer2); _GBufferTexture3RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(rayIntersection.gbuffer3); _RaytracingDistanceBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = rayIntersection.t; -} \ No newline at end of file +} diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/IndirectDiffuse/RaytracingIndirectDiffuse.compute b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/IndirectDiffuse/RaytracingIndirectDiffuse.compute index 205e79c11f2..0195501a56c 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/IndirectDiffuse/RaytracingIndirectDiffuse.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/IndirectDiffuse/RaytracingIndirectDiffuse.compute @@ -20,7 +20,7 @@ // Raytracing includes #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingSampling.hlsl" -#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingCommon.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" // Tile size of this compute #define RAYTRACING_INDIRECT_DIFFUSE_TILE_SIZE 8 @@ -55,7 +55,7 @@ void RaytracingIndirectDiffuseHalfRes(uint3 dispatchThreadId : SV_DispatchThread if (depthValue == UNITY_RAW_FAR_CLIP_VALUE) return; - // Convert this to a world space position + // Convert this to a world space position PositionInputs posInput = GetPositionInput(sourceCoord, _ScreenSize.zw, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0); // Compute the view in world space const float3 viewWS = GetWorldSpaceNormalizeViewDir(posInput.positionWS); @@ -207,7 +207,7 @@ void INDIRECT_DIFFUSE_INTEGRATION_UPSCALE(uint3 dispatchThreadId : SV_DispatchTh // Fetch the Depth float sampleDepth = LOAD_TEXTURE2D_X(_DepthTexture, actualSourceCoord).x; - + // If this the background, it should not be used as a valid sample if(sampleDepth == UNITY_RAW_FAR_CLIP_VALUE) continue; diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/IndirectDiffuse/RaytracingIndirectDiffuse.raytrace b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/IndirectDiffuse/RaytracingIndirectDiffuse.raytrace index 11909718d51..f2c91a74615 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/IndirectDiffuse/RaytracingIndirectDiffuse.raytrace +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/IndirectDiffuse/RaytracingIndirectDiffuse.raytrace @@ -20,7 +20,7 @@ #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingIntersection.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingSampling.hlsl" -#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingCommon.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/ScreenSpaceLighting.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RayTracing/Shaders/Common/AtmosphericScatteringRayTracing.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/RayCountManager.cs.hlsl" diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingReflectionFilter.compute b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingReflectionFilter.compute index 773f951b89e..79641f2185d 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingReflectionFilter.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingReflectionFilter.compute @@ -13,7 +13,7 @@ // Raytracing Includes #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/OnlineVariance.hlsl" -#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingCommon.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/ScreenSpaceLighting.hlsl" diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Reflections/RaytracingReflections.compute b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Reflections/RaytracingReflections.compute index 2d2b687c1b4..ecf3caa573c 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Reflections/RaytracingReflections.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Reflections/RaytracingReflections.compute @@ -21,7 +21,7 @@ // Raytracing includes #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingSampling.hlsl" -#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingCommon.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" // Tile size of this compute #define RAYTRACING_REFLECTIONS_TILE_SIZE 8 @@ -68,7 +68,7 @@ void RaytracingReflectionsHalfRes(uint3 dispatchThreadId : SV_DispatchThreadID, if ((stencilValue & _SsrStencilBit) == 0) return; - // Convert this to a world space position + // Convert this to a world space position PositionInputs posInput = GetPositionInput(sourceCoord, _ScreenSize.zw, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0); float distanceToCamera = length(posInput.positionWS); // Compute the incident vector on the surfaces @@ -161,7 +161,7 @@ void RaytracingReflectionsTransparentHalfRes(uint3 dispatchThreadId : SV_Dispatc if ((stencilValue & _SsrStencilBit) == 0) return; - // Convert this to a world space position + // Convert this to a world space position PositionInputs posInput = GetPositionInput(sourceCoord, _ScreenSize.zw, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0); float distanceToCamera = length(posInput.positionWS); // Compute the incident vector on the surfaces @@ -218,7 +218,7 @@ void RaytracingReflectionsFullRes(uint3 dispatchThreadId : SV_DispatchThreadID, // Override the roughness by the clearcoat value of this is a clear coat float4 coatMask = LOAD_TEXTURE2D_X(_SsrClearCoatMaskTexture, currentCoord); normalData.perceptualRoughness = HasClearCoatMask(coatMask) ? CLEAR_COAT_PERCEPTUAL_ROUGHNESS : normalData.perceptualRoughness; - + // Create the local ortho basis float3x3 localToWorld = GetLocalFrame(normalData.normalWS); diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Reflections/RaytracingReflections.raytrace b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Reflections/RaytracingReflections.raytrace index 88b4f27db08..0e1e2835f1a 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Reflections/RaytracingReflections.raytrace +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Reflections/RaytracingReflections.raytrace @@ -20,7 +20,7 @@ #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingIntersection.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingSampling.hlsl" -#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingCommon.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/ScreenSpaceLighting.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RayTracing/Shaders/Common/AtmosphericScatteringRayTracing.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/RayCountManager.cs.hlsl" @@ -220,7 +220,7 @@ void RayGenIntegrationTransparent() // Compute the reflected direction float3 reflectionDir = reflect(-viewWS, normalData.normalWS); - + // Make sure the new ray is taken into account in the ray counters if (_RayCountEnabled > 0) {