Skip to content

Texture-weighted automatic exposure #165

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 6 commits into from
Apr 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 @@ -105,6 +105,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added Light decomposition lighting debugging modes and support in AOV
- Added exposure compensation to Fixed exposure mode
- Added support for rasterized area light shadows in StackLit
- Added support for texture-weighted automatic exposure

### Fixed
- Fix when rescale probe all direction below zero (1219246)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ To configure **Automatic Mode**, select the **Metering Mode**. This tells the Ca

![](Images/Override-Exposure3.png)

- **Mask Weighted**: The Camera applies a weight to every pixel in the buffer then uses the weights to measure the exposure. To specify the weighting, this technique uses the Texture set in the **Weight Texture Mask** field. Note that, if you do not provide a Texture, this metering mode is equivalent to **Average**.


Next, set the **Limit Min** and **Limit Max** to define the minimum and maximum exposure values respectively. Move between light and dark areas of your Scene and alter each property until you find the perfect values for your Scene.


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ sealed class ExposureEditor : VolumeComponentEditor
SerializedDataParameter m_AdaptationSpeedDarkToLight;
SerializedDataParameter m_AdaptationSpeedLightToDark;

SerializedDataParameter m_WeightTextureMask;

public override void OnEnable()
{
var o = new PropertyFetcher<Exposure>(serializedObject);
Expand All @@ -37,6 +39,8 @@ public override void OnEnable()
m_AdaptationMode = Unpack(o.Find(x => x.adaptationMode));
m_AdaptationSpeedDarkToLight = Unpack(o.Find(x => x.adaptationSpeedDarkToLight));
m_AdaptationSpeedLightToDark = Unpack(o.Find(x => x.adaptationSpeedLightToDark));

m_WeightTextureMask = Unpack(o.Find(x => x.weightTextureMask));
}

public override void OnInspectorGUI()
Expand All @@ -58,6 +62,9 @@ public override void OnInspectorGUI()
EditorGUILayout.Space();

PropertyField(m_MeteringMode);
if(m_MeteringMode.value.intValue == (int)MeteringMode.MaskWeighted)
PropertyField(m_WeightTextureMask);

PropertyField(m_LuminanceSource);

if (m_LuminanceSource.value.intValue == (int)LuminanceSource.LightingBuffer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ public sealed class Exposure : VolumeComponent, IPostProcessComponent
[Tooltip("Sets the speed at which the exposure changes when the Camera moves from a bright area to a dark area.")]
public MinFloatParameter adaptationSpeedLightToDark = new MinFloatParameter(1f, 0.001f);

/// <summary>
/// Sets the texture mask used to weight the pixels in the buffer when computing exposure. Used only with .
/// </summary>
[Tooltip("Sets the texture mask to be used to weight the pixels in the buffer for the sake of computing exposure..")]
public NoInterpTextureParameter weightTextureMask = new NoInterpTextureParameter(null);

/// <summary>
/// Tells if the effect needs to be rendered or not.
/// </summary>
Expand Down Expand Up @@ -145,7 +151,16 @@ public enum MeteringMode
/// have the minimum weight, and pixels in between have a progressively lower weight the
/// closer they are to the screen borders.
/// </summary>
CenterWeighted
CenterWeighted,


/// <summary>
/// The Camera applies a weight to every pixel in the buffer and then uses them to measure
/// 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.
/// </summary>
MaskWeighted

}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,14 @@ void DoDynamicExposure(CommandBuffer cmd, HDCamera camera, RTHandle colorBuffer)
cmd.SetComputeIntParams(cs, HDShaderIDs._Variants, m_ExposureVariants);
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._PreviousExposureTexture, prevExposure);
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._SourceTexture, sourceTex);
if (m_Exposure.meteringMode == MeteringMode.MaskWeighted && m_Exposure.weightTextureMask.value != null)
{
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._ExposureWeightMask, m_Exposure.weightTextureMask.value);
}
else
{
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._ExposureWeightMask, Texture2D.whiteTexture);
}
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._OutputTexture, m_TempTexture1024);
cmd.DispatchCompute(cs, kernel, 1024 / 8, 1024 / 8, 1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
TEXTURE2D(_ExposureCurveTexture);
TEXTURE2D(_PreviousExposureTexture);
TEXTURE2D(_InputTexture);

TEXTURE2D(_ExposureWeightMask);

TEXTURE2D_X(_SourceTexture);

RW_TEXTURE2D(float2, _OutputTexture);
Expand Down Expand Up @@ -42,6 +45,9 @@ CBUFFER_END
#define ParamAdaptationMode _Variants.z
#define ParamEvaluateMode _Variants.w

#define PREPASS_TEX_SIZE 1024.0
#define PREPASS_TEX_HALF_SIZE 512.0

float WeightSample(uint2 pixel)
{
UNITY_BRANCH
Expand All @@ -50,17 +56,23 @@ float WeightSample(uint2 pixel)
case 1u:
{
// Spot metering
const float kRadius = 0.075 * 1024.0;
const float2 kCenter = (512.0).xx;
const float kRadius = 0.075 * PREPASS_TEX_SIZE;
const float2 kCenter = (PREPASS_TEX_HALF_SIZE).xx;
float d = length(kCenter - pixel) - kRadius;
return 1.0 - saturate(d);
}
case 2u:
{
// Center-weighted
const float2 kCenter = (512.0).xx;
return 1.0 - saturate(pow(length(kCenter - pixel) / 512.0, 1.0));
const float2 kCenter = (PREPASS_TEX_HALF_SIZE).xx;
return 1.0 - saturate(pow(length(kCenter - pixel) / PREPASS_TEX_HALF_SIZE, 1.0));
}
case 3u:
{
// Mask weigthing
return SAMPLE_TEXTURE2D_LOD(_ExposureWeightMask, sampler_LinearClamp, pixel * rcp(PREPASS_TEX_SIZE), 0.0).x;
}

default:
{
// Global average
Expand Down Expand Up @@ -126,7 +138,7 @@ void KPrePass(uint2 dispatchThreadId : SV_DispatchThreadID)
// For XR, interleave single-pass views in a checkerboard pattern
UNITY_XR_ASSIGN_VIEW_INDEX((dispatchThreadId.x + dispatchThreadId.y) % _XRViewCount)

PositionInputs posInputs = GetPositionInput(float2(dispatchThreadId), 1.0 / 1024.0, uint2(8u, 8u));
PositionInputs posInputs = GetPositionInput(float2(dispatchThreadId), rcp(PREPASS_TEX_SIZE), uint2(8u, 8u));
float2 uv = ClampAndScaleUVForBilinear(posInputs.positionNDC);
float luma;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,7 @@ static class HDShaderIDs
public static readonly int _ExposureParams = Shader.PropertyToID("_ExposureParams");
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 _Variants = Shader.PropertyToID("_Variants");
public static readonly int _InputTexture = Shader.PropertyToID("_InputTexture");
public static readonly int _OutputTexture = Shader.PropertyToID("_OutputTexture");
Expand Down