Skip to content

Commit a219063

Browse files
Exposure curve remapping can specify curves for min/max limits (#882)
* Port code * changelog * Revert HDRP asset Co-authored-by: sebastienlagarde <[email protected]>
1 parent eedfe69 commit a219063

File tree

7 files changed

+66
-15
lines changed

7 files changed

+66
-15
lines changed

com.unity.render-pipelines.high-definition/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
152152
- Added compute shader stripping.
153153
- Added Cull Mode option for opaque materials and ShaderGraphs.
154154
- Added scene view exposure override.
155+
- Added support for exposure curve remapping for min/max limits.
155156

156157
### Fixed
157158
- Fix when rescale probe all direction below zero (1219246)

com.unity.render-pipelines.high-definition/Editor/PostProcessing/ExposureEditor.cs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ sealed class ExposureEditor : VolumeComponentEditor
1616
SerializedDataParameter m_LimitMin;
1717
SerializedDataParameter m_LimitMax;
1818
SerializedDataParameter m_CurveMap;
19-
19+
SerializedDataParameter m_CurveMin;
20+
SerializedDataParameter m_CurveMax;
21+
2022
SerializedDataParameter m_AdaptationMode;
2123
SerializedDataParameter m_AdaptationSpeedDarkToLight;
2224
SerializedDataParameter m_AdaptationSpeedLightToDark;
@@ -52,7 +54,9 @@ public override void OnEnable()
5254
m_LimitMin = Unpack(o.Find(x => x.limitMin));
5355
m_LimitMax = Unpack(o.Find(x => x.limitMax));
5456
m_CurveMap = Unpack(o.Find(x => x.curveMap));
55-
57+
m_CurveMin = Unpack(o.Find(x => x.limitMinCurveMap));
58+
m_CurveMax = Unpack(o.Find(x => x.limitMaxCurveMap));
59+
5660
m_AdaptationMode = Unpack(o.Find(x => x.adaptationMode));
5761
m_AdaptationSpeedDarkToLight = Unpack(o.Find(x => x.adaptationSpeedDarkToLight));
5862
m_AdaptationSpeedLightToDark = Unpack(o.Find(x => x.adaptationSpeedLightToDark));
@@ -137,11 +141,18 @@ public override void OnInspectorGUI()
137141
// EditorGUILayout.HelpBox("Luminance source buffer isn't supported yet.", MessageType.Warning);
138142

139143
if (mode == (int)ExposureMode.CurveMapping)
144+
{
140145
PropertyField(m_CurveMap);
141-
146+
PropertyField(m_CurveMin, EditorGUIUtility.TrTextContent("Limit Min"));
147+
PropertyField(m_CurveMax, EditorGUIUtility.TrTextContent("Limit Max"));
148+
}
149+
else if (!(mode == (int)ExposureMode.AutomaticHistogram && m_HistogramCurveRemapping.value.boolValue))
150+
{
151+
PropertyField(m_LimitMin);
152+
PropertyField(m_LimitMax);
153+
}
154+
142155
PropertyField(m_Compensation);
143-
PropertyField(m_LimitMin);
144-
PropertyField(m_LimitMax);
145156

146157
if(mode == (int)ExposureMode.AutomaticHistogram)
147158
{
@@ -152,6 +163,8 @@ public override void OnInspectorGUI()
152163
if (m_HistogramCurveRemapping.value.boolValue)
153164
{
154165
PropertyField(m_CurveMap);
166+
PropertyField(m_CurveMin, EditorGUIUtility.TrTextContent("Limit Min"));
167+
PropertyField(m_CurveMax, EditorGUIUtility.TrTextContent("Limit Max"));
155168
}
156169
}
157170

com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Exposure.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@ public sealed class Exposure : VolumeComponent, IPostProcessComponent
6464
[Tooltip("Specifies a curve that remaps the Scene exposure on the x-axis to the exposure you want on the y-axis.")]
6565
public AnimationCurveParameter curveMap = new AnimationCurveParameter(AnimationCurve.Linear(-10f, -10f, 20f, 20f)); // TODO: Use TextureCurve instead?
6666

67+
/// <summary>
68+
/// Specifies a curve that determines for each current exposure value (x-value) what minimum value is allowed to auto-adaptation (y-axis).
69+
/// This parameter is only used when <see cref="ExposureMode.CurveMapping"/> is set.
70+
/// </summary>
71+
[Tooltip("Specifies a curve that determines for each current exposure value (x-value) what minimum value is allowed to auto-adaptation (y-axis).")]
72+
public AnimationCurveParameter limitMinCurveMap = new AnimationCurveParameter(AnimationCurve.Linear(-10f, -12f, 20f, 18f));
73+
74+
/// <summary>
75+
/// Specifies a curve that determines for each current exposure value (x-value) what maximum value is allowed to auto-adaptation (y-axis).
76+
/// This parameter is only used when <see cref="ExposureMode.CurveMapping"/> is set.
77+
/// </summary>
78+
[Tooltip("Specifies a curve that determines for each current exposure value (x-value) what maximum value is allowed to auto-adaptation (y-axis).")]
79+
public AnimationCurveParameter limitMaxCurveMap = new AnimationCurveParameter(AnimationCurve.Linear(-10f, -8f, 20f, 22f));
80+
6781
/// <summary>
6882
/// Specifies the method that HDRP uses to change the exposure when the Camera moves from dark to light and vice versa.
6983
/// This parameter is only used when <see cref="ExposureMode.Automatic"/> or <see cref="ExposureMode.CurveMapping"/> is set.

com.unity.render-pipelines.high-definition/Runtime/PostProcessing/PostProcessSystem.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,18 +1017,27 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem)
10171017
previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.Exposure);
10181018
}
10191019

