Nathan Reed

Blog Stuff I’ve Made Talks About Me
Quadrilateral Interpolation, Part 1E=mc2E = mc^2E=mc2 Is Only Half The Story

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 nnn and fff 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 ddd in terms of world-space depth zzz is: d=ff−n−nff−n1z d = \frac{f}{f - n} - \frac{nf}{f - n} \frac{1}{z} d=f−nf​−f−nnf​z1​ Inverting this equation to get ‘z’ in terms of ‘d’ gives: z=11n−f−nnfd z = \frac{1}{\frac{1}{n} - \frac{f - n}{nf} d} z=n1​−nff−n​d1​ From Wikipedia, the equation for the CoC radius ccc of a point at depth zzz is: c=s∣1−zfocusz∣, c = s \left|1 - \frac{z_\text{focus}}{z} \right|, c=s∣∣​1−zzfocus​​∣∣​, where zfocusz_\text{focus}zfocus​ is the depth at which the camera is in perfect focus, and sss is a constant scale factor related to the camera setup (see the Wikipedia page for details). Putting together the last two equations gives c=s∣1−zfocus(1n−f−nnfd)∣=∣s(1−zfocusn)+(szfocusf−nnf)d∣ \begin{aligned} c &= s \left|1 - z_\text{focus} \left(\frac{1}{n} - \frac{f - n}{nf} d \right) \right| \\ &= \left| s\left(1 - \frac{z_\text{focus}}{n} \right) + \left(s z_\text{focus} \frac{f - n}{nf} \right) d \right| \end{aligned} c​=s∣∣​1−zfocus​(n1​−nff−n​d)∣∣​=∣∣​s(1−nzfocus​​)+(szfocus​nff−n​)d∣∣​​ This is just (the absolute value of) a linear scale-bias of ddd, 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.

Quadrilateral Interpolation, Part 1E=mc2E = mc^2E=mc2 Is Only Half The Story

3 Comments on “Circle of Confusion From The Depth Buffer”

Subscribe

  • RSS RSS

Recent Posts

  • Reading Veach’s Thesis, Part 2
  • Reading Veach’s Thesis
  • Texture Gathers and Coordinate Precision
  • git-partial-submodule
  • Slope Space in BRDF Theory
  • Hash Functions for GPU Rendering
  • All Posts

Categories

  • Graphics(32)
  • Coding(23)
  • Math(21)
  • GPU(15)
  • Physics(6)
  • Eye Candy(4)
© 2007–2024 by Nathan Reed. Licensed CC-BY-4.0.