diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index 4a9051920f4..93b62e43bad 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -139,6 +139,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added more custom pass API functions, mainly to render objects from another camera. - Added support for transparent Unlit in path tracing. - Added a minimal lit used for RTGI in peformance mode. +- Added procedural metering mask that can follow an object ### Fixed - Fix when rescale probe all direction below zero (1219246) diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ExposureEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ExposureEditor.cs index e5883dcc709..14fc781f072 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ExposureEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ExposureEditor.cs @@ -26,6 +26,13 @@ sealed class ExposureEditor : VolumeComponentEditor SerializedDataParameter m_HistogramPercentages; SerializedDataParameter m_HistogramCurveRemapping; + SerializedDataParameter m_CenterAroundTarget; + SerializedDataParameter m_ProceduralCenter; + SerializedDataParameter m_ProceduralRadii; + SerializedDataParameter m_ProceduralSoftness; + SerializedDataParameter m_ProceduralMinIntensity; + SerializedDataParameter m_ProceduralMaxIntensity; + SerializedDataParameter m_TargetMidGray; static readonly string[] s_MidGrayNames = { "Grey 12.5%", "Grey 14.0%", "Grey 18.0%" }; @@ -54,6 +61,14 @@ public override void OnEnable() m_HistogramPercentages = Unpack(o.Find(x => x.histogramPercentages)); m_HistogramCurveRemapping = Unpack(o.Find(x => x.histogramUseCurveRemapping)); + + m_CenterAroundTarget = Unpack(o.Find(x => x.centerAroundExposureTarget)); + m_ProceduralCenter = Unpack(o.Find(x => x.proceduralCenter)); + m_ProceduralRadii = Unpack(o.Find(x => x.proceduralRadii)); + m_ProceduralSoftness = Unpack(o.Find(x => x.proceduralSoftness)); + m_ProceduralMinIntensity = Unpack(o.Find(x => x.maskMinIntensity)); + m_ProceduralMaxIntensity = Unpack(o.Find(x => x.maskMaxIntensity)); + m_TargetMidGray = Unpack(o.Find(x => x.targetMidGray)); } @@ -79,6 +94,42 @@ public override void OnInspectorGUI() if(m_MeteringMode.value.intValue == (int)MeteringMode.MaskWeighted) PropertyField(m_WeightTextureMask); + if (m_MeteringMode.value.intValue == (int) MeteringMode.ProceduralMask) + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Procedural Mask", EditorStyles.miniLabel); + + + PropertyField(m_CenterAroundTarget); + + var centerLabel = EditorGUIUtility.TrTextContent("Center", "Sets the center of the procedural metering mask ([0,0] being bottom left of the screen and [1,1] top right of the screen)"); + var centerValue = m_ProceduralCenter.value.vector2Value; + + if (m_CenterAroundTarget.value.boolValue) + { + centerLabel = EditorGUIUtility.TrTextContent("Offset", "Sets an offset to the mask center"); + m_ProceduralCenter.value.vector2Value = new Vector2(Mathf.Clamp(centerValue.x, -0.5f, 0.5f), Mathf.Clamp(centerValue.y, -0.5f, 0.5f)); + } + else + { + m_ProceduralCenter.value.vector2Value = new Vector2(Mathf.Clamp01(centerValue.x), Mathf.Clamp01(centerValue.y)); + } + + PropertyField(m_ProceduralCenter, centerLabel); + var radiiValue = m_ProceduralRadii.value.vector2Value; + m_ProceduralRadii.value.vector2Value = new Vector2(Mathf.Clamp01(radiiValue.x), Mathf.Clamp01(radiiValue.y)); + PropertyField(m_ProceduralRadii, EditorGUIUtility.TrTextContent("Radii", "Sets the radii of the procedural mask, in terms of fraction of the screen (i.e. 0.5 means a radius that stretch half of the screen).")); + PropertyField(m_ProceduralSoftness, EditorGUIUtility.TrTextContent("Softness", "Sets the softness of the mask, the higher the value the less influence is given to pixels at the edge of the mask")); + + if (isInAdvancedMode) + { + PropertyField(m_ProceduralMinIntensity); + PropertyField(m_ProceduralMaxIntensity); + } + + EditorGUILayout.Space(); + } + // Temporary hiding the field since we don't support anything but color buffer for now. //PropertyField(m_LuminanceSource); diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Camera/HDCameraUI.Drawers.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Camera/HDCameraUI.Drawers.cs index c895f09020c..824406229f7 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Camera/HDCameraUI.Drawers.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Camera/HDCameraUI.Drawers.cs @@ -116,7 +116,8 @@ static HDCameraUI() Drawer_FieldVolumeLayerMask, Drawer_FieldVolumeAnchorOverride, (p, owner) => EditorGUILayout.PropertyField(p.probeLayerMask, probeLayerMaskContent), - Drawer_FieldOcclusionCulling + Drawer_FieldOcclusionCulling, + Drawer_FieldExposureTarget ), CED.space, CED.Group( @@ -562,6 +563,11 @@ static void Drawer_FieldRenderTarget(SerializedHDCamera p, Editor owner) } } + static void Drawer_FieldExposureTarget(SerializedHDCamera p, Editor owner) + { + EditorGUILayout.PropertyField(p.exposureTarget, exposureTargetContent); + } + static void Drawer_FieldOcclusionCulling(SerializedHDCamera p, Editor owner) { EditorGUILayout.PropertyField(p.baseCameraSettings.occlusionCulling, occlusionCullingContent); diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Camera/HDCameraUI.Skin.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Camera/HDCameraUI.Skin.cs index 8d49a2a1568..d9df6d4c688 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Camera/HDCameraUI.Skin.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Camera/HDCameraUI.Skin.cs @@ -20,6 +20,8 @@ static partial class HDCameraUI static readonly GUIContent volumeAnchorOverrideContent = EditorGUIUtility.TrTextContent("Volume Anchor Override"); static readonly GUIContent occlusionCullingContent = EditorGUIUtility.TrTextContent("Occlusion Culling"); + static readonly GUIContent exposureTargetContent = EditorGUIUtility.TrTextContent("Exposure Target", "The object used as a target for centering the Exposure's Procedural Mask metering mode when target object option is set (See Exposure Volume Component)."); + static readonly GUIContent projectionContent = EditorGUIUtility.TrTextContent("Projection", "How the Camera renders perspective.\n\nChoose Perspective to render objects with perspective.\n\nChoose Orthographic to render objects uniformly, with no sense of perspective."); static readonly GUIContent sizeContent = EditorGUIUtility.TrTextContent("Size"); static readonly GUIContent fieldOfViewContent = EditorGUIUtility.TrTextContent("Field of View", "The height of the Camera’s view angle, measured in degrees along the local Y axis."); diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Camera/SerializedHDCamera.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Camera/SerializedHDCamera.cs index 415bc740a51..1ed00c4411c 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Camera/SerializedHDCamera.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Camera/SerializedHDCamera.cs @@ -18,6 +18,7 @@ class SerializedHDCamera public SerializedProperty curvature; public SerializedProperty barrelClipping; public SerializedProperty anamorphism; + public SerializedProperty exposureTarget; public SerializedProperty antialiasing; public SerializedProperty SMAAQuality; @@ -71,6 +72,8 @@ public SerializedHDCamera(SerializedObject serializedObject) barrelClipping = serializedAdditionalDataObject.FindProperty("physicalParameters.m_BarrelClipping"); anamorphism = serializedAdditionalDataObject.FindProperty("physicalParameters.m_Anamorphism"); + exposureTarget = serializedAdditionalDataObject.Find((HDAdditionalCameraData d) => d.exposureTarget); + antialiasing = serializedAdditionalDataObject.Find((HDAdditionalCameraData d) => d.antialiasing); SMAAQuality = serializedAdditionalDataObject.Find((HDAdditionalCameraData d) => d.SMAAQuality); taaSharpenStrength = serializedAdditionalDataObject.Find((HDAdditionalCameraData d) => d.taaSharpenStrength); diff --git a/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugExposure.shader b/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugExposure.shader index 06eba4fbb4d..7dab784c729 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugExposure.shader +++ b/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugExposure.shader @@ -461,7 +461,6 @@ Shader "Hidden/HDRP/DebugExposure" UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); float2 uv = input.texcoord.xy; float3 color = SAMPLE_TEXTURE2D_X_LOD(_DebugFullScreenTexture, s_linear_clamp_sampler, uv, 0.0).xyz; - float weight = WeightSample(input.positionCS.xy, _ScreenSize.xy); float pipFraction = 0.33f; uint borderSize = 3; @@ -471,7 +470,8 @@ Shader "Hidden/HDRP/DebugExposure" { float2 scaledUV = uv / pipFraction; float3 pipColor = SAMPLE_TEXTURE2D_X_LOD(_SourceTexture, s_linear_clamp_sampler, scaledUV, 0.0).xyz; - float weight = WeightSample(scaledUV.xy * _ScreenSize.xy / _RTHandleScale.xy, _ScreenSize.xy); + float luminance = SampleLuminance(scaledUV); + float weight = WeightSample(scaledUV.xy * _ScreenSize.xy / _RTHandleScale.xy, _ScreenSize.xy, luminance); return pipColor * weight; } @@ -574,7 +574,6 @@ Shader "Hidden/HDRP/DebugExposure" float2 uv = input.texcoord.xy; float3 color = SAMPLE_TEXTURE2D_X_LOD(_DebugFullScreenTexture, s_linear_clamp_sampler, uv, 0.0).xyz; - float weight = WeightSample(input.positionCS.xy, _ScreenSize.xy); float3 outputColor = color; @@ -616,7 +615,7 @@ Shader "Hidden/HDRP/DebugExposure" uint2 unormCoord = input.positionCS.xy; float3 textColor = float3(0.5f, 0.5f, 0.5f); - int2 textLocation = int2(DEBUG_FONT_TEXT_WIDTH * 0.5, DEBUG_FONT_TEXT_WIDTH * 0.5 + histFrameHeight * (_ScreenSize.y / _RTHandleScale.y)); + uint2 textLocation = uint2(DEBUG_FONT_TEXT_WIDTH * 0.5, DEBUG_FONT_TEXT_WIDTH * 0.5 + histFrameHeight * (_ScreenSize.y / _RTHandleScale.y)); DrawCharacter('C', textColor, unormCoord, textLocation, outputColor.rgb, 1, 10); DrawCharacter('u', textColor, unormCoord, textLocation, outputColor.rgb, 1, 7); DrawCharacter('r', textColor, unormCoord, textLocation, outputColor.rgb, 1, 7); @@ -636,7 +635,7 @@ Shader "Hidden/HDRP/DebugExposure" DrawCharacter(':', textColor, unormCoord, textLocation, outputColor.rgb, 1, 7); textLocation.x += DEBUG_FONT_TEXT_WIDTH * 0.5f; DrawFloatExplicitPrecision(currExposure, textColor, unormCoord, 3, textLocation, outputColor.rgb); - textLocation = int2(DEBUG_FONT_TEXT_WIDTH * 0.5, textLocation.y + DEBUG_FONT_TEXT_WIDTH); + textLocation = uint2(DEBUG_FONT_TEXT_WIDTH * 0.5, textLocation.y + DEBUG_FONT_TEXT_WIDTH); DrawCharacter('T', textColor, unormCoord, textLocation, outputColor.rgb, 1, 10); DrawCharacter('a', textColor, unormCoord, textLocation, outputColor.rgb, 1, 7); DrawCharacter('r', textColor, unormCoord, textLocation, outputColor.rgb, 1, 7); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Exposure.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Exposure.cs index 6ef1b78c581..fdef62f313f 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Exposure.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Exposure.cs @@ -112,6 +112,37 @@ public sealed class Exposure : VolumeComponent, IPostProcessComponent [Tooltip("Sets the desired Mid gray level used by the auto exposure (i.e. to what grey value the auto exposure system maps the average scene luminance).")] public TargetMidGrayParameter targetMidGray = new TargetMidGrayParameter(TargetMidGray.Grey125); + /// + /// Sets whether the procedural metering mask is centered around the exposure target (to be set on the camera) + /// + [Tooltip("Sets whether histogram exposure mode will remap the computed exposure with a curve remapping (akin to Curve Remapping mode).")] + public BoolParameter centerAroundExposureTarget = new BoolParameter(false); + + /// + /// Sets the center of the procedural metering mask ([0,0] being bottom left of the screen and [1,1] top right of the screen) + /// + public NoInterpVector2Parameter proceduralCenter = new NoInterpVector2Parameter(new Vector2(0.5f, 0.5f)); + /// + /// Sets the radii of the procedural mask, in terms of fraction of the screen (i.e. 0.5 means a radius that stretch half of the screen). + /// + public NoInterpVector2Parameter proceduralRadii = new NoInterpVector2Parameter(new Vector2(0.15f, 0.15f)); + /// + /// All pixels below this threshold (in EV100 units) will be assigned a weight of 0 in the metering mask. + /// + [Tooltip("All pixels below this threshold (in EV100 units) will be assigned a weight of 0 in the metering mask.")] + public FloatParameter maskMinIntensity = new FloatParameter(-30.0f); + /// + /// All pixels above this threshold (in EV100 units) will be assigned a weight of 0 in the metering mask. + /// + [Tooltip("All pixels above this threshold (in EV100 units) will be assigned a weight of 0 in the metering mask.")] + public FloatParameter maskMaxIntensity = new FloatParameter(30.0f); + + /// + /// Sets the softness of the mask, the higher the value the less influence is given to pixels at the edge of the mask. + /// + public NoInterpMinFloatParameter proceduralSoftness = new NoInterpMinFloatParameter(0.5f, 0.0f); + + /// /// Tells if the effect needs to be rendered or not. /// @@ -185,7 +216,13 @@ public enum MeteringMode /// the exposure. The weighting is specified by the texture provided by the user. Note that if /// no texture is provided, then this metering mode is equivalent to Average. /// - MaskWeighted + MaskWeighted, + + /// + /// Create a weight mask centered around the specified UV and with the desired parameters. + /// + ProceduralMask, + } diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs index ff2ba171251..624c9db68cd 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs @@ -924,6 +924,42 @@ internal ComputeBuffer GetHistogramBuffer() return m_HistogramBuffer; } + internal void ComputeProceduralMeteringParams(HDCamera camera, out Vector4 proceduralParams1, out Vector4 proceduralParams2) + { + Vector2 proceduralCenter = m_Exposure.proceduralCenter.value; + if (camera.exposureTarget != null && m_Exposure.centerAroundExposureTarget.value) + { + var transform = camera.exposureTarget.transform; + // Transform in screen space + Vector3 targetLocation = transform.position; + if (ShaderConfig.s_CameraRelativeRendering != 0) + { + targetLocation -= camera.camera.transform.position; + } + var ndcLoc = camera.mainViewConstants.viewProjMatrix * (targetLocation); + ndcLoc.x /= ndcLoc.w; + ndcLoc.y /= ndcLoc.w; + + Vector2 targetUV = new Vector2(ndcLoc.x, ndcLoc.y) * 0.5f + new Vector2(0.5f, 0.5f); + targetUV.y = 1.0f - targetUV.y; + + proceduralCenter += targetUV; + } + + proceduralCenter.x = Mathf.Clamp01(proceduralCenter.x); + proceduralCenter.y = Mathf.Clamp01(proceduralCenter.y); + + proceduralCenter.x *= camera.actualWidth; + proceduralCenter.y *= camera.actualHeight; + + float screenDiagonal = 0.5f * (camera.actualHeight + camera.actualWidth); + + proceduralParams1 = new Vector4(proceduralCenter.x, proceduralCenter.y, + m_Exposure.proceduralRadii.value.x * screenDiagonal, + m_Exposure.proceduralRadii.value.y * screenDiagonal); + + proceduralParams2 = new Vector4(1.0f / m_Exposure.proceduralSoftness.value, LightUtils.ConvertEvToLuminance(m_Exposure.maskMinIntensity.value), LightUtils.ConvertEvToLuminance(m_Exposure.maskMaxIntensity.value), 0.0f); + } void DoFixedExposure(CommandBuffer cmd, HDCamera camera) { var cs = m_Resources.shaders.exposureCS; @@ -1050,6 +1086,11 @@ void DoDynamicExposure(CommandBuffer cmd, HDCamera camera, RTHandle colorBuffer) { cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._ExposureWeightMask, Texture2D.whiteTexture); } + + ComputeProceduralMeteringParams(camera, out Vector4 proceduralParams1, out Vector4 proceduralParams2); + cmd.SetComputeVectorParam(cs, HDShaderIDs._ProceduralMaskParams, proceduralParams1); + cmd.SetComputeVectorParam(cs, HDShaderIDs._ProceduralMaskParams2, proceduralParams2); + cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputTexture, m_TempTexture1024); cmd.DispatchCompute(cs, kernel, 1024 / 8, 1024 / 8, 1); @@ -1099,6 +1140,10 @@ void DoHistogramBasedExposure(CommandBuffer cmd, HDCamera camera, RTHandle sourc float histBias = -m_Exposure.limitMin.value * histScale; Vector4 histogramParams = new Vector4(histScale, histBias, histogramFraction.x, histogramFraction.y); + ComputeProceduralMeteringParams(camera, out Vector4 proceduralParams1, out Vector4 proceduralParams2); + cmd.SetComputeVectorParam(cs, HDShaderIDs._ProceduralMaskParams, proceduralParams1); + cmd.SetComputeVectorParam(cs, HDShaderIDs._ProceduralMaskParams2, proceduralParams2); + ValidateComputeBuffer(ref m_HistogramBuffer, k_HistogramBins, sizeof(uint)); m_HistogramBuffer.SetData(m_EmptyHistogram); // Clear the histogram cmd.SetComputeVectorParam(cs, HDShaderIDs._HistogramExposureParams, histogramParams); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/Exposure.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/Exposure.compute index 1624800459b..88e7a7490ce 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/Exposure.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/Exposure.compute @@ -12,6 +12,7 @@ TEXTURE2D(_InputTexture); #define PREPASS_TEX_SIZE 1024.0 #define PREPASS_TEX_HALF_SIZE 512.0 +//#pragma enable_d3d11_debug_symbols // // Fixed exposure @@ -51,7 +52,7 @@ void KPrePass(uint2 dispatchThreadId : SV_DispatchThreadID) float2 uv = ClampAndScaleUVForBilinear(posInputs.positionNDC); float luma = SampleLuminance(uv); - float weight = WeightSample(dispatchThreadId, PREPASS_TEX_SIZE.xx); + float weight = WeightSample(dispatchThreadId, PREPASS_TEX_SIZE.xx, luma); float logLuma = ComputeEV100FromAvgLuminance(max(luma, 1e-4), MeterCalibrationConstant); _OutputTexture[posInputs.positionSS] = float2(logLuma, weight); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/ExposureCommon.hlsl b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/ExposureCommon.hlsl index 6d80756323c..c7e3cf6e5f8 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/ExposureCommon.hlsl +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/ExposureCommon.hlsl @@ -16,6 +16,8 @@ TEXTURE2D(_ExposureCurveTexture); CBUFFER_START(cb) float4 _ExposureParams; float4 _ExposureParams2; +float4 _ProceduralMaskParams; +float4 _ProceduralMaskParams2; float4 _HistogramExposureParams; float4 _AdaptationParams; uint4 _Variants; @@ -39,12 +41,18 @@ CBUFFER_END #define ParamAdaptationMode _Variants.z #define ParamEvaluateMode _Variants.w +#define ProceduralCenter _ProceduralMaskParams.xy // Transformed in screen space on CPU +#define ProceduralRadii _ProceduralMaskParams.zw +#define ProceduralSoftness _ProceduralMaskParams2.x +#define ProceduralMin _ProceduralMaskParams2.y +#define ProceduralMax _ProceduralMaskParams2.z + float GetPreviousExposureEV100() { return _PreviousExposureTexture[uint2(0u, 0u)].y; } -float WeightSample(uint2 pixel, float2 sourceSize) +float WeightSample(uint2 pixel, float2 sourceSize, float luminance) { UNITY_BRANCH switch (ParamMeteringMode) @@ -70,7 +78,15 @@ float WeightSample(uint2 pixel, float2 sourceSize) // Mask weigthing return SAMPLE_TEXTURE2D_LOD(_ExposureWeightMask, s_linear_clamp_sampler, pixel * rcp(sourceSize), 0.0).x; } + case 4u: + { + // Procedural. + float radius = max(ProceduralRadii.x, ProceduralRadii.y); + float2 ellipseScale = float2(radius / ProceduralRadii.x, radius / ProceduralRadii.y); + float dist = length(ProceduralCenter * ellipseScale - pixel * ellipseScale); + return (luminance > ProceduralMin && luminance < ProceduralMax) ? saturate(1.0 - pow((dist / radius), ProceduralSoftness)) : 0.0f; + } default: { // Global average diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/HistogramExposure.compute b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/HistogramExposure.compute index 5547b0d17a3..8f12e2925ef 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/HistogramExposure.compute +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/HistogramExposure.compute @@ -44,7 +44,7 @@ void KHistogramGen(uint groupIndex : SV_GroupIndex, { float2 uv = ClampAndScaleUVForBilinear((fullResCoords + 0.5) * _ScreenSize.zw); float luminance = SampleLuminance(uv); - float weight = WeightSample(fullResCoords, _ScreenSize.xy); + float weight = WeightSample(fullResCoords, _ScreenSize.xy, luminance); uint bin = GetHistogramBinLocation(luminance); InterlockedAdd(gs_localHistogram[bin], PackWeight(weight)); diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDAdditionalCameraData.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDAdditionalCameraData.cs index 74c7adcfcfb..a9667339265 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDAdditionalCameraData.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDAdditionalCameraData.cs @@ -338,6 +338,9 @@ public enum TAAQualityLevel /// RequestAccessDelegate used to request access to various buffers of this camera. public event RequestAccessDelegate requestGraphicsBuffer; + /// The object used as a target for centering the Exposure's Procedural Mask metering mode when target object option is set (See Exposure Volume Component). + public GameObject exposureTarget = null; + internal float probeCustomFixedExposure = 1.0f; [SerializeField, FormerlySerializedAs("renderingPathCustomFrameSettings")] diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs index 95b53beba04..0952898dc03 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Camera/HDCamera.cs @@ -291,6 +291,19 @@ internal HDAdditionalCameraData.FlipYMode flipYMode } } + internal GameObject exposureTarget + { + get + { + if (m_AdditionalCameraData != null) + { + return m_AdditionalCameraData.exposureTarget; + } + + return null; + } + } + // This value will always be correct for the current camera, no need to check for // game view / scene view / preview in the editor, it's handled automatically internal AntialiasingMode antialiasing { get; private set; } = AntialiasingMode.None; diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs index 3595ec4e161..63226f43801 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -4780,6 +4780,8 @@ static void RenderExposureDebug(in DebugParameters parameters, RTHandle output, HableCurve hableCurve, int lutSize, + Vector4 proceduralParams1, + Vector4 proceduralParams2, ComputeBuffer histogramBuffer, CommandBuffer cmd) { @@ -4796,6 +4798,9 @@ static void RenderExposureDebug(in DebugParameters parameters, float histBias = -exposureSettings.limitMin.value * histScale; Vector4 histogramParams = new Vector4(histScale, histBias, histogramFraction.x, histogramFraction.y); + parameters.debugExposureMaterial.SetVector(HDShaderIDs._ProceduralMaskParams, proceduralParams1); + parameters.debugExposureMaterial.SetVector(HDShaderIDs._ProceduralMaskParams2, proceduralParams2); + parameters.debugExposureMaterial.SetVector(HDShaderIDs._HistogramExposureParams, histogramParams); parameters.debugExposureMaterial.SetVector(HDShaderIDs._Variants, exposureVariants); parameters.debugExposureMaterial.SetVector(HDShaderIDs._ExposureParams, exposureParams); @@ -4821,11 +4826,9 @@ static void RenderExposureDebug(in DebugParameters parameters, var tonemappingMode = toneMapIsEnabled ? tonemappingSettings.mode.value : TonemappingMode.None; bool drawTonemapCurve = tonemappingMode != TonemappingMode.None && - parameters.debugDisplaySettings.data.lightingDebugSettings.showTonemapCurveAlongHistogramView; - - bool centerAroundMiddleGrey = parameters.debugDisplaySettings.data.lightingDebugSettings.centerHistogramAroundMiddleGrey; + parameters.debugDisplaySettings.data.lightingDebugSettings.showTonemapCurveAlongHistogramView; - parameters.debugExposureMaterial.SetVector(HDShaderIDs._ExposureDebugParams, new Vector4(drawTonemapCurve ? 1.0f : 0.0f, (int)tonemappingMode, centerAroundMiddleGrey ? 1 : 0, 0)); + parameters.debugExposureMaterial.SetVector(HDShaderIDs._ExposureDebugParams, new Vector4(drawTonemapCurve ? 1.0f : 0.0f, (int)tonemappingMode, 0, 0)); if (drawTonemapCurve) { if (tonemappingMode == TonemappingMode.Custom) @@ -4894,8 +4897,18 @@ void RenderDebug(HDCamera hdCamera, CommandBuffer cmd, CullingResults cullResult if (debugParams.exposureDebugEnabled) { - RenderExposureDebug(debugParams, m_CameraColorBuffer, m_DebugFullScreenTempBuffer,m_PostProcessSystem.GetPreviousExposureTexture(hdCamera), m_PostProcessSystem.GetExposureTexture(hdCamera), - m_PostProcessSystem.GetExposureDebugData(),m_IntermediateAfterPostProcessBuffer, m_PostProcessSystem.GetCustomToneMapCurve(), m_PostProcessSystem.GetLutSize(), m_PostProcessSystem.GetHistogramBuffer(), cmd); + m_PostProcessSystem.ComputeProceduralMeteringParams(hdCamera, out Vector4 proceduralParams1, out Vector4 proceduralParams2); + + RenderExposureDebug(debugParams, m_CameraColorBuffer, m_DebugFullScreenTempBuffer, + m_PostProcessSystem.GetPreviousExposureTexture(hdCamera), + m_PostProcessSystem.GetExposureTexture(hdCamera), + m_PostProcessSystem.GetExposureDebugData(), + m_IntermediateAfterPostProcessBuffer, + m_PostProcessSystem.GetCustomToneMapCurve(), + m_PostProcessSystem.GetLutSize(), + proceduralParams1, + proceduralParams2, + m_PostProcessSystem.GetHistogramBuffer(), cmd); } // First resolve color picker diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs index 40fd8925915..3ea1f6489de 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDStringConstants.cs @@ -612,6 +612,8 @@ static class HDShaderIDs public static readonly int _AdaptationParams = Shader.PropertyToID("_AdaptationParams"); public static readonly int _ExposureCurveTexture = Shader.PropertyToID("_ExposureCurveTexture"); public static readonly int _ExposureWeightMask = Shader.PropertyToID("_ExposureWeightMask"); + public static readonly int _ProceduralMaskParams = Shader.PropertyToID("_ProceduralMaskParams"); + public static readonly int _ProceduralMaskParams2 = Shader.PropertyToID("_ProceduralMaskParams2"); public static readonly int _Variants = Shader.PropertyToID("_Variants"); public static readonly int _InputTexture = Shader.PropertyToID("_InputTexture"); public static readonly int _InputTextureMSAA = Shader.PropertyToID("_InputTextureMSAA");