Skip to content

Final Image Histogram Debug View #887

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 3 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 @@ -154,6 +154,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added scene view exposure override.
- Added support for exposure curve remapping for min/max limits.
- Added presets for ray traced reflections.
- Added final image histogram debug view (both luminance and RGB).

### Fixed
- Fix when rescale probe all direction below zero (1219246)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -981,8 +981,20 @@ void RegisterLightingDebug()
setter = value => data.lightingDebugSettings.centerHistogramAroundMiddleGrey = value
});
}
if (data.lightingDebugSettings.exposureDebugMode == ExposureDebugMode.FinalImageHistogramView)
{
exposureFoldout.children.Add(
new DebugUI.BoolField()
{
displayName = "Display RGB Histogram",
getter = () => data.lightingDebugSettings.displayFinalImageHistogramAsRGB,
setter = value => data.lightingDebugSettings.displayFinalImageHistogramAsRGB = value
});

exposureFoldout.children.Add(
}


exposureFoldout.children.Add(
new DebugUI.FloatField
{
displayName = "Debug Lens Attenuation",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Shader "Hidden/HDRP/DebugExposure"
#define _DrawTonemapCurve _ExposureDebugParams.x
#define _TonemapType _ExposureDebugParams.y
#define _CenterAroundTargetExposure _ExposureDebugParams.z
#define _FinalImageHistogramRGB _ExposureDebugParams.w


struct Attributes
Expand Down Expand Up @@ -683,6 +684,71 @@ Shader "Hidden/HDRP/DebugExposure"
return outputColor;
}

StructuredBuffer<uint4> _FullImageHistogram;

float3 FragImageHistogram(Varyings input) : SV_Target
{
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;
float3 outputColor = color;
float heightLabelBar = (DEBUG_FONT_TEXT_WIDTH * 1.25) * _ScreenSize.w * _RTHandleScale.y;
uint maxValue = 0;
uint maxLuma = 0;
for (int i = 0; i < 256; ++i)
{
uint histogramVal = Max3(_FullImageHistogram[i].x, _FullImageHistogram[i].y, _FullImageHistogram[i].z);
maxValue = max(histogramVal, maxValue);
maxLuma = max(_FullImageHistogram[i].w, maxLuma);
}
float histFrameHeight = 0.2 * _RTHandleScale.y;
float safeBand = 1.0f / 255.0f;
float binLocMin = safeBand;
float binLocMax = 1.0f - safeBand;
if (DrawEmptyFrame(uv, float3(0.125, 0.125, 0.125), 0.4, histFrameHeight, heightLabelBar, outputColor))
{
// Draw labels
const int labelCount = 12;
int minLabelLocationX = DEBUG_FONT_TEXT_WIDTH * 0.25;
int maxLabelLocationX = _ScreenSize.x - (DEBUG_FONT_TEXT_WIDTH * 3);
int labelLocationY = 0.0f;
uint2 unormCoord = input.positionCS.xy;
[unroll]
for (int i = 0; i <= labelCount; ++i)
{
float t = rcp(labelCount) * i;
uint2 labelLoc = uint2((uint)lerp(minLabelLocationX, maxLabelLocationX, t), labelLocationY);
float labelValue = lerp(0.0, 255.0, t);
labelLoc.x += 2;
DrawInteger(labelValue, float3(1.0f, 1.0f, 1.0f), unormCoord, labelLoc, outputColor.rgb);
}
float remappedX = (uv.x - binLocMin) / (binLocMax - binLocMin);
// Draw bins
uint bin = remappedX * 255;
float4 val = _FullImageHistogram[bin];
val /= float4(maxValue, maxValue, maxValue, maxLuma);
val *= 0.95*(histFrameHeight - heightLabelBar);
val += heightLabelBar;
if (_FinalImageHistogramRGB > 0)
{
float3 alphas = 0;
if (uv.y < val.x && uv.y > heightLabelBar)
alphas.x = 0.3333f;
if (uv.y < val.y && uv.y > heightLabelBar)
alphas.y = 0.3333f;
if (uv.y < val.z && uv.y > heightLabelBar)
alphas.z = 0.3333f;
outputColor = outputColor * (1.0f - (alphas.x + alphas.y + alphas.z)) + alphas;
}
else
{
if (uv.y < val.w && uv.y > heightLabelBar)
outputColor = 0.3333f;
}
}
return outputColor;
}

ENDHLSL

SubShader
Expand Down Expand Up @@ -724,6 +790,17 @@ Shader "Hidden/HDRP/DebugExposure"
ENDHLSL
}

Pass
{
ZWrite Off
ZTest Always
Blend Off
Cull Off
HLSLPROGRAM
#pragma fragment FragImageHistogram
ENDHLSL
}

}
Fallback Off
}
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ public enum ExposureDebugMode
SceneEV100Values,
/// <summary>Display the Histogram used for exposure.</summary>
HistogramView,
/// <summary>Display an RGB histogram of the final image (after post-processing).</summary>
FinalImageHistogramView,
/// <summary>Visualize the scene color weighted as the metering mode selected.</summary>
MeteringWeighted,

