Skip to content

Exposure curve remapping can specify curves for min/max limits #882

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions com.unity.render-pipelines.high-definition/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added compute shader stripping.
- Added Cull Mode option for opaque materials and ShaderGraphs.
- Added scene view exposure override.
- Added support for exposure curve remapping for min/max limits.

### Fixed
- Fix when rescale probe all direction below zero (1219246)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ sealed class ExposureEditor : VolumeComponentEditor
SerializedDataParameter m_LimitMin;
SerializedDataParameter m_LimitMax;
SerializedDataParameter m_CurveMap;

SerializedDataParameter m_CurveMin;
SerializedDataParameter m_CurveMax;

SerializedDataParameter m_AdaptationMode;
SerializedDataParameter m_AdaptationSpeedDarkToLight;
SerializedDataParameter m_AdaptationSpeedLightToDark;
Expand Down Expand Up @@ -52,7 +54,9 @@ public override void OnEnable()
m_LimitMin = Unpack(o.Find(x => x.limitMin));
m_LimitMax = Unpack(o.Find(x => x.limitMax));
m_CurveMap = Unpack(o.Find(x => x.curveMap));

m_CurveMin = Unpack(o.Find(x => x.limitMinCurveMap));
m_CurveMax = Unpack(o.Find(x => x.limitMaxCurveMap));

m_AdaptationMode = Unpack(o.Find(x => x.adaptationMode));
m_AdaptationSpeedDarkToLight = Unpack(o.Find(x => x.adaptationSpeedDarkToLight));
m_AdaptationSpeedLightToDark = Unpack(o.Find(x => x.adaptationSpeedLightToDark));
Expand Down Expand Up @@ -137,11 +141,18 @@ public override void OnInspectorGUI()
// EditorGUILayout.HelpBox("Luminance source buffer isn't supported yet.", MessageType.Warning);

if (mode == (int)ExposureMode.CurveMapping)
{
PropertyField(m_CurveMap);

PropertyField(m_CurveMin, EditorGUIUtility.TrTextContent("Limit Min"));
PropertyField(m_CurveMax, EditorGUIUtility.TrTextContent("Limit Max"));
}
else if (!(mode == (int)ExposureMode.AutomaticHistogram && m_HistogramCurveRemapping.value.boolValue))
{
PropertyField(m_LimitMin);
PropertyField(m_LimitMax);
}

PropertyField(m_Compensation);
PropertyField(m_LimitMin);
PropertyField(m_LimitMax);

