Depth of field is one of the cooler things we see in games and like bloom if abused is noticed in a bad way but if used properly is not noticed in a good way. It’s one of those things you don’t want the gamer to notice too much of because if they do it means it’s getting in the way though it adds a whole lot to the personality of any given scene when done right.
My implementation of depth of field like many of my other effects is an entirely post process effect and is done in the following steps (with accompanying screen shots from my upcoming game to aid in explaining). Please note that if you have any trouble understanding any of the concepts or ‘buzzwords’ I’m using let me know and I’ll do future posts to follow up on them as I’m trying to gauge the experience of readers to this blog, this is after all my first technical post.
Render the scene to a texture with depth using MRT (multiple render targets)
Here is the scene I am rendering without depth of field:
Depth maps are basically textures where each ‘pixel’ is a single floating point value from 0 to 1 where 1 is the projection matrix far clip and 0 is the projection matrix near clip. We can use the depth map to figure out what position each pixel being rendered is in world space. The depth map for the scene is shown below,
As you can see in the screenshot nearer to the camera the image is darker while further out it’s whiter. We’re using a single floating point value representing depth for the RGB hence the image is whiter in areas further away from the camera.
Copy the texture and blur the copy using Gaussian blur
Since we have rendered the scene to a texture we can make copies of it and modify them, so we simply copy the texture and apply a Gaussian blur to it,
Determine how much of the blur texture vs. the ’sharp’ texture should be used for every pixel on screen
To do this I define focal points as values between 0 and 1 which map directly ontop of the depth map values between 0 and 1.
For example we can say that for each pixel in the depth map where the value is from 0.8 to 1.0 we want to use the corresponding pixel from the blurred texture. Another thing we can do is blend the two blurred and sharp texture together, for example if we want an 80% blurred image we can say (0.8f*colourOfBlurredPixel) + (0.2f*colourOfSharpPixel).
This is all fine and dandy however it would mean very hard transitions between blur and sharp which creates the effect that we are sitting in a glass sphere and looking out at the world.
To get around this we use linear interpolation, that is we map the points 0.8 and 1.0 to a blur of 0.0 to 1.0, at point 0.8 the blur value is 0 and at point 1.0 the blur value is 1.0. Linear interpolation can be achieved using the lerp function in HLSL.
In my game I use a near and far blur with four points. Point 1 determines the nearest point in which the image is fully blurred, Point 2 is the end point for the blur after which the image is sharp until point 3 where it starts becoming blurry until it reaches point 4 where it is at maximum blur.
The following two screenshots demonstrate near and far blur,




