D3DBook:Depth of Field

From GDWiki
Jump to: navigation, search

Depth of Field Filter

In photography and movies, the zone of acceptable sharpness (also called in focus) is referred to as the depth of field. The zone in front of the depth of field and after depth of field appears to be blurred in movies and photos, which is caused by the physical properties of camera lenses. While possibly considered undesireable, it is now a commonly used tool in bringing a viewer's attention to specific areas of a scene, enhancing the visual experience.

A depth of field filter mimics the zone of acceptable sharpness of camera lenses by blurring everything outside this zone. On a per-pixel basis the distance between the camera and the objects in a scene is compared to the distance between the camera and the near and far blur plane as shown in Figure 13.

Image:DepthOfField.jpg
Figure 13 - Depth of Field filter

This figure shows how the car on the left will be blurred because it is far away from the camera than the far blur plane, whereas the car on the right will only be partially blurred because it is nearer to the camera than the near blur plane. The car in the middle is in the depth of field.

The main challenge of implementing a depth of field filter is converting the depth value of the pixel that should be drawn to camera space, so that they can be compared to the near and far blur plane that are in camera space as well.

To derive an equation that converts depth buffer values into camera space, we must first understand how these values are obtained. Below is a standard left-handed row-major perspective projection matrix, which is used to transform camera space coordinates to clip space (NDC).

Image:ProjectionMatrixEQ.gif
Equation 23

The only difference compared to the left-handed projection matrix version is, that the left-handed version negates ZnQ in the third column. Some graphics engines based on a right-handed coordinate system have positive values to specify the near and far clipping plane. In this case the left-handed version would be still applicable.

Equation 24.1 shows the full equation that results from multiplying a 4D homogenous vector with the third column of the projection matrix above.

Image:ZBufferTransformEQ.gif
Equation 24

Equation 24.2 shows how to factor in the homogenous divide by w, in the case of the above matrix w =z. This is the final depth buffer equation. Solving for z leads to equation 24.3 that can be used to back-transform depth buffer values into camera space (read more in [Scheuermann] and [Gillham]).

Instead of fetching the depth buffer to calculate the camera space distance of the pixel, the camera space depth value of each pixel can be stored in the alpha channel of the render target while rendering the scene. This approach would not cooperate with alpha blending well. Additionally many post-processing effect might utilize camera space depth values as well, so it is expected to be re-used between several effects.

With the ability to determine the distance from the camera of each pixel that needs to be written into the frame buffer, the camera distance of a pixel can now be compared to where the focus of the camera is and to the range of the depth of field effect. Based on the result of this comparison the pixel color can be chosen from a blurred or an unblurred image emulating the blurring effect that happens outside of the depth of field.

Picking the blurred or unblurred image is done by linearly interpolating between those based on the variable s like this:

Image:LinearInterpolationbetweenBlurredAndOriginalImage.gif
Equation 25

Mimicing the focus of a real camera, the camera space range of the depth of field can be calculated like this: 

Image:Focus.gif
Equation 26

The Range value fades in and out into the near and far blur plane as shown in Figure 14.

Image:RangeMapping.jpg
Figure 14 - Result of different Range values

This figure shows a Focus value of 0.5 and Range values between 0 and 4. The y axis represents the resulting value s that is used to linearly interpolate between the blurred and the original image. A value of 1 means the pixel color is picked from the blurred image and a value of 0 means the pixel color is picked from the original image. An high value in Range makes the length of Depth-of-Field effect smaller and the fade-in and fade-out effect gets a V shape form. A low value in Range let the Depth of Field effect disappear.

Implementation

For a Depth of Field effect equation 24.3 needs to be implemented in the pixel shader and user defined values for the near and far blurring plane need to be compared to the camera space z value of the pixel currently drawn. Based on this comparison a blurred quarter or 1/16 size render target is picked or the original unblurred render target.

Equation 24.3 is implemented by calculating the Q value on the application level and then sending it down to the pixel shader as shown in the following source code snippet.

// back transform to camera space
float PixelCameraZ = (-NearClip * Q) / (Depth - Q);

The user defined Focus value and the user defined Range of the depth of field value are used together with the pixel's camera distance achieved in equation x to linearly interpolate between the blurred and the unblurred image:

// linear approximate the near and far blur plane
return lerp(OriginalImage, BlurredImage, saturate(Range * abs(Focus - PixelCameraZ)));

By changing the variable Focus, an auto-focus like effect can be achieved. This is similar to the effect achieved by changing the focus of the lens of a binocular or the auto-focus effect found in most modern cameras. To achieve a self-controlled auto-focus in-game the camera depth values of the pixels around for example the notch of a weapon can be measured and the Focus can be adjusted to this distance.

Personal tools