Files
UnrealEngineUWP/Engine/Shaders/PostProcessHistogramCommon.usf
Ben Marsh 149375b14b Update copyright notices to 2015.
[CL 2379638 by Ben Marsh in Main branch]
2014-12-07 19:09:38 -05:00

117 lines
3.9 KiB
Plaintext

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
PostProcessHistogramCommon.usf: PostProcessing histogram shared functions and structures.
=============================================================================*/
// [0] .x:ExposureLowPercent/100, .y:EyeAdaptationHighPercent/100, .z:EyeAdaptationMin, .w:EyeAdaptationMax
// [1] .x:exp2(ExposureOffset), .y:DeltaWorldTime, .zw: EyeAdaptionSpeedUp/Down
// [2] .x:Histogram multiply, .y:Histogram add, .zw:unused
float4 EyeAdaptationParams[3];
// inverse of ComputeLuminanceFromHistogramPosition
// is executed more often than ComputeLuminanceFromHistogramPosition()
// @param Luminance
// @return HistogramPosition 0..1
float ComputeHistogramPositionFromLuminance(float Luminance)
{
return log2(Luminance) * EyeAdaptationParams[2].x + EyeAdaptationParams[2].y;
}
// inverse of ComputeHistogramPositionFromLuminance()
// is not as often executed as ComputeHistogramPositionFromLuminance()
// @param HistogramPosition 0..1
// @return Lumiance
float ComputeLuminanceFromHistogramPosition(float HistogramPosition)
{
return exp2( (HistogramPosition - EyeAdaptationParams[2].y) / EyeAdaptationParams[2].x );
}
#define HISTOGRAM_SIZE 64
#define HISTOGRAM_TEXEL_SIZE (HISTOGRAM_SIZE / 4)
float4 ComputeARGBStripeMaskInt(uint x)
{
return float4(
(x % 4) == 0,
(x % 4) == 1,
(x % 4) == 2,
(x % 4) == 3);
}
float GetHistogramBucket(Texture2D HistogramTexture, uint BucketIndex)
{
uint Texel = BucketIndex / 4;
float4 HistogramColor = HistogramTexture.Load(int3(Texel, 0, 0));
// WAR for a GLSL shader compiler bug in the driver
#if 0
float UnweightedValue = dot(HistogramColor, ComputeARGBStripeMaskInt(BucketIndex));
#else
uint channel = BucketIndex % 4;
float UnweightedValue = HistogramColor.r;
UnweightedValue = (channel == 1) ? HistogramColor.g : UnweightedValue;
UnweightedValue = (channel == 2) ? HistogramColor.b : UnweightedValue;
UnweightedValue = (channel == 3) ? HistogramColor.a : UnweightedValue;
#endif
// because of the logarithmic scale we need to weight the buckets ?
// return UnweightedValue * pow(2, BucketIndex);
// return UnweightedValue * pow(2, BucketIndex / HISTOGRAM_SIZE * (2 * HDRLogRadius));
return UnweightedValue;
}
float ComputeHistogramSum(Texture2D HistogramTexture)
{
float Sum = 0;
for(uint i = 0; i < HISTOGRAM_SIZE; ++i)
{
Sum += GetHistogramBucket(HistogramTexture, i);
}
return Sum;
}
// @param MinFractionSum e.g. ComputeHistogramSum() * 0.5f for 50% percentil
// @param MaxFractionSum e.g. ComputeHistogramSum() * 0.9f for 90% percentil
float ComputeAverageLuminaneWithoutOutlier(Texture2D HistogramTexture, float MinFractionSum, float MaxFractionSum)
{
float2 SumWithoutOutliers = 0;
UNROLL for(uint i = 0; i < HISTOGRAM_SIZE; ++i)
{
float LocalValue = GetHistogramBucket(HistogramTexture, i);
// remove outlier at lower end
float Sub = min(LocalValue, MinFractionSum);
LocalValue = LocalValue - Sub;
MinFractionSum -= Sub;
MaxFractionSum -= Sub;
// remove outlier at upper end
LocalValue = min(LocalValue, MaxFractionSum);
MaxFractionSum -= LocalValue;
float LuminanceAtBucket = ComputeLuminanceFromHistogramPosition(i / (float)HISTOGRAM_SIZE);
SumWithoutOutliers += float2(LuminanceAtBucket, 1) * LocalValue;
}
return SumWithoutOutliers.x / max(0.0001f, SumWithoutOutliers.y);
}
// used by bloom and tonemapper VS
// requires EyeAdaptationParams to be set
float ComputeEyeAdaptationExposure(Texture2D HistogramTexture)
{
float HistogramSum = ComputeHistogramSum(HistogramTexture);
float UnclampedAdaptedLuminance = ComputeAverageLuminaneWithoutOutlier(HistogramTexture, HistogramSum * EyeAdaptationParams[0].x, HistogramSum * EyeAdaptationParams[0].y);
float ClampedAdaptedLuminance = clamp(UnclampedAdaptedLuminance, EyeAdaptationParams[0].z, EyeAdaptationParams[0].w);
return ClampedAdaptedLuminance;
}