Shader with fbo texture

// Sorry. I am Japanese programmer. So, my English is not good enough.

I want to use the texture which the previous fbo create. But I can’t get texture data in the shader.
I can not explain it well, so please read the following code.

ofApp.cpp

void ofApp::setup(){
    u_mouse = ofVec2f(0,0);
    ofSetBackgroundColor(0);
    ofSetWindowShape(1024, 1024);

    ofSetBoxResolution(1000);
    ofSetVerticalSync(false);

    dir.open("");
    dir.allowExt("frag");
    dir.listDir();

   fbo.allocate(ofGetWidth(), ofGetHeight());
   texture.allocate(ofGetWidth(), ofGetHeight(), GL_RGBA);
}

//--------------------------------------------------------------
void ofApp::draw(){     
    fbo.begin();
    
    shader.load("", "frag.frag");

    shader.begin();
    shader.setUniform1f("u_time", save_time + ofGetElapsedTimef());
    shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight());
    shader.setUniformTexture("texture", texture, 0);

    ofFill();
    ofDrawRectangle(0,0,ofGetWidth(), ofGetHeight());
    shader.end();
    fbo.end();
    
    fbo.draw(0, 0);
    texture = fbo.getTexture();
}

frag.frag

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform float u_time;
uniform sampler2D texture;

vec2 vInvert( vec2 _st ) {
    return vec2( 0.0, 1.0 ) + vec2( 1.0, -1.0 ) * _st;
}

void main(void){
    vec2 st = gl_FragCoord.xy / u_resolution.xy;

    vec3 color = vec3(0.);
    if (u_time <= 3.) {
        color = vec3(1.);
    }
    color += texture2D(texture, vInvert(st)).xyz;
    gl_FragColor = vec4(color, 1.);
}

I think if the texture data is sent correctly by ofApp.cpp to the shader, the result will be white forever.

Can anybody help me?

1 Like

It’s not that clear to me what you want to do. One thing that is wrong is that shader.load call goes in the setup method, not in the draw.
Did you read this? http://openframeworks.cc/ofBook/chapters/shaders.html it is pretty well explained how to pass textures to a shader.

1 Like

i think what you want is to use the texture from the previous draw? in that case you need 2 fbos, bind fbo1 and set fbo2.getTexture() as texture for the uniform then just use:

swap(fbo1, fbo2)

to swap the fbos so in the next frame you’ll use the currently drawn texture

1 Like

In that case, there is an example of what is called “ping pong technique” in examples/gl/gpuParticleSystemExample. Have a look at the pingPongBuffer struct in the header file.

Thank you !
I tried it in the way I taught you, but I still can’t get the texture from the previous draw.

ofApp.h

ofFbo fbo;
ofFbo back_buffer;

ofApp.cpp

void ofApp::setup(){
    fbo.allocate(ofGetWidth(), ofGetHeight());
    back_buffer.allocate(ofGetWidth(), ofGetHeight());

        back_buffer.begin();
        ofClear(255);
        ofFill();
        ofSetColor(255);
       ofDrawRectangle(0,0,ofGetWidth(), ofGetHeight());
       back_buffer.end();
}

void ofApp::draw(){     
    fbo.begin();
    
    shader.load("", "frag.frag");

    shader.begin();
    shader.setUniform1f("u_time", save_time + ofGetElapsedTimef());
    shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight());

    // The first way
    shader.setUniformTexture("texture", backbuffer.getTexture(), 0);
    // Another way
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, back_buffer.getTexture().texData.textureID);
    glActiveTexture(GL_TEXTURE0);
    glUniform1i(shader.getUniformLocation("texture"), GL_TEXTURE0);
    // end

    ofFill();
    ofDrawRectangle(0,0,ofGetWidth(), ofGetHeight());
    shader.end();
    fbo.end();
    
    fbo.draw(0, 0);

    swap(fbo, back_buffer);
}

What is wrong with me?

hello @arturo can you give an example of how can i get the previous draw? in order to make a “feedback shader” using the current fbo as a texture?
if you can, take a look this thread,

im using differents technics trying to get the buffer and passing to the shader as a texture, but i still can get it… thanks a LOT!