One of the most straightforward things we can do with a framebuffer object is apply a post-process effect to a scene. This is much like applying a photographic filter to the entire scene. It entails two steps:
The first step has been covered. The second proceeds as follows.
A post-process effect is rendered as a rectangle that exactly fits the screen, textured with the framebuffer color buffer. This produces a one-to-one mapping from the input rendering to the output image, while introducing an extra opportunity for fragment shading.
To produce a piece of geometry that exactly fits the screen, we need not know the size or shape of the screen. Recall that the
gl_Position varying in the vertex shader receives a position in clip coordinates, the position after the $M$, $V$, and $P$ matrices have been applied. In this coordinate system, the visible portion of the scene is known to extend from $-1$ to $+1$ along the $x$, $y$, and $z$ axes.
Thus, to produce a full-screen rectangle, define geometry that covers this volume, and do not apply any of the $M$, $V$, or $P$ transforms. Here is that geometry.
And here is an appropriate vertex shader. This shader receives no uniforms and does nothing but copy its attributes into varyings.
This vertex shader works with a variety of fragment shaders, and the fragment shader is where the post-process effect is implemented.