Circle of Confusion From The Depth Buffer
May 26, 2012 · Coding, GPU, Graphics, Math · 3 Comments
The first step in a depth-of-field postprocessing filter is to find the radius of the circle of confusion (CoC) for each pixel on screen. This isn’t difficult—the lens equation for a realistic camera is simple and easy to implement in a pixel shader. But there’s a neat simplification of it that I found the other day and wanted to share.
To get the CoC for a pixel, you’d typically write a pixel shader that samples the depth buffer and plugs that value into the lens equation. But the depth buffer usually stores post-projective depth using a reciprocal mapping, so you must convert that to linear depth in world-space units before using it in the lens equation. This conversion involves a reciprocal, and the lens equation involves another reciprocal. It turns out that you can put the two equations together and the reciprocals cancel out! The CoC is therefore just a linear scale and bias of the depth buffer value.
First, let me review converting the depth buffer value to linear depth. Let and be the
world-space depths of the near and far frustum planes. Consulting a standard projection-matrix
formula, such as the one implemented by
D3DXMatrixPerspectiveLH
,
we see that the formula for the depth buffer value in terms of world-space depth is:
Inverting this equation to get ‘z’ in terms of ‘d’ gives:
From Wikipedia, the equation for the CoC radius of a point at depth is:
where is the depth at which the camera is in perfect focus, and is a
constant scale factor related to the camera setup (see the Wikipedia page for details). Putting
together the last two equations gives
This is just (the absolute value of) a linear scale-bias of , since all the other quantities are
constants with respect to the image. So it’s very easy and cheap to compute a physical camera CoC
directly from the post-projective depth buffer!
Of course, you may not wish to match a real-world camera exactly—we have the freedom to calculate CoC with whatever algorithm we like, and can even do things that real-world cameras can’t, like have two different focal planes in one image! But if you do want to simulate the CoC of an actual camera, this is a convenient formula to have.