ISF Speed / Time


Hi - I’m just getting started with shaders, mostly playing with other peoples code. Coming from quartz composer there is something i would like to emulate and is bugging me with many shaders.

So QC and GLSL share the concept of animation being driven by a flaot called TIME. In quartz I would generate time using integrator patch. Giving this patch a variable between -1 and 1 would allow me to control the rate of animation, as this variable sets the rate time accumulates at. Mostly importantly changing this rate gave smooth changes in speed.

Most ISFs i have loaded into VDMX seam to control rate by multiplying TIME by a rate factor - the problem with this is that changes in rate cause jumps in time and jerky playback whenever the rate is changed.

So what im after is a smooth way to change the rate of time in ISF ?

Hope this makes sense - im not fluent in shader speak.

cheers_ Howie

1 Like


Update - I have just been looking at the madmapper material format - which appears to be ISF+
They have included a function to solve this issue. Its declared like an ISF input but its called a “generator”.Its used in most of their shaders.
Looks like this…
“NAME”: “animation_time”,
“TYPE”: “time_base”,
“PARAMS”: {“speed”: “speed”, “bpm_sync”: “bpmsync”, “speed_curve”: 2, “reverse”: “reverse”, “link_speed_to_global_bpm”:true}



Hey Howie,

Yup, we’ve been in touch it the Mad Mapper crew, and we might do something along these lines officially as part of the next version of the ISF specification, but we probably won’t support their extension in the short term.

A common trick we use is to have a render pass that stores a 1x1 pixel for storing local variables like accumulators. A good example of this is in the HorizVertHold.fs filter, which essentially does this with ‘rate’ sliders for both x & y,
(if you look at the non-web version of this, you’ll see how to use a floating point buffer for the accumulator pixel)

or this countdown timer that I made,
(which uses an inc / dec / reset)



Thank You David - Those examples where just enough. I went from staring at it thinking this is too deep for me, to slowly figuring it out and feeling pleased with myself :-)

A little side note your probably aware of: ISF editor seams to be 1 out on the line numbers for error reports.

For the record here is the solution;

“INPUTS” : [
{“NAME” : “rate”,“TYPE” : “float”,“MAX” : 0.2,“DEFAULT” : 0.03,“MIN” : -0.2}
“PASSES” : [
“HEIGHT” : 1,
“WIDTH:” : 1,
“TARGET” : “TimeHold”,
“persistent” : true,
“FLOAT” : true,
“PERSISTENT” : true,
“DESCRIPTION” : “time buffer - float target buffer…”
“DESCRIPTION” : “empty pass`”

void main()
// first pass "HoldTime’
if (PASSINDEX == 0) {
vec4 srcPixel = IMG_PIXEL(TimeHold,vec2(0.5));
srcPixel.x = srcPixel.x + rate;
gl_FragColor = srcPixel;
// else getTime buffer
else {
vec4 getTime = IMG_PIXEL(TimeHold,vec2(0.5));
float Atime = getTime.x;
// then main pass

vec2 screenSpace = isf_FragNormCoord;
screenSpace -=.5;
screenSpace.x *= (RENDERSIZE.x/RENDERSIZE.y);
float distance = length(screenSpace);
float circleThresh = step(sin(Atime)*0.1+0.3,distance);
vec3 color = vec3(1.0 -circleThresh) * 1.0;

gl_FragColor = vec4(color, 1.0);





Which ISF Editor are you using? Online or desktop? Version #?
(usually best to send us emails with bug reports for those, feel free to follow via

Glad to hear you got it working.

PS We have been working on new ISF documentation; I had already started a chapter on multi-pass / persistent buffers, but I’ll also start jotting up some notes for this particular technique to include there with some examples so we’ve got something to point people to in the future on this detail. We’d of course love your feedback on the stuff we’ve written so far, you can find it here,



Is there a way to use this method to control functions outside the main pass ? If that makes sense.

I’ll check out the documentation - if i can stop playing with code.
NB offline editor / email sent



I’m not quite sure what you mean by this, but if you give the render pass a name, then you can access the stored value by using the IMG_PIXEL function within other passes.

For example, in this shader that I wrote, the first pass is a 1x1 pixel that manages the ‘state’ of the composition, including which cell is going to be randomly drawn into during the 2nd pass.
(then the 2nd pass of this shader is used to store the randomized values for each cell, and the final pass is used to visualize the stored data)



Thanks - this makes sense. I was reading & writing the buffer in the main function and assigning time to a float. It was this float that I couldn’t access in other functions. But I now understand that I can read the buffer directly from these functions.

1 Like


Worth noting, I dosn’t appear this method of time control works in Mad Mapper.



Nope, they sadly don’t support multi-pass shaders; beyond this trick, they are missing out on shaders like the optical flow distort.



Turns out they weren’t the only one missing out on the optical flow distort.
I like it :slight_smile: