Creating a post-processing framework for your game engine is a powerful way to customize the look of your game and add a number of high-end features from basic blooming to color space manipulation and image perturbation.
Post-processing in itself is a relatively simple area of graphics programming, however there are some nuances which have to be paid attention to when using the 3D hardware to operate in 2D space.
The article will start by covering some basics for 2D programming with Direct3D and touching a bit on pixel alignment which is sometimes overlooked when implementing 2D features, and will then go further into optimization techniques for hardware and give basic ideas for certain special effects.
The basic setup for a post-processing framework is to allocate one or more auxiliary buffers (other than the back-buffer) for rendering the scene, and then copy the rendered scene from this buffer to the back-buffer through a number of post-processing filters. A number of varying size auxiliary buffers may be needed for different special effects, for multiple pass filters or for example storing the previous frame’s data.
An example setup with 4 auxiliary work buffers and a back-buffer.
In the illustrated case the Aux 0 is used as the real render target throughout the scene, and smaller Aux 1-3 buffers are used during the post-processing as intermediary stages when transferring the scene through various filters to the back-buffer for displaying.
To address the source texture by pixel, the source texture coordinates have to be translated into pixels, which is done with the following formula:
dx = 1/TextureWidth
dy = 1/TextureHeight
This gives you dx,dy which are the pixel deltas in the UV space of 0-1.
Special care must be taken in correctly mapping the source and target textures to the pixels centers for the hardware interpolation to yield the correct results. If the pixels are not perfectly aligned, the hardware may end up sampling in-between the intended pixels causing the output color to be an undesired blend of more than pixel. Also in the case of effects using a feed-back loop of the screen, a color bleeding may be produced.
In Direct3D, the texture coordinates originate at the top-left corner of the first texel, while the screen space coordinates originate at the center of the first pixel, as illustrated in the following figure.
This means that when aligning the source texels to target pixels, the drawn target quad must originate from the screen coordinate (-0.5,-0.5), in pixels, in order for it to match with the top-left corner of the source texture (0,0).
The basic setup for the post-processing framework would be as follows.
The HLSL code sample for vertex and pixel shader input
and output structures for a simple post-processing framework.
The HLSL code sample for basic vertex
and pixel shaders for the post-processing framework.
The code shown above doesn’t actually do anything except for passing the rendered scene from the auxiliary work buffer to the back-buffer. However it contains the fundamentals for adding on more complex post-processing effects.