float luminance(float3 color) { return dot(color, float3(0.2126, 0.7152, 0.0722)); } float currentResetPhase(float timeSeconds, float resetInterval) { float safeInterval = max(resetInterval, 0.001); float cycleIndex = floor(timeSeconds / safeInterval); return frac(cycleIndex * 0.5) >= 0.5 ? 1.0 : 0.0; } float4 shadeVideo(ShaderContext context) { float safeResetSeconds = max(resetSeconds, 0.001); float phase = currentResetPhase(context.time, safeResetSeconds); float4 previousFeedback = sampleFeedback(context.uv); bool phaseMatches = context.feedbackAvailable > 0 && abs(previousFeedback.a - phase) < 0.25; float3 previousAccumulation = phaseMatches ? previousFeedback.rgb : float3(0.0, 0.0, 0.0); float currentLuma = luminance(context.sourceColor.rgb); float thresholdWidth = max(softness, 0.0001); float brightMask = smoothstep(highlightThreshold - thresholdWidth, highlightThreshold + thresholdWidth, currentLuma); float3 currentContribution = context.sourceColor.rgb * brightMask * max(accumulateAmount, 0.0); float3 nextAccumulation = saturate(previousAccumulation + currentContribution); float3 displayColor = context.sourceColor.rgb * saturate(baseMix) + nextAccumulation * max(displayGain, 0.0); return float4(saturate(displayColor), phase); }