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");