struct FragmentInput { float4 position : SV_Position; float2 texCoord : TEXCOORD0; }; struct ShaderContext { float2 uv; float4 sourceColor; float2 inputResolution; float2 outputResolution; float time; float frameCount; float mixAmount; float bypass; int sourceHistoryLength; int temporalHistoryLength; float2 audioRms; float2 audioPeak; float audioMonoRms; float audioMonoPeak; float4 audioBands; }; cbuffer GlobalParams { float gTime; float2 gInputResolution; float2 gOutputResolution; float gFrameCount; float gMixAmount; float gBypass; int gSourceHistoryLength; int gTemporalHistoryLength; float2 gAudioRms; float2 gAudioPeak; float gAudioMonoRms; float gAudioMonoPeak; float4 gAudioBands; {{PARAMETER_UNIFORMS}}}; Sampler2D gVideoInput; Sampler2D gAudioData; {{SOURCE_HISTORY_SAMPLERS}}{{TEMPORAL_HISTORY_SAMPLERS}}{{TEXTURE_SAMPLERS}} float4 sampleVideo(float2 tc) { return gVideoInput.Sample(tc); } float4 sampleAudioWaveform(float x) { return gAudioData.Sample(float2(saturate(x), 0.25)); } float4 sampleAudioSpectrum(float x) { return gAudioData.Sample(float2(saturate(x), 0.75)); } float4 sampleSourceHistory(int framesAgo, float2 tc) { if (gSourceHistoryLength <= 0) return sampleVideo(tc); int clampedIndex = framesAgo; if (clampedIndex < 0) clampedIndex = 0; if (clampedIndex >= gSourceHistoryLength) clampedIndex = gSourceHistoryLength - 1; switch (clampedIndex) { {{SOURCE_HISTORY_SWITCH_CASES}} default: return sampleVideo(tc); } } float4 sampleTemporalHistory(int framesAgo, float2 tc) { if (gTemporalHistoryLength <= 0) return sampleVideo(tc); int clampedIndex = framesAgo; if (clampedIndex < 0) clampedIndex = 0; if (clampedIndex >= gTemporalHistoryLength) clampedIndex = gTemporalHistoryLength - 1; switch (clampedIndex) { {{TEMPORAL_HISTORY_SWITCH_CASES}} default: return sampleVideo(tc); } } #include "{{USER_SHADER_INCLUDE}}" [shader("fragment")] float4 fragmentMain(FragmentInput input) : SV_Target { ShaderContext context; context.uv = input.texCoord; context.sourceColor = sampleVideo(context.uv); context.inputResolution = gInputResolution; context.outputResolution = gOutputResolution; context.time = gTime; context.frameCount = gFrameCount; context.mixAmount = gMixAmount; context.bypass = gBypass; context.sourceHistoryLength = gSourceHistoryLength; context.temporalHistoryLength = gTemporalHistoryLength; context.audioRms = gAudioRms; context.audioPeak = gAudioPeak; context.audioMonoRms = gAudioMonoRms; context.audioMonoPeak = gAudioMonoPeak; context.audioBands = gAudioBands; float4 effectedColor = {{ENTRY_POINT_CALL}}; float mixValue = clamp(gBypass > 0.5 ? 0.0 : gMixAmount, 0.0, 1.0); return lerp(context.sourceColor, effectedColor, mixValue); }