Skip to main content
gamedev.net
🔒 Locked

Managing post processing effects

Started by RobM Dec 4, 2011 at 6:33 PM 1 replies 900+ views
Original Post
RobM
RobM
I'm implementing post processing effects and I've come across a bit of a hurdle. I understand the principles of post processing effects, but I was wondering how typical rendering engines implement it. Do you render everything to the back buffer surface and then for each post process effect use the back buffer surface as a source and render to a temporary texture and then back to the back buffer surface? With such effects that require two passes, I understand you use an intermediate surface/texture and render to that in a flip/flop scenario but do you always have to do the render everything back to back buffer surface in order to either view it or pass it to the next post processing effect?

My system is fairly generic, so you can bolt on post processing effects at will, but I got a bit muddled with the flip flopping of surfaces - if effect A is a bright pass filter, that takes a source and a destination and has only one pass, but you obviously can't write to the same surface you read from so you need to render to a temporary surface in order to pass it on - but what if it's the last effect - do you always have to render from temporary surface A (or B in flip flopping) back to the back buffer surface?

Essentially I have this:

brightPassFilter->SetSource(backBufferTexture);
brightPassFilter->SetDestination(temporarySurfaceA);
brightPassFilter->Render();

blurFilter->SetSource(temporaryTextureA);
blurFilter->SetDestination(temporaryTextureB);
blurFilter->Render();

etc.

The problem with the above is that the blurFilter has two passes, horizontal and vertical which needs to render to 2 different surfaces, so should I be supplying two specific textures/surfaces as well as the source and destination? I don't want to create and use surfaces if I don't need to.

Any help or guidance would be greatly appreciated...
Ashaman73
Ashaman73

I'm implementing post processing effects and I've come across a bit of a hurdle. I understand the principles of post processing effects, but I was wondering how typical rendering engines implement it. Do you render everything to the back buffer surface and then for each post process effect use the back buffer surface as a source and render to a temporary texture and then back to the back buffer surface? With such effects that require two passes, I understand you use an intermediate surface/texture and render to that in a flip/flop scenario but do you always have to do the render everything back to back buffer surface in order to either view it or pass it to the next post processing effect?

My system is fairly generic, so you can bolt on post processing effects at will, but I got a bit muddled with the flip flopping of surfaces - if effect A is a bright pass filter, that takes a source and a destination and has only one pass, but you obviously can't write to the same surface you read from so you need to render to a temporary surface in order to pass it on - but what if it's the last effect - do you always have to render from temporary surface A (or B in flip flopping) back to the back buffer surface?

Essentially I have this:

brightPassFilter->SetSource(backBufferTexture);
brightPassFilter->SetDestination(temporarySurfaceA);
brightPassFilter->Render();

blurFilter->SetSource(temporaryTextureA);
blurFilter->SetDestination(temporaryTextureB);
blurFilter->Render();

etc.

The problem with the above is that the blurFilter has two passes, horizontal and vertical which needs to render to 2 different surfaces, so should I be supplying two specific textures/surfaces as well as the source and destination? I don't want to create and use surfaces if I don't need to.

Any help or guidance would be greatly appreciated...

A common approach is to render to different offscreen buffers and only to the backbuffer at the very end. A offscreen buffer is often used as input(texture) for several other post processing steps and offscreen buffers often are smaller than the screen size. Here's a simple example:

create buffers:
off_A = CreateBuffer(screen_x,screen_y)
off_B_1_2 = CreateBuffer(screen_x/2,screen_y/2)
off_C_1_2 = CreateBuffer(screen_x/2,screen_y/2)

// passes
render scene to off_A
downscale off_A to off_B_1_2
brightness pass from off_B_1_2 to off_C_1_2
blur X pass from off_C_1_2 to off_B_1_2
blur Y pass from off_B_1_2 to off_C_1_2
final render pass from off_A & off_C_1_2 to back buffer

This is a simple example of a bloom post processing effect where you use only 1/4 of the screensize to render the bloom effect. Only the final rendering pass uses two sources (as textures) and renders them directly to the back buffer. Although I toggle between off_B_1_2 and off_C_1_2 to save buffer space.

You need to be familiar with rendering to texture and render/frame buffer handling (in OGL it is called FBO, frame buffer objects).
RobM
RobM
Thanks for the reply, that's very helpful.

I have everything set up in my engine for post process effects and in fact my bloom effect is identical flow-wise to your example - the bit you've cleared up is that you create 3 off screen buffers and do a final 'copy last temp buffer used' to the back buffer surface. I thought that step might be a bit of a waste of processing time because you could just set your last effect in the chain to output to the back buffer surface - I guess once it's set up I can do some profiling.

Thanks again

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.