1020-
void PrepareExposureCurveData(AnimationCurve curve, out float min, out float max)
1020+
void PrepareExposureCurveData(out float min, out float max)
10211021
{
1022+
var curve = m_Exposure.curveMap.value;
1023+
var minCurve = m_Exposure.limitMinCurveMap.value;
1024+
var maxCurve = m_Exposure.limitMaxCurveMap.value;
1025+
10221026
if (m_ExposureCurveTexture == null)
10231027
{
1024-
m_ExposureCurveTexture = new Texture2D(k_ExposureCurvePrecision, 1, TextureFormat.RHalf, false, true)
1028+
m_ExposureCurveTexture = new Texture2D(k_ExposureCurvePrecision, 1, TextureFormat.RGBAHalf, false, true)
10251029
{
10261030
name = "Exposure Curve",
10271031
filterMode = FilterMode.Bilinear,
10281032
wrapMode = TextureWrapMode.Clamp
10291033
};
10301034
}
10311035

1036+
bool minCurveHasPoints = minCurve.length > 0;
1037+
bool maxCurveHasPoints = maxCurve.length > 0;
1038+
float defaultMin = -100.0f;
1039+
float defaultMax = 100.0f;
1040+
10321041
var pixels = m_ExposureCurveColorArray;
10331042

10341043
// Fail safe in case the curve is deleted / has 0 point
@@ -1047,7 +1056,13 @@ void PrepareExposureCurveData(AnimationCurve curve, out float min, out float max
10471056
float step = (max - min) / (k_ExposureCurvePrecision - 1f);
10481057

10491058
for (int i = 0; i < k_ExposureCurvePrecision; i++)
1050-
pixels[i] = new Color(curve.Evaluate(min + step * i), 0f, 0f, 0f);
1059+
{
1060+
float currTime = min + step * i;
1061+
pixels[i] = new Color(curve.Evaluate(currTime),
1062+
minCurveHasPoints ? minCurve.Evaluate(currTime) : defaultMin,
1063+
maxCurveHasPoints ? maxCurve.Evaluate(currTime) : defaultMax,
1064+
0f);
1065+
}
10511066
}
10521067

10531068
m_ExposureCurveTexture.SetPixels(pixels);
@@ -1124,7 +1139,7 @@ void DoDynamicExposure(CommandBuffer cmd, HDCamera camera, RTHandle colorBuffer)
11241139
}
11251140
else if (m_Exposure.mode.value == ExposureMode.CurveMapping)
11261141
{
1127-
PrepareExposureCurveData(m_Exposure.curveMap.value, out float min, out float max);
1142+
PrepareExposureCurveData(out float min, out float max);
11281143
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._ExposureCurveTexture, m_ExposureCurveTexture);
11291144
cmd.SetComputeVectorParam(cs, HDShaderIDs._ExposureParams, new Vector4(m_Exposure.compensation.value + m_DebugExposureCompensation, min, max, 0f));
11301145
cmd.SetComputeVectorParam(cs, HDShaderIDs._ExposureParams2, new Vector4(min, max, ColorUtils.lensImperfectionExposureScale, ColorUtils.s_LightMeterCalibrationConstant));
@@ -1199,7 +1214,7 @@ void DoHistogramBasedExposure(CommandBuffer cmd, HDCamera camera, RTHandle sourc
11991214
m_ExposureVariants[3] = 0;
12001215
if (m_Exposure.histogramUseCurveRemapping.value)
12011216
{
1202-
PrepareExposureCurveData(m_Exposure.curveMap.value, out float min, out float max);
1217+
PrepareExposureCurveData(out float min, out float max);
12031218
cmd.SetComputeVectorParam(cs, HDShaderIDs._ExposureParams2, new Vector4(min, max, ColorUtils.lensImperfectionExposureScale, ColorUtils.s_LightMeterCalibrationConstant));
12041219
m_ExposureVariants[3] = 2;
12051220
}

com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/Exposure.compute

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,11 @@ void KReduction(uint2 groupId : SV_GroupID, uint2 groupThreadId : SV_GroupThread
127127
case 2u:
128128
{
129129
// Curve remapping
130-
float exposure = CurveRemap(avgLuminance);
130+
float minExposure = ParamExposureLimitMin;
131+
float maxExposure = ParamExposureLimitMax;
132+
float exposure = CurveRemap(avgLuminance, minExposure, maxExposure);
131133
exposure = AdaptExposure(exposure - ParamExposureCompensation);
134+
exposure = clamp(exposure, minExposure, maxExposure);
132135
_OutputTexture[groupId.xy] = float2(ConvertEV100ToExposure(exposure, LensImperfectionExposureScale), exposure);
133136
break;
134137
}

com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/ExposureCommon.hlsl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,13 @@ float AdaptExposure(float exposure)
122122
}
123123
}
124124

