Rendering Visual Feedback Loop

Hello,

I’m trying to write a very simple renderer with 3 passes: a main scene render pass, a feedback loop pass, and a final post-processing pass. I’m having problems with the feedback loop pass which is not working as expected. I’m simply trying feed back the current frame to the next frame to achieve the classic trail / visual feedback look similar to this: https://www.shadertoy.com/view/ldsczf

To do so I have a mFeedbackFboPingPong with two color attachments that I ping pong (since it’s not possible to read and draw at the same time from one texture:

gl::ScopedFramebuffer scopedFBO( mFeedbackFboPingPong );
gl::drawBuffer( GL_COLOR_ATTACHMENT0 + (GLenum)mFeedbackPing );
gl::ScopedGlslProg shader( mFeedbackShader );
gl::ScopedTextureBind sourceTexture( mSceneFbo->getColorTexture(), 0 );
gl::ScopedTextureBind feedbackTexture( mFeedbackTextureFboPingPong[ mFeedbackPong ], 1 );
gl::drawSolidRect( drawRect );
mFeedbackPing = mFeedbackPong;
mFeedbackPong = ( mFeedbackPing + 1 ) % 2;

mSceneFbo is rendered in the previous pass. And mFeedbackTextureFboPingPong[ mFeedbackPong ] is passed to the following post-processing pass for the final render.

The feedback shader simply mixes between the scene and feedback texture:

vec4 source = texture( sourceTexture, vTexCoord0 );
vec4 feedback = texture( feedbackTexture, scaleCentered( vTexCoord0, 1. ) );
oColor = mix(source, feedback, .9);

I’m not getting the desired effect though. Any idea what I’m doing wrong? Am I just not thinking about this the right way? I was thinking of trying to do this with two FBOs instead of one FBO with two color attachments but I feel like it should work with one FBO, right?

Thanks a lot for the help :slight_smile:

Hi,

try creating 2 Fbo's with one color buffer each. It’s easier to specify source and destination texture that way. Just bind one Fbo as the destination buffer and bind the other Fbo's color texture as the source. There is very little extra overhead (if any) compared to your solution.

-Paul

Thanks Paul! I just tried to replace my approach to use two Fbo’s and for some reason it still doesn’t feed back. Wondering if I’m misunderstanding something at a high-level…The updated code looks like:

{
  bool fboSwap = (mFeedbackFboCount % 2 == 0);
  auto fboOut = fboSwap ? mFeedbackFbo1 : mFeedbackFbo2;
  auto fboIn =  fboSwap ? mFeedbackFbo2 : mFeedbackFbo1;
  
  {
    // Feedback
    gl::ScopedFramebuffer scopedFBO( fboOut );
    gl::ScopedGlslProg shader( mFeedbackShader );
    gl::ScopedTextureBind sourceTexture( mSceneFbo->getColorTexture(), 0 );
    gl::ScopedTextureBind feedbackTexture( fboIn->getColorTexture(), 1 );
    gl::drawSolidRect( drawRect );
    mFeedbackFboCount++;
  }
  
  {
    // Post Processing
    gl::ScopedGlslProg shader( mPostProcessingShader );
    gl::ScopedTextureBind inputTexture( fboOut->getColorTexture(), 0 );
    gl::ScopedTextureBind lookup_table( mLUT, 1 );
    mPostProcessingShader->uniform( "u_mix_amount", mLUTMixAmount );
    gl::drawSolidRect( drawRect );
  }
}

mSceneFbo is drawn into in a previous pass which seems to work. I’ll keep poking at it, thanks for your help!

It’s all looking good, provided that:

  • mFeedbackFbo1, mFeedbackFbo2 and mSceneFbo have the same dimensions.
  • drawRect is equal to mSceneFbo->getBounds().
  • the mFeedbackShader has a uniform of type sampler2d which has been initialized to 1.
  • the mFeedbackShader actually samples texture 1 and adds the color to the result.

Also make sure, if the Fbo’s dimensions are different from your window’s dimensions, to update the viewport before using the Fbo’s.

-Paul

1 Like

Thanks Paul! Turns out I had forgotten to initialize the sampler2d’s uniforms :clown_face:

Apologies and thanks for being so thorough when you help us out :slight_smile:

1 Like

Glad I could be of assistance :slight_smile: