48 lines
1.8 KiB
Plaintext
48 lines
1.8 KiB
Plaintext
float luminance(float3 color)
|
|
{
|
|
return dot(color, float3(0.2126, 0.7152, 0.0722));
|
|
}
|
|
|
|
float4 buildHistory(ShaderContext context)
|
|
{
|
|
float4 previousFeedback = sampleFeedback(context.uv);
|
|
float4 previousHistory = context.feedbackAvailable > 0
|
|
? previousFeedback
|
|
: float4(0.0, 0.0, 0.0, 0.0);
|
|
|
|
// Highlight selection is always based on the live source image only.
|
|
// The stored feedback never feeds back into the threshold test.
|
|
float currentLuma = luminance(context.sourceColor.rgb);
|
|
float thresholdWidth = max(softness, 0.0001);
|
|
float brightMask = smoothstep(highlightThreshold - thresholdWidth, highlightThreshold + thresholdWidth, currentLuma);
|
|
|
|
// Treat RGBA as a 4-slot rolling scalar history:
|
|
// R = current frame, G = 1 frame ago, B = 2 frames ago, A = 3 frames ago.
|
|
// Each frame shifts the history forward and drops the oldest sample.
|
|
float currentContribution = currentLuma * brightMask * max(accumulateAmount, 0.0);
|
|
float4 nextHistory = float4(
|
|
currentContribution,
|
|
previousHistory.r,
|
|
previousHistory.g,
|
|
previousHistory.b
|
|
);
|
|
|
|
return saturate(nextHistory);
|
|
}
|
|
|
|
float4 displayHistory(ShaderContext context)
|
|
{
|
|
// In the display pass, context.sourceColor is the same-frame historyBuffer
|
|
// produced by buildHistory().
|
|
float4 history = context.sourceColor;
|
|
float recentEnergy = history.r + history.g + history.b;
|
|
float3 originalColor = sampleLayerInput(context.uv).rgb;
|
|
float highlightBoost = recentEnergy * max(displayGain, 0.0);
|
|
float3 sourceHue = originalColor / max(max(originalColor.r, originalColor.g), max(originalColor.b, 0.0001));
|
|
float3 displayColor =
|
|
originalColor +
|
|
sourceHue * highlightBoost * 1.5;
|
|
|
|
return float4(saturate(displayColor), 1.0);
|
|
}
|