Expand Down Expand Up @@ -323,6 +325,8 @@ public bool IsDebugDisplayEnabled()
public bool showTonemapCurveAlongHistogramView = true;
/// <summary>Whether to center the histogram debug view around the middle-grey point or not.</summary>
public bool centerHistogramAroundMiddleGrey = false;
/// <summary>Whether to show tonemap curve in the histogram debug view or not.</summary>
public bool displayFinalImageHistogramAsRGB = false;

/// <summary>Display the light cookies atlas.</summary>
public bool displayCookieAtlas = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,17 @@ private enum SMAAStage
// Exposure data
const int k_ExposureCurvePrecision = 128;
const int k_HistogramBins = 128; // Important! If this changes, need to change HistogramExposure.compute
const int k_DebugImageHistogramBins = 256; // Important! If this changes, need to change HistogramExposure.compute
readonly Color[] m_ExposureCurveColorArray = new Color[k_ExposureCurvePrecision];
readonly int[] m_ExposureVariants = new int[4];

Texture2D m_ExposureCurveTexture;
RTHandle m_EmptyExposureTexture; // RGHalf
RTHandle m_DebugExposureData;
ComputeBuffer m_HistogramBuffer;
ComputeBuffer m_DebugImageHistogramBuffer;
readonly int[] m_EmptyHistogram = new int[k_HistogramBins];
readonly int[] m_EmptyDebugImageHistogram = new int[k_DebugImageHistogramBins * 4];

// Depth of field data
ComputeBuffer m_BokehNearKernel;
Expand Down Expand Up @@ -234,6 +237,7 @@ public void Cleanup()
CoreUtils.SafeRelease(m_FarBokehTileList);
CoreUtils.SafeRelease(m_ContrastAdaptiveSharpen);
CoreUtils.SafeRelease(m_HistogramBuffer);
CoreUtils.SafeRelease(m_DebugImageHistogramBuffer);
RTHandles.Release(m_DebugExposureData);

m_ExposureCurveTexture = null;
Expand All @@ -248,7 +252,8 @@ public void Cleanup()
m_NearBokehTileList = null;
m_FarBokehTileList = null;
m_HistogramBuffer = null;
m_DebugExposureData = null;
m_DebugImageHistogramBuffer = null;
m_DebugExposureData = null;

}

Expand Down Expand Up @@ -969,6 +974,12 @@ internal void ComputeProceduralMeteringParams(HDCamera camera, out Vector4 proce

proceduralParams2 = new Vector4(1.0f / m_Exposure.proceduralSoftness.value, LightUtils.ConvertEvToLuminance(m_Exposure.maskMinIntensity.value), LightUtils.ConvertEvToLuminance(m_Exposure.maskMaxIntensity.value), 0.0f);
}

internal ComputeBuffer GetDebugImageHistogramBuffer()
{
return m_DebugImageHistogramBuffer;
}

