Adding fbo mesh objects together in a shader

Hello OF

I’m wondering if anyone could give me a tip or two on how to successfully add together two fbo objects in a shader. Specifically, I’m hoping to create a mesh object, load it into an fbo and then, using a ping-pong between that and another fbo, incrementally add to a set of pixel stored values (i.e. as the mesh changes over time)

I think I’m more or less correct with the cpu side, which looks as follows:

    //toggle pingpong boolean
    isA = !isA;
    //generate an ofPath object
    pass.clear();
    for(int i = 0; i <3; i++){
        ofVec2f p (ofRandom(0,width), ofRandom(0,height));
        pass.lineTo(p);
    }
    pass.close();
    
    // turn ofpath to mesh
    ofMesh passMesh;
    passMesh = pass.getTessellation();
    
    //send fbo data to shaders
    if(isA) fboPass(fboA, fboB, passMesh);
    else    fboPass(fboB, fboA, passMesh);

Where the fboPass function is:

    fboX.begin();
    //Wipe live fbo clean
    ofClear(0, 0, 0, 0);
    shader.begin();
    //pass stored fbo to the shader
    shader.setUniformTexture("dataIn", fboY.getTextureReference(), 1 );
   //pass new mesh to the shader
   passMesh.draw();
   shader.end();
   fboX.end();

But I’m struggling to figure out the shader. I’d assumed it could just happen in the frag shader as per the below, but this does not seem to combine the respective fbo datas. Can anyone point me in the right direction?

// get mesh data recently pushed to tex0
vec4 srce = texture(tex0, texCoordVarying).rgba;

// get stored data from previous fbo
vec4 data = texture(dataIn, texCoordVarying).rgba;

srce.x += data.x;
srce.y += data.y;
srce.z += data.z;
srce.w += data.w;

//return the combined output
outputColor = vec4(srce);

S

Ok, have made progress with this, through a lot of days of trial and error.

Seems that the mesh object needed to be loaded into an fbo object first. So the pass function became:

void ofApp::fboPass(ofFbo & fboX, ofFbo & fboY, ofFbo & fboZ){

fboX.begin();                                               // to make fboX
shader.begin();

fboY.draw(0,0);                                             // Add anything saved
shader.setUniformTexture("data", fboZ.getTexture(), 1 );    // Add anything seen in the mesh
shader.setUniform1f("count", rounds);                       // send the no. of cycles through

shader.end();
fboX.end();

fboY.begin();
ofClear(0,0,0,0);
fboY.end();
}

Where fboS is an fbo object with the texture pre-loaded into it, and the other two are the ping-pong pair.

This works. Then with the shader, a very basic addition at present (below), which I need to improve. Tips welcome, this one seems to stop adding after just 500 odd samples (I think because of the floating point fraction being added being so tiny beyond this point)

uniform sampler2DRect tex0;
uniform sampler2DRect data;
uniform float count;

in vec2 texCoordVarying;

out vec4 outputColor;

void main()
{
vec3 src = texture(tex0, texCoordVarying).rgb;
vec3 add = texture(data, texCoordVarying).rgb;

src *= count;
src += add;
src /= count + 1;

outputColor = vec4(src ,1);
}

Would be good to know if the format of the texture values wasn’t limited to (1,1,1,1) as this would solve the above.

S

How do you allocate FBO with? have you tried allocating with RGB32F or RGB16F?

I don’t think fbo limits the value to 1. but if so then you can always use it as a unit vector and scale up to whatever you aim

Ah, brill, thanks, didn’t realise that was an option in allocate. So I’m using:

fboA.allocate(width, height, GL_RGBA16);

Which seems to more or less get around the floating point problem. Is this the best approach?

++ yeah, I checked and it does seem to be limited to 1 for me.

So I have this working now, and adding together the mesh objects allows me to build a spectrum over time.

However… the resulting spectrum very gradually slides sideways (towards 0,0?) over 1,000s of loops of the ping-pong code. See the image below; where the blue/green has moved away from and over the defining lines.

Why would this happen (another float imprecision??) // can I fix it?

Most likely you might accidently increment your uv (texCoord)? But can’t be 100% sure by only the image you’ve given.

Yeah that’s what I was wondering, but I can’t figure out where that would be happening

shader.vert is only this:

void main()
{
texCoordVarying = texcoord;
gl_Position = modelViewProjectionMatrix * position;
}

Update… feels like the problem is a lot like this one? But I don’t understand it enough yet to work out what I would need to do to solve it exactly.

http://xboxforums.create.msdn.com/forums/t/101172.aspx

Editing shader.vert to be the below does seem to give me a non-sliding texture result for >5000 cycles, but it would be good to know the ‘proper’ fix.

void main()
{
vec2 tiny = vec2(0.001,0.001);
texcoord -= tiny;
texCoordVarying = texcoord;
gl_Position = modelViewProjectionMatrix * position;
}

Update: The above does not fully fix the issue, only partially.

Using vec2(0.002,0.002) as the coord fix is better, but still not quite perfect. I’m guessing there must be some screen size vs texture size (pixels to texels?) ratio that results in an exact fix, but I’d appreciate it if someone could explain this to me!

S

yea you eventually use texcoord in frag not in vert so please upload your full codes for ofcpp / vert / frag so that anyone can give you some answers.

1 Like

Sure thing - sorry, I didn’t want to spam a whole load of code up

Here is a zip file of the whole thing on dropbox: https://dl.dropboxusercontent.com/u/6460407/170414_fbo_spectrum.zip

1 Like