What a machine computes

One depth per sample is not enough

A depth buffer keeps a single distance at each sample, so a post-process blur can only ask how far away the thing at this pixel is. Across an occluding edge that answer is two depths and an occlusion, and the gather it produces differs from the pupil's own integral by 70 per cent of full scale over a band eleven pixels wide.

Worth reading first: The precision a depth buffer has left · The centre has an area.

The precision a depth buffer has left measured what a depth buffer’s codes are spent on, and found the answer to be a reciprocal: most of them go to the first few per cent of the view. This essay is about a different limit of the same buffer, and it is not a precision limit at all.

A depth buffer holds one number per sample. At most surfaces that is the whole truth. At an occluding edge it is not, and the shortfall is not small.

What a post-process blur does

Every real-time renderer computes depth of field the same way. Render the scene sharp, keep the depth buffer, and for each pixel gather from its neighbours with a radius taken from that pixel’s own depth.

The radius is right: the centre has an area gives it as R|1 − v₀/v(Z)|, and a renderer that computes it from the buffer computes the correct number — which is also the number the sharp band is a decision cuts its band out of. The gather is what is wrong, and it is wrong for a reason that has nothing to do with how many samples it takes.

A depth buffer's blur and the real one differ by 70% over 11 pxTwo edge profiles across the same occluding edge. The solid curve is what the pupil actually delivers, integrated over the disc with the occlusion applied ray by ray. The other is what a renderer produces when it keeps one depth per sample and gathers with the blur radius belonging to whatever surface is at each pixel — the near surface's radius here is 33 pixels and the far one's is 0.0. They part company by 70 per cent of full scale over a band 11 pixels wide, and the sign of the difference is always the same: the gather has no way to let the background through, because the sharp image it is gathering from does not contain it.00.2500.5000.7501-10-50510across the edge, in pixels of the picturehow much of the background reaches the sensorwhere a pinhole puts the edgethe pupilone depth per samplethe same edge, two ways of blurring it70% apart
Fig. 1 The profile a pupil actually delivers across an occluding edge, and the profile a per-pixel gather produces.

The measurement

An 85 mm lens at f/1.4, an opaque edge at 1.2 metres, a background at the focus distance of six.

The pupil’s own answer is computed by integrating over the disc with the occlusion applied ray by ray. The renderer’s answer is computed the way a renderer computes it: at each sample, take the depth of whatever surface is there — the near one on one side of the edge, the far one on the other — and gather with that radius. The near surface’s radius is 33.5 pixels; the far one’s is 0.0, because the background is exactly in focus.

The two profiles part company by 70 per cent of full scale, over a band 10.5 pixels wide.

And the sign of the difference is always the same. The gather cannot let the background through, because the sharp image it is gathering from does not contain the background behind the edge.

The control

A profile computed at sixty-one sample positions across a sharp step has one sample straddling it, where the pupil integral reads a half and a gather reads nothing. That is a single-sample artefact, not a disagreement about the picture, and a control stated on the peak difference would have been reporting it.

So the control is stated on the width instead. With the edge in focus and the background just behind it, the band over which the two disagree is 1.4 pixels — the straddling samples — against 10.5 pixels in the defocused case. A factor of seven, and the two disagreements are different in kind rather than in degree.

Getting that wrong once is what the control is for. The first version of this measurement compared peak differences and reported the focused case at fifty per cent, which is a picture of the sampling grid.

What the buffer would need to hold

The honest answer is not “a second depth”. It is a list, and the list is unbounded.

At a pixel near a defocused edge, the light arriving comes from every surface visible from any point of the pupil. Two surfaces is the simple case; a defocused chain-link fence in front of a defocused hedge in front of a sharp building is three, and there is no bound. Storing per-sample lists is what a deep framebuffer or an A-buffer does, and it is why those exist.

There is a second thing the buffer would need and it is easier to miss: visibility from each pupil position, not merely from the pupil’s centre. A deep buffer built by rasterising from the centre records the surfaces the centre can see, and the whole content of a pupil sees around an edge is that the pupil sees surfaces the centre cannot. So even a deep buffer from one viewpoint is short of the answer.

That is what makes this an information problem rather than a storage problem, and it is why the only exact method is to sample the pupil.

Two scenes a pinhole cannot tell apart, 42% apart through a pupilTwo backgrounds identical everywhere a pinhole at the pupil's centre can see, and different only inside the strip the occluding edge hides from it. Their pinhole pictures are identical to the last bit. Their pupil pictures differ by up to 42 per cent of full scale. So there is no function of the pinhole picture that produces the picture a real lens makes — not a blur kernel, not a depth-dependent kernel, not anything — because two different outputs would have to come from one input. That is the strongest form the claim takes, and it needs no assumption about how the blur is modelled.00.2500.5000.7501-50-2502550across the edge, in pixels of the picturewhat the sensor receivesidentical to a pinhole, different to a pupil42% apart
Fig. 2 The proof that it is information rather than storage: two scenes with identical centre-of-pupil pictures and different pupil pictures.

The deficit is an amount of light, and it is conserved

The disagreement is quoted as a peak and a width, and there is a third number that is more useful than either because no tuning of the gather can change it.

Across the transition the pupil’s answer at each position is the background’s brightness times the open share — the fraction of the pupil that sees past the edge — which runs from 0 on the occluded side to 1 on the clear side. Integrating that share across the strip gives exactly half the strip’s width, because the share’s profile is antisymmetric about its midpoint. So the light the pupil delivers that the gather cannot is

12×(strip width)×(background brightness),\tfrac{1}{2} \times (\text{strip width}) \times (\text{background brightness}),

a fixed quantity, set by the geometry and the scene and by nothing about the blur.

That is a stronger statement than the peak or the width, and the reason is that it survives every mitigation. A depth-aware weighting redistributes light within the frame; a foreground extension copies light from elsewhere; a scatter formulation changes which pixels spread where. None of them changes the total, because none of them has access to the hidden strip’s actual contents, and a redistribution conserves what it redistributes. So a gather-based renderer’s defocused edges are short by a computable amount of energy, always, whatever is done to the kernel.

It also supplies a test that is cheaper than comparing profiles. Render a scene twice — once with a per-pixel gather and once with a sampled pupil — and integrate the total light over a window containing a defocused edge. The two profiles may be argued about; the two totals differ by a number the geometry predicts in advance, and a mitigation that closes the gap has necessarily taken the light from somewhere else in the frame, which the same integral over a wider window will show.

That is the form this collection prefers for any impossibility claim, and it is the form the two-background demonstration already takes one level up. A profile comparison invites a better kernel. A conserved quantity that the input does not contain rules out every kernel at once, and it does so with an integral rather than an argument.

Why it looks acceptable anyway

A fair question, since every game ships this and few players complain.

Most edges are between similar depths. The failure’s size scales with R(Z₂/Z₁ − 1), so it is large only when a strongly defocused near object stands in front of a much more distant one — which in a typical scene is a minority of edges.

The error is in the direction of “too opaque”. A gather makes a defocused foreground more solid than it should be, and a viewer with no reference has no way to know. The failure is not a visible artefact; it is a systematic absence of one.

And the artefacts people do complain about are different ones. Bleeding of a sharp foreground onto a blurred background, and the halo where the gather radius jumps across an edge, are both consequences of the same missing information but present as visible defects rather than as absences, so they attract fixes — depth-aware weighting, layer separation, foreground extension — that ameliorate the symptom without addressing the cause.

That last point is the useful one. Every mitigation in the standard toolbox is an attempt to guess the hidden background, and none of them can be right, because the input does not determine the answer.

A depth buffer's blur and the real one differ by 100% over 11 pxTwo edge profiles across the same occluding edge. The solid curve is what the pupil actually delivers, integrated over the disc with the occlusion applied ray by ray. The other is what a renderer produces when it keeps one depth per sample and gathers with the blur radius belonging to whatever surface is at each pixel — the near surface's radius here is 8 pixels and the far one's is 0.0. They part company by 100 per cent of full scale over a band 11 pixels wide, and the sign of the difference is always the same: the gather has no way to let the background through, because the sharp image it is gathering from does not contain it.00.2500.5000.7501-10-50510across the edge, in pixels of the picturehow much of the background reaches the sensorwhere a pinhole puts the edgethe pupilone depth per samplethe same edge, two ways of blurring it100% apart
Fig. 3 A stopped-down case, where the failure is small and a mitigation looks like it worked.

The same shape, three times in this field

This is the third time this collection has found a rendering approximation failing at a discontinuity, and putting them together says what the pattern is.

Perspective-correct interpolation. A texture does not interpolate on the page — a quantity that is linear in the world is not linear in the picture, and interpolating it on the page is wrong by an amount that grows with the depth range across the primitive.

Depth precision. The precision a depth buffer has left — the codes are spent reciprocally, so a distant surface has fewer of them than a near one and coplanar surfaces fight.

And this. One value per sample cannot represent what a finite aperture integrates over.

All three are the same trade: the pipeline stores a rasterised, single-valued, page-space approximation of something that is continuous, multi-valued and world-space, and each of them fails exactly where the approximation’s assumption fails — at large depth ranges, at discontinuities, at edges.

