Builtin Library
README.md
bokehBlur
The render feature behind DepthOfField and
@builtin::systems.depthOfField.depthOfField. Two compute passes run after
lighting:
| order | pass | output |
|---|---|---|
| 300 | dof_coc | the signed circle of confusion each pixel projects, in pixels |
| 302 | dof_gather | a disc gather at that radius, and the composite |
The circle of confusion
A point at distance d images as a disc whose diameter follows from focal length,
aperture and where the lens is focused — the thin-lens relation. Deriving the
blur radius that way is what makes fStop and focalLength behave the way they
do on a camera instead of being two more arbitrary sliders.
It is stored signed: negative in front of the focal plane, positive behind it. The two fields are not symmetric — a near blur spills over what it occludes and a far blur does not — and the sign is what lets the gather tell them apart.
The sky sits at the far plane and takes the full far-field radius rather than a distance that would divide badly.
The gather
Taps follow a golden-angle spiral: even coverage of the disc with no stored sample table and no directional structure for the eye to catch.
Each tap contributes only if its OWN circle of confusion is wide enough to reach the pixel gathering it — scatter expressed as a gather. Without that test a sharp foreground bleeds outward onto a blurred background, which is the classic tell of a defocus that was applied rather than photographed.
Weights are 1/spread², so a wide circle contributes proportionally less per
sample than a tight one — energy spread over a larger disc. The centre pixel is
weighted by the same rule as every tap; seeding it at 1 while taps carry
1/spread² would let it outweigh the whole disc.
Parameters arrive through the dof_params buffer, packed by
@builtin::systems.depthOfField.depthOfField.