void DoFixedExposure(CommandBuffer cmd, HDCamera camera)
{
var cs = m_Resources.shaders.exposureCS;
Expand Down Expand Up @@ -1229,6 +1240,24 @@ void DoHistogramBasedExposure(CommandBuffer cmd, HDCamera camera, RTHandle sourc
cmd.DispatchCompute(cs, kernel, 1, 1, 1);
}

internal void GenerateDebugImageHistogram(CommandBuffer cmd, HDCamera camera, RTHandle sourceTexture)
{
var cs = m_Resources.shaders.debugImageHistogramCS;
int kernel = cs.FindKernel("KHistogramGen");

ValidateComputeBuffer(ref m_DebugImageHistogramBuffer, k_DebugImageHistogramBins * 4, sizeof(uint));
m_DebugImageHistogramBuffer.SetData(m_EmptyDebugImageHistogram); // Clear the histogram
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._SourceTexture, sourceTexture);
cmd.SetComputeBufferParam(cs, kernel, HDShaderIDs._HistogramBuffer, m_DebugImageHistogramBuffer);

int threadGroupSizeX = 16;
int threadGroupSizeY = 16;
int dispatchSizeX = HDUtils.DivRoundUp(camera.actualWidth / 2, threadGroupSizeX);
int dispatchSizeY = HDUtils.DivRoundUp(camera.actualHeight / 2, threadGroupSizeY);
int totalPixels = camera.actualWidth * camera.actualHeight;
cmd.DispatchCompute(cs, kernel, dispatchSizeX, dispatchSizeY, 1);
}

#endregion

#region Temporal Anti-aliasing
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/PhysicalCamera.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"


#pragma kernel KHistogramGen
#define GROUP_SIZE_X 16
#define GROUP_SIZE_Y 16

#define HISTOGRAM_BINS 256

// RGB: Histogram for RGB separately A: Histogram for luminance
RWStructuredBuffer<uint4> _HistogramBuffer;
TEXTURE2D_X(_SourceTexture);


uint4 GetBinsLoc(float3 rgbValue)
{
float3 srgbVal = LinearToSRGB(rgbValue);

return uint4(saturate(float4(srgbVal, Luminance(srgbVal))) * (HISTOGRAM_BINS - 1));
}

groupshared uint4 gs_localHistogram[HISTOGRAM_BINS];

