Sorry for reviving this long dead topic but I thought Iâ€™d share my experience with this in case anyone comes along looking to do this. I put together an example in webGL a couple years ago but only just now got around to trying it in oF.

In my iteration I just keep a vector of past textures around and have a few different cyclical indices evenly spaced throughout the vector. You are limited to whatever your max texture slots are per shader (in my case 16), but 8 textures seems to be plenty to get a nice effect.

Iâ€™d also be curious about developing a more advanced blending mode, or perhaps just doing a weighted sum based on the age of the texture. I know the shader is also very branchy for the different modes, but it seems performant enough. I think the real disadvantage of doing it this way is running out of memory when you try to allocate memory for like anything greater than a couple hundred fbos.

Lastly, one more approach might be to use a 3d texture, though having never used them, I canâ€™t say for certain if this would give any performance gains.

```
precision highp float;
uniform sampler2D u_image;
uniform sampler2D u_image2;
uniform sampler2D u_image3;
uniform sampler2D u_image4;
uniform sampler2D u_image5;
uniform sampler2D u_image6;
uniform sampler2D u_image7;
uniform sampler2D u_image8;
uniform int mode;
varying vec2 tc;
void main() {
vec3 tex_one = vec3(texture2D(u_image, tc));
vec3 tex_two = vec3(texture2D(u_image2, tc));
vec3 tex_three = vec3(texture2D(u_image3, tc));
vec3 tex_four = vec3(texture2D(u_image4, tc));
vec3 tex_five = vec3(texture2D(u_image5, tc));
vec3 tex_six = vec3(texture2D(u_image6, tc));
vec3 tex_seven = vec3(texture2D(u_image7, tc));
vec3 tex_eight = vec3(texture2D(u_image8, tc));
vec3 outCol = mode == 0 ? min(tex_one, tex_two) : max(tex_one, tex_two);
outCol = mode == 0 ? min(outCol, tex_three) : max(outCol, tex_three);
outCol = mode == 0 ? min(outCol, tex_four) : max(outCol, tex_four);
outCol = mode == 0 ? min(outCol, tex_five) : max(outCol, tex_five);
outCol = mode == 0 ? min(outCol, tex_six) : max(outCol, tex_six);
outCol = mode == 0 ? min(outCol, tex_seven) : max(outCol, tex_seven);
outCol = mode == 0 ? min(outCol, tex_eight) : max(outCol, tex_eight);
gl_FragColor = vec4(outCol,1.0);
}
```

```
int maxFrames;
int textureIndex;
vector<ofFbo> fbos;
int index1, index2, index3, index4, index5, index6, index7, index8;
ofVideoGrabber grabber;
ofApp::setup(){
multixShader.load("shaders/multix");
grabber.setup(w, h);
maxFrames = 128;
textureIndex = 0;
for(int i = 0; i<maxFrames; i++){
ofFbo f;
f.allocate(w, h, GL_RGB);
fbos.push_back(f);
}
int numSplits = 8;
index1 = 0;
index2 = maxFrames/numSplits * 1;
index3 = maxFrames/numSplits * 2;
index4 = maxFrames/numSplits * 3;
index5 = maxFrames/numSplits * 4;
index6 = maxFrames/numSplits * 5;
index7 = maxFrames/numSplits * 6;
index8 = maxFrames/numSplits * 7;
}
```

```
ofApp::draw(){
fbos[textureIndex].begin();
grabber.draw(0,0);
fbos[textureIndex].end();
multixShader.begin();
multixShader.setUniformTexture("u_image", fbos[index1].getTexture(), 0);
multixShader.setUniformTexture("u_image2", fbos[index2].getTexture(), 1);
multixShader.setUniformTexture("u_image3", fbos[index3].getTexture(), 2);
multixShader.setUniformTexture("u_image4", fbos[index4].getTexture(), 3);
multixShader.setUniformTexture("u_image5", fbos[index5].getTexture(), 4);
multixShader.setUniformTexture("u_image6", fbos[index6].getTexture(), 5);
multixShader.setUniformTexture("u_image7", fbos[index7].getTexture(), 6);
multixShader.setUniformTexture("u_image8", fbos[index8].getTexture(), 7);
multixShader.setUniform1f("mode", 0.0);
fbos[index1].draw(0,0);
multixShader.end();
index1 = (index1 + 1) % maxFrames;
index2 = (index2 + 1) % maxFrames;
index3 = (index3 + 1) % maxFrames;
index4 = (index4 + 1) % maxFrames;
index5 = (index5 + 1) % maxFrames;
index6 = (index6 + 1) % maxFrames;
index7 = (index7 + 1) % maxFrames;
index8 = (index8 + 1) % maxFrames;
textureIndex = (textureIndex + 1) % maxFrames;
}
```