if(mode == (int)ExposureMode.AutomaticHistogram)
{
Expand All @@ -152,6 +163,8 @@ public override void OnInspectorGUI()
if (m_HistogramCurveRemapping.value.boolValue)
{
PropertyField(m_CurveMap);
PropertyField(m_CurveMin, EditorGUIUtility.TrTextContent("Limit Min"));
PropertyField(m_CurveMax, EditorGUIUtility.TrTextContent("Limit Max"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ public sealed class Exposure : VolumeComponent, IPostProcessComponent
[Tooltip("Specifies a curve that remaps the Scene exposure on the x-axis to the exposure you want on the y-axis.")]
public AnimationCurveParameter curveMap = new AnimationCurveParameter(AnimationCurve.Linear(-10f, -10f, 20f, 20f)); // TODO: Use TextureCurve instead?

/// <summary>
/// Specifies a curve that determines for each current exposure value (x-value) what minimum value is allowed to auto-adaptation (y-axis).
/// This parameter is only used when <see cref="ExposureMode.CurveMapping"/> is set.
/// </summary>
[Tooltip("Specifies a curve that determines for each current exposure value (x-value) what minimum value is allowed to auto-adaptation (y-axis).")]
public AnimationCurveParameter limitMinCurveMap = new AnimationCurveParameter(AnimationCurve.Linear(-10f, -12f, 20f, 18f));

/// <summary>
/// Specifies a curve that determines for each current exposure value (x-value) what maximum value is allowed to auto-adaptation (y-axis).
/// This parameter is only used when <see cref="ExposureMode.CurveMapping"/> is set.
/// </summary>
[Tooltip("Specifies a curve that determines for each current exposure value (x-value) what maximum value is allowed to auto-adaptation (y-axis).")]
public AnimationCurveParameter limitMaxCurveMap = new AnimationCurveParameter(AnimationCurve.Linear(-10f, -8f, 20f, 22f));

/// <summary>
/// Specifies the method that HDRP uses to change the exposure when the Camera moves from dark to light and vice versa.
/// This parameter is only used when <see cref="ExposureMode.Automatic"/> or <see cref="ExposureMode.CurveMapping"/> is set.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1017,18 +1017,27 @@ RTHandle Allocator(string id, int frameIndex, RTHandleSystem rtHandleSystem)
previous = camera.GetPreviousFrameRT((int)HDCameraFrameHistoryType.Exposure);
}

void PrepareExposureCurveData(AnimationCurve curve, out float min, out float max)
void PrepareExposureCurveData(out float min, out float max)
{
var curve = m_Exposure.curveMap.value;
var minCurve = m_Exposure.limitMinCurveMap.value;
var maxCurve = m_Exposure.limitMaxCurveMap.value;

if (m_ExposureCurveTexture == null)
{
m_ExposureCurveTexture = new Texture2D(k_ExposureCurvePrecision, 1, TextureFormat.RHalf, false, true)
m_ExposureCurveTexture = new Texture2D(k_ExposureCurvePrecision, 1, TextureFormat.RGBAHalf, false, true)
{
name = "Exposure Curve",
filterMode = FilterMode.Bilinear,
wrapMode = TextureWrapMode.Clamp
};
}

bool minCurveHasPoints = minCurve.length > 0;
bool maxCurveHasPoints = maxCurve.length > 0;
float defaultMin = -100.0f;
float defaultMax = 100.0f;

var pixels = m_ExposureCurveColorArray;

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

for (int i = 0; i < k_ExposureCurvePrecision; i++)
pixels[i] = new Color(curve.Evaluate(min + step * i), 0f, 0f, 0f);
{
float currTime = min + step * i;
pixels[i] = new Color(curve.Evaluate(currTime),
minCurveHasPoints ? minCurve.Evaluate(currTime) : defaultMin,
maxCurveHasPoints ? maxCurve.Evaluate(currTime) : defaultMax,
0f);
}
}

m_ExposureCurveTexture.SetPixels(pixels);
Expand Down Expand Up @@ -1124,7 +1139,7 @@ void DoDynamicExposure(CommandBuffer cmd, HDCamera camera, RTHandle colorBuffer)
}
else if (m_Exposure.mode.value == ExposureMode.CurveMapping)
{
PrepareExposureCurveData(m_Exposure.curveMap.value, out float min, out float max);
PrepareExposureCurveData(out float min, out float max);
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._ExposureCurveTexture, m_ExposureCurveTexture);
cmd.SetComputeVectorParam(cs, HDShaderIDs._ExposureParams, new Vector4(m_Exposure.compensation.value + m_DebugExposureCompensation, min, max, 0f));
cmd.SetComputeVectorParam(cs, HDShaderIDs._ExposureParams2, new Vector4(min, max, ColorUtils.lensImperfectionExposureScale, ColorUtils.s_LightMeterCalibrationConstant));
Expand Down Expand Up @@ -1199,7 +1214,7 @@ void DoHistogramBasedExposure(CommandBuffer cmd, HDCamera camera, RTHandle sourc
m_ExposureVariants[3] = 0;
if (m_Exposure.histogramUseCurveRemapping.value)
{
PrepareExposureCurveData(m_Exposure.curveMap.value, out float min, out float max);
PrepareExposureCurveData(out float min, out float max);
cmd.SetComputeVectorParam(cs, HDShaderIDs._ExposureParams2, new Vector4(min, max, ColorUtils.lensImperfectionExposureScale, ColorUtils.s_LightMeterCalibrationConstant));
m_ExposureVariants[3] = 2;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,11 @@ void KReduction(uint2 groupId : SV_GroupID, uint2 groupThreadId : SV_GroupThread
case 2u:
{
// Curve remapping
float exposure = CurveRemap(avgLuminance);
float minExposure = ParamExposureLimitMin;
float maxExposure = ParamExposureLimitMax;
float exposure = CurveRemap(avgLuminance, minExposure, maxExposure);
exposure = AdaptExposure(exposure - ParamExposureCompensation);
exposure = clamp(exposure, minExposure, maxExposure);
_OutputTexture[groupId.xy] = float2(ConvertEV100ToExposure(exposure, LensImperfectionExposureScale), exposure);
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,13 @@ float AdaptExposure(float exposure)
}
}

float CurveRemap(float inEV)
float CurveRemap(float inEV, out float limitMin, out float limitMax)
{
float remap = saturate((inEV - ParamCurveMin) / (ParamCurveMax - ParamCurveMin));
return SAMPLE_TEXTURE2D_LOD(_ExposureCurveTexture, s_linear_clamp_sampler, float2(remap, 0.0), 0.0).x;
float3 curveSample = SAMPLE_TEXTURE2D_LOD(_ExposureCurveTexture, s_linear_clamp_sampler, float2(remap, 0.0), 0.0).xyz;
limitMin = curveSample.y;
limitMax = curveSample.z;
return curveSample.x;
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,15 @@ void KHistogramReduce(uint3 dispatchThreadId : SV_DispatchThreadID)
w = max(w, 1e-4f);
float avgEV = evProcessedSum * rcp(w);

float minExposure = ParamExposureLimitMin;
float maxExposure = ParamExposureLimitMax;
if (ParamEvaluateMode == 2)
{
avgEV = CurveRemap(avgEV);
avgEV = CurveRemap(avgEV, minExposure, maxExposure);
}

float exposure = AdaptExposure(avgEV - ParamExposureCompensation);
exposure = clamp(exposure, ParamExposureLimitMin, ParamExposureLimitMax);
exposure = clamp(exposure, minExposure, maxExposure);
_OutputTexture[uint2(0, 0)] = float2(ConvertEV100ToExposure(exposure, LensImperfectionExposureScale), exposure);
#ifdef OUTPUT_DEBUG_DATA
_ExposureDebugTexture[uint2(0, 0)] = float2(avgEV - ParamExposureCompensation, 0.0f);
Expand Down