The gap between walking the page and walking the surfaceFor a surface receding from 2 m to 24 m, the departure peaks at 0.5520 of the whole range — over half of it — at s = 0.7760. The closed form is (√k−1)/(√k+1) with k the depth ratio, and the marked point is where it says the peak is.-0.400-0.200000.2000.4000.6000.8001position across the drawn surfacehow far along the real surface, minus how far along the drawn one(√k−1)/(√k+1) = 0.5520at the page's midpoint, 42.3%depth ratio 12 : 1peak 0.5520 at s = 0.776
Fig. 4 The first of the three at a large depth ratio, where the page-space approximation is at its worst.

What is actually done about it

Three approaches, in ascending order of cost and correctness.

Layered blur. Split the frame into a few depth layers, blur each independently, and composite back to front with the foreground layers’ edges extended inward. The extension is a guess at the hidden background — usually the nearest visible background pixel, stretched — and it is right when the background is smooth and wrong when it is not.

Gathering with scatter semantics. Let each pixel spread into its neighbours rather than gathering from them, which gets the foreground’s transparency approximately right because a defocused foreground pixel really does spread. This handles the occlusion direction correctly and still cannot produce hidden background.

And sampling the pupil. Render the scene several times from different points across the pupil and average, which is exact in the limit and is what offline renderers do. Sixteen samples removes most of the visible error; the number needed for a smooth result grows with the disc’s area.

The third is the only one that answers the question rather than approximating an answer, and it is expensive for exactly the reason this essay is about: it is gathering information that one pass does not have.

A pupil reaches 60 mm behind the edge that a pinhole cannot see pastA plan of the object side of a 85 mm lens at f/2.8. The pupil is on the left, an opaque edge stands 1.2 metres away, and the background is at the focus distance of 6 metres. Five rays leave one point of the sensor and fan out across the pupil; the ones drawn faint are stopped by the edge, and the ones drawn solid get past it and land on the background behind the edge — as far as 60 millimetres behind it, which is R(Z₂/Z₁ − 1) and comes out at 61. A pinhole at the pupil's centre receives the middle ray only, so everything in that strip is, to a pinhole, absent. **The scene behind an edge is in the photograph and not in the pinhole picture of it.** The axis is compressed; the vertical scale is millimetres of the scene.the pupilan opaque edge60 mmf/2.8, focused at 6 m3 of 5 rays get past
Fig. 5 The amount of hidden background a sampled pupil recovers, at a moderate aperture.

What it costs a measurement rather than a picture

Rendering is where this matters most often; measurement is where it matters most.

A synthetic image used as ground truth for a vision algorithm inherits whatever its renderer got wrong. If the renderer’s defocus is a per-pixel gather, every defocused edge in the training set has the wrong profile — too opaque, in a consistent direction — and a method trained on it learns that bias.

The same applies to any evaluation of a depth-from-defocus method against rendered data: the method is being scored against images whose edges do not have the profile a camera would produce, and its errors at edges are being measured against the wrong answer. That is not hypothetical; edges are exactly where such methods are weakest and where the evaluation is therefore least trustworthy.

The remedy is the same as the rendering remedy — sample the pupil — and it is much cheaper here, because ground truth is generated offline and sixteen or sixty-four samples costs time rather than frame rate.

Why this belongs to the pipeline field and not the sensor field

A boundary worth drawing, since the geometry is the aperture row’s and the failure is a renderer’s.

The aperture row measures what an instrument does. This measures what a representation cannot do, and the representation is a depth buffer — a rasterised grid of one depth per sample, which is a decision made in hardware in the nineteen-seventies and inherited by everything since.

That makes it the same kind of finding as this field’s others: not “the arithmetic is wrong” but “the data structure cannot hold the answer”. What happens behind the eye is the same shape — a clipper exists because homogeneous coordinates cannot represent a point behind the camera without one — and so is a pixel is not a point.

Each of them is a place where the pipeline’s own representation, not its precision, sets the limit.

The two radii, and why one of them is zero here

Worth pausing on the arrangement’s numbers, because one of them looks like a special case and is the ordinary one.

The near surface’s gather radius is 33.5 pixels and the far surface’s is 0.0 — because the background sits exactly at the focus distance. That is not a contrivance; it is the commonest arrangement in a photograph, where the subject is in focus and the foreground obstruction is not.

It also makes the failure as clean as possible to state. Every pixel on the background side of the edge is gathered with a radius of zero, so the renderer’s profile there is the sharp image itself: a step. The pupil’s profile is not a step, because part of the pupil sees background that the step’s own occluder is covering. The whole disagreement is therefore on the background side and it is the full height of the transition.

Move the background off the focus distance and the far radius becomes nonzero, the renderer’s profile softens, and the disagreement shrinks without disappearing — because a soft wrong answer is still wrong. The band narrows and the peak falls; the sign does not change.

