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
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
Apologies and thanks for being so thorough when you help us out
1 Like
Glad I could be of assistance