125-
float CurveRemap(float inEV)
125+
float CurveRemap(float inEV, out float limitMin, out float limitMax)
126126
{
127127
float remap = saturate((inEV - ParamCurveMin) / (ParamCurveMax - ParamCurveMin));
128-
return SAMPLE_TEXTURE2D_LOD(_ExposureCurveTexture, s_linear_clamp_sampler, float2(remap, 0.0), 0.0).x;
128+
float3 curveSample = SAMPLE_TEXTURE2D_LOD(_ExposureCurveTexture, s_linear_clamp_sampler, float2(remap, 0.0), 0.0).xyz;
129+
limitMin = curveSample.y;
130+
limitMax = curveSample.z;
131+
return curveSample.x;
129132
}
130133

131134
#endif

com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/HistogramExposure.compute

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,15 @@ void KHistogramReduce(uint3 dispatchThreadId : SV_DispatchThreadID)
165165
w = max(w, 1e-4f);
166166
float avgEV = evProcessedSum * rcp(w);
167167

168+
float minExposure = ParamExposureLimitMin;
169+
float maxExposure = ParamExposureLimitMax;
168170
if (ParamEvaluateMode == 2)
169171
{
170-
avgEV = CurveRemap(avgEV);
172+
avgEV = CurveRemap(avgEV, minExposure, maxExposure);
171173
}
172174

173175
float exposure = AdaptExposure(avgEV - ParamExposureCompensation);
174-
exposure = clamp(exposure, ParamExposureLimitMin, ParamExposureLimitMax);
176+
exposure = clamp(exposure, minExposure, maxExposure);
175177
_OutputTexture[uint2(0, 0)] = float2(ConvertEV100ToExposure(exposure, LensImperfectionExposureScale), exposure);
176178
#ifdef OUTPUT_DEBUG_DATA
177179
_ExposureDebugTexture[uint2(0, 0)] = float2(avgEV - ParamExposureCompensation, 0.0f);

0 commit comments

Comments
 (0)