A depth buffer's blur and the real one differ by 70% over 11 pxTwo edge profiles across the same occluding edge. The solid curve is what the pupil actually delivers, integrated over the disc with the occlusion applied ray by ray. The other is what a renderer produces when it keeps one depth per sample and gathers with the blur radius belonging to whatever surface is at each pixel — the near surface's radius here is 33 pixels and the far one's is 0.0. They part company by 70 per cent of full scale over a band 11 pixels wide, and the sign of the difference is always the same: the gather has no way to let the background through, because the sharp image it is gathering from does not contain it.00.2500.5000.7501-10-50510across the edge, in pixels of the picturehow much of the background reaches the sensorwhere a pinhole puts the edgethe pupilone depth per samplethe same edge, two ways of blurring it70% apart
Fig. 6 The two profiles again at the setting the numbers are quoted from, where the renderer’s is a step and the pupil’s is not.

What a hardware designer would have to change

Not a proposal, but worth naming, because the shape of the fix says what the limit is.

The buffer is a grid of samples with one depth each because rasterisation visits triangles and writes a fixed-size record per covered sample. Anything richer — a list per sample, a set of fragments, a per-sample visibility function — breaks the fixed-size record, which is what makes the whole pipeline’s memory traffic predictable.

Deep framebuffers exist and are used offline for exactly this class of problem, and they are not adopted in real time for the memory reason rather than a computational one. What they still would not give is visibility from anywhere but the centre of the pupil, so the honest fix is not a richer buffer but more viewpoints, which is the same conclusion the software side reaches.

That is a satisfying place to end, because it says the limit is not in the buffer’s width. It is in the number of places the scene was looked at from, and one is not enough.

Clip space: the box the frustum becomes, and the plane the segment stops atA plan section through the frustum. The segment runs from 6.60 m in front of the eye to 0.79 m behind it, and the clipper stops it on the near plane at 0.40 m. Clipping happens here, before the divide, because both ends are still finite numbers at this stage.near 0.4 mtoward the far planethe eyein front0.8 m behind the eyeclipped hereeverything below the eye's line has a negative w, and dividing by it flips both signsplan section · near 0.4 m, far 26 mthe segment crosses the eye plane at t = 0.839
Fig. 7 The fixed-size record’s own space, from this field’s clipping rung.

What the sixty-one samples are

The profiles are computed at sixty-one positions across a span of about a millimetre on the sensor, which is roughly twenty pixels of the picture, and that resolution is chosen rather than default.

It has to be fine enough that the pupil’s own profile — which reaches from zero to one over the disc’s diameter — is resolved by many samples, and coarse enough that the pupil integral, which is a ninety-six by ninety-six sweep of the disc at every position, finishes in a reasonable time. Sixty-one across a thirty-three-pixel disc gives about two samples per pixel of blur, which resolves the profile and leaves the straddling artefact at the sharp edge visible rather than hidden.

Reporting that artefact rather than smoothing it away is what let the control be stated on a width, and it is the reason the number quoted for the in-focus case is 1.4 pixels rather than zero.

The short version

A depth buffer holds one depth per sample. A post-process blur can therefore ask only how far away the surface at each pixel is, and at an occluding edge the correct answer involves two surfaces and what the pupil can see past one of them.

Measured on an 85 mm at f/1.4 with an edge at 1.2 metres and a background at six: the gather and the pupil’s own integral differ by 70 per cent of full scale over a band 10.5 pixels wide, against a 1.4-pixel control with the edge in focus. The difference always has the same sign, because the sharp image the gather reads has no pixel for the background behind the edge.

No amount of storage fixes it from one viewpoint. Sampling the pupil does, and that is exactly the information the extra samples are for.

A depth buffer's blur and the real one differ by 78% over 11 pxTwo edge profiles across the same occluding edge. The solid curve is what the pupil actually delivers, integrated over the disc with the occlusion applied ray by ray. The other is what a renderer produces when it keeps one depth per sample and gathers with the blur radius belonging to whatever surface is at each pixel — the near surface's radius here is 23 pixels and the far one's is 0.0. They part company by 78 per cent of full scale over a band 11 pixels wide, and the sign of the difference is always the same: the gather has no way to let the background through, because the sharp image it is gathering from does not contain it.00.2500.5000.7501-10-50510across the edge, in pixels of the picturehow much of the background reaches the sensorwhere a pinhole puts the edgethe pupilone depth per samplethe same edge, two ways of blurring it78% apart
Fig. 8 The two profiles at f/2, midway down the sweep, where the band is narrower and the sign of the difference is the same.

What links here

Computed from the collection, not written here: the essays that point at this one.

Shares its objects with

Essays that name at least two of the same things, and that neither author linked.

Named objects

A flat tag is an object no other essay names yet.

ApertureCircle of confusionConvolutionDepth bufferEntrance pupilIdentifiabilityinstrument limitMotion blurOcclusionRasterisationSampling