[numthreads(GROUP_SIZE_X, GROUP_SIZE_Y, 1)]
void KHistogramGen(uint groupIndex : SV_GroupIndex,
uint3 dispatchThreadId : SV_DispatchThreadID)
{
if (groupIndex < HISTOGRAM_BINS)
{
gs_localHistogram[groupIndex] = uint4(0u, 0u, 0u, 0u);
}

GroupMemoryBarrierWithGroupSync();

uint2 fullResCoords = dispatchThreadId.xy << 1u;

if (all(fullResCoords < uint2(_ScreenSize.xy)))
{
float2 uv = ClampAndScaleUVForBilinear((fullResCoords + 0.5) * _ScreenSize.zw);
float3 rgbVal = SAMPLE_TEXTURE2D_X_LOD(_SourceTexture, s_linear_clamp_sampler, uv, 0.0).xyz;

uint4 bins = GetBinsLoc(rgbVal);

InterlockedAdd(gs_localHistogram[bins.x].x, 1u);
InterlockedAdd(gs_localHistogram[bins.y].y, 1u);
InterlockedAdd(gs_localHistogram[bins.z].z, 1u);
InterlockedAdd(gs_localHistogram[bins.w].w, 1u);
}

GroupMemoryBarrierWithGroupSync();

if (groupIndex < HISTOGRAM_BINS)
{
InterlockedAdd(_HistogramBuffer[groupIndex].x, gs_localHistogram[groupIndex].x);
InterlockedAdd(_HistogramBuffer[groupIndex].y, gs_localHistogram[groupIndex].y);
InterlockedAdd(_HistogramBuffer[groupIndex].z, gs_localHistogram[groupIndex].z);
InterlockedAdd(_HistogramBuffer[groupIndex].w, gs_localHistogram[groupIndex].w);
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -2816,6 +2816,12 @@ void Callback(CommandBuffer c, HDCamera cam)
RenderTargetIdentifier postProcessDest = HDUtils.PostProcessIsFinalPass(hdCamera) ? target.id : m_IntermediateAfterPostProcessBuffer;
RenderPostProcess(cullingResults, hdCamera, postProcessDest, renderContext, cmd);

// If requested, compute histogram of the very final image
if (m_CurrentDebugDisplaySettings.data.lightingDebugSettings.exposureDebugMode == ExposureDebugMode.FinalImageHistogramView)
{
m_PostProcessSystem.GenerateDebugImageHistogram(cmd, hdCamera, m_IntermediateAfterPostProcessBuffer);
}

PushFullScreenExposureDebugTexture(cmd, m_IntermediateAfterPostProcessBuffer);

RenderCustomPass(renderContext, cmd, hdCamera, customPassCullingResults, CustomPassInjectionPoint.AfterPostProcess, aovRequest, aovCustomPassBuffers);
Expand Down Expand Up @@ -4909,7 +4915,8 @@ static void RenderExposureDebug(in DebugParameters parameters,
bool drawTonemapCurve = tonemappingMode != TonemappingMode.None &&
parameters.debugDisplaySettings.data.lightingDebugSettings.showTonemapCurveAlongHistogramView;

parameters.debugExposureMaterial.SetVector(HDShaderIDs._ExposureDebugParams, new Vector4(drawTonemapCurve ? 1.0f : 0.0f, (int)tonemappingMode, 0, 0));
bool centerAroundMiddleGrey = parameters.debugDisplaySettings.data.lightingDebugSettings.centerHistogramAroundMiddleGrey;
parameters.debugExposureMaterial.SetVector(HDShaderIDs._ExposureDebugParams, new Vector4(drawTonemapCurve ? 1.0f : 0.0f, (int)tonemappingMode, centerAroundMiddleGrey ? 1 : 0, 0));
if (drawTonemapCurve)
{
if (tonemappingMode == TonemappingMode.Custom)
Expand All @@ -4930,6 +4937,16 @@ static void RenderExposureDebug(in DebugParameters parameters,
}
passIndex = 2;
}
if (parameters.debugDisplaySettings.data.lightingDebugSettings.exposureDebugMode == ExposureDebugMode.FinalImageHistogramView)
{
bool finalImageRGBHisto = parameters.debugDisplaySettings.data.lightingDebugSettings.displayFinalImageHistogramAsRGB;

parameters.debugExposureMaterial.SetVector(HDShaderIDs._ExposureDebugParams, new Vector4(0, 0, 0, finalImageRGBHisto ? 1 : 0));

parameters.debugExposureMaterial.SetBuffer(HDShaderIDs._FullImageHistogram, histogramBuffer);
passIndex = 3;
}


HDUtils.DrawFullScreen(cmd, parameters.debugExposureMaterial, output, null, passIndex);
}
Expand Down Expand Up @@ -4989,7 +5006,7 @@ void RenderDebug(HDCamera hdCamera, CommandBuffer cmd, CullingResults cullResult
m_PostProcessSystem.GetLutSize(),
proceduralParams1,
proceduralParams2,
m_PostProcessSystem.GetHistogramBuffer(), cmd);
debugParams.debugDisplaySettings.data.lightingDebugSettings.exposureDebugMode == ExposureDebugMode.FinalImageHistogramView ? m_PostProcessSystem.GetDebugImageHistogramBuffer() : m_PostProcessSystem.GetHistogramBuffer(), cmd);
}

// First resolve color picker
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,7 @@ static class HDShaderIDs
public static readonly int _ExposureDebugParams = Shader.PropertyToID("_ExposureDebugParams");
public static readonly int _HistogramExposureParams = Shader.PropertyToID("_HistogramExposureParams");
public static readonly int _HistogramBuffer = Shader.PropertyToID("_HistogramBuffer");
public static readonly int _FullImageHistogram = Shader.PropertyToID("_FullImageHistogram");
public static readonly int _AdaptationParams = Shader.PropertyToID("_AdaptationParams");
public static readonly int _ExposureCurveTexture = Shader.PropertyToID("_ExposureCurveTexture");
public static readonly int _ExposureWeightMask = Shader.PropertyToID("_ExposureWeightMask");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ public sealed class ShaderResources
public ComputeShader histogramExposureCS;
[Reload("Runtime/PostProcessing/Shaders/ApplyExposure.compute")]
public ComputeShader applyExposureCS;
[Reload("Runtime/PostProcessing/Shaders/DebugHistogramImage.compute")]
public ComputeShader debugImageHistogramCS;
[Reload("Runtime/PostProcessing/Shaders/UberPost.compute")]
public ComputeShader uberPostCS;
[Reload("Runtime/PostProcessing/Shaders/LutBuilder3D.compute")]
Expand Down