Shadow-map bias is a physical length along the incident light ray, applied immediately before the depth comparison. Too short a length misclassifies an analytically lit receiver as shadowed—surface acne. Too long a length lifts the contact shadow of a thin occluder off its geometric foot—peter-panning. This note measures that trade-off on one map, one sun, and one constant-bias sweep.
Discrete depth encoding, winner-islands, and reverse-Z belong to Z-fighting is geometric compression plus quantization. That note defers the acne-versus-peter-pan distinction here and keeps fight-fraction metrics in its own scope. We fix a single shadow map and do not sweep a depth code. The shared geometric idea is that a depth failure can be stated as a length: there an isolatable interval in front of the camera; here a bias in metres along the sun vector.
Scene
The cover is a service-yard curb: asphalt apron, 160 mm concrete curb, poured wash ramp at , and a 12 mm steel plate, in one framebuffer. One directional sun at altitude feeds a single depth-compare map with an 8 m orthographic frustum. The shadow map is rendered once per frame. Across the ladder, bias is the only independent variable.
Beauty runs on Mesa llvmpipe in scene-referred linear Rec.709, then through the display path in Tone Mapping: Scene-Referred to Display-Referred: Khronos PBR Neutral with , , , , and an sRGB OETF on the CPU. Exposure is locked at for every bias sample. Neutral only assigns display codes; it does not enter the acne fraction or the contact gap.
At the operating point (), as runs from through to , ramp acne falls from through to (lede abbreviations ), and apron acne falls from to (lede ). The contact gap opens from through to . Slope-scale at , clears both acne fractions with . The smallest constant bias that also clears the ramp is , where is already . The run prints 11 pass / 0 fail. Sweep rows, the full meter table, and gate notes live in the appendices.
Method: bias as a length on one map
A shadow map stores one depth per texel—the front-most surface from the light. The compare asks whether a shaded point lies farther from the light than that stored depth. On a surface tilted relative to the texel plane, continuous shaded points fall deeper than the winning fragment, so the compare fails. Acne is that mismatch: analytic visibility toward the sun is 1, yet the compare marks the sample shadowed.
Under this orthographic frustum, texel slope dominates the 24-bit depth step. Apron slope is per shadow texel; the quantization step is . The ratio is (lede ), well above the gate floor of . The acne in the cover sequence is therefore a texel-slope failure; winner-islands stay in the z-fighting note.
Bias subtracts a length along the ray toward the sun before the compare, sliding the shaded point toward the light. Large enough swallows the texel mismatch and acne falls. The same slide moves a thin occluder's shadow boundary away from its foot: the lit band between foot and shadow is the contact gap , measured along the apron.
Two receivers keep the trade-off from collapsing to one slope. The wash ramp sees grazing incidence at ; the apron sees the sun altitude . A constant bias large enough to kill ramp acne opens a large gap at the plate. Slope-scale applies a longer offset where the texel slope is steeper (ramp) and a shorter one on the apron, leaving the constant-bias curve.
The environment is right-handed, up, in metres.
| symbol | meaning | unit |
|---|---|---|
| unit vector toward the sun | — | |
| sun altitude, | degree | |
| ramp tilt, | degree | |
| light depth, | ||
| ortho near and far in | ||
| window depth, at , at | — | |
| shadow texel, ortho width | ||
| constant bias along the ray, toward the sun | ||
| slope-scale multiplier | — | |
| plate thickness, | ||
| acne fraction | — | |
| contact gap along |
One light camera serves the whole ladder. Depth increases along . The ortho square has width :
This run uses and , so (). The 24-bit step is . Texel slopes are on the apron, on the ramp, and on the plate face.
CPU meters and the beauty shader share the compare. is the stored window of the winning fragment, decoded with the same , . Depth fetch is nearest-neighbor. Bias depends on the receiver normal:
Constant sweep. With , . The ladder is (31 samples). The map is built once; checksum a816326e2dbe2366 is invariant across every and after the last beauty. Bias changes only the compare, never the stored depths.
Slope-scale, one marked point. Here and . With light-image basis , ,
is metres of light depth across one texel: on the ramp, on the apron. Neutral's display shoulder is unrelated to this geometric .
Acne fraction. An grid over a receiver; a sample counts only if analytic visibility toward the sun is exactly 1:
Both regions are fully analytically lit: ramp , apron .
Contact gap. The plate's downstream face sits at with thickness toward the sun. Visible ground is majority-filtered over a window for boundary finding only—never for . is the start of the longest shadowed run minus . At , the raw compare shadows transect samples downstream of the plate, so a closed gap is a real contact shadow, not a missing caster.
Ideal-map oracle. For this plate and sun altitude,
The knee sits at . Across five locking biases the unfiltered ideal traversal tracks within ; peak error is . The raster gap is measured, not fitted to the oracle.
Operating point. With and ,
(ties take the smaller ). This run isolates at , interior to the swept extremes. The sweep was not extrapolated past .
Photographs are scene-referred linear Rec.709 through Neutral at , . The sweep plot and metrics snapshot are authored sRGB, bypassing Neutral: photographs show the curb; tables and curves carry and .
Discussion: what if bias is short, long, or slope-scaled?
What if you stop at the interior minimum of ?
The cover is that operating point: , . A faint residue remains on the ramp (); the apron is clear (); the annotated gap is the measured along the apron, not a JPEG luminance cue. Apron acne is already gone by while the ramp still shows with . At the gap has just opened; ramp acne nulls only at with . The operating point sits where ramp acne is mostly gone and detachment has only begun.

What if ?
Same camera and the same shadow map, compare at . Ramp and apron self-shadow as high-frequency stripes: lit receivers marked shadowed. , , . Contact is correct; about half of every lit grid is a false shadow.

What if ?
Same camera and map at the long extreme. Both acne fractions are , but the plate's contact shadow has left the foot: () along the apron. The curb's own shadow remains a separate band.

What if slope-scale marks one point instead?
Slope-scale at , is one marked point in the same space—not a second ladder. It clears and with (), shorter than at matched ramp acne. The claim is that inequality, not a product ranking of filtered shadows.

The teaching pin plots , , and against constant bias from 0 to 120 mm, marks , and callouts the slope-scale triplet. Eight contact strips sit under the plot at 0, 24, 48, 72, 96, and 120 mm, then , then slope-scale; the gap staircase is left visible. Selected constant-bias rows are in Appendix A; the full 31-sample ladder is what the figure maps.

| frame | role |
|---|---|
| 00 | Cover. Operating point . |
| 01 | Acne. Same map, . |
| 02 | Peter-pan. Same map, . |
| 03 | Sweep. and vs constant bias; slope-scale callout. |
| 04 | Metrics snapshot. Tables and gates from this run. |
Limits: what this run can and cannot claim
Can claim. On this OSMesa / llvmpipe build (core 3.3 request), one directional sun, one nearest-texel shadow map, and one constant-bias sweep from 0 to 120 mm produced falling acne on both receivers and a rising contact gap at a 12 mm plate. The interior minimum of the normalised sum of ramp acne and gap is (). Slope-scale at clears ramp acne at a shorter gap than the matching constant sample (13 mm against 20 mm). The regime ratio places the failure in the texel-slope regime. The run prints 11 pass / 0 fail.
Cannot claim. A discrete GPU, wavefront, or frame-time budget. A filtered shadow, cascade, or soft penumbra. A measured polygon offset, normal-offset bias, or receiver-plane depth. Acne or gap read from a JPEG. A second depth codebook, fight-fraction, or reverse-Z curve. A ranking of this bias length against a product shadow stack.
Honesty notes that stay out of the main argument: the meter uses a 32-bit float color copy of winning fragment (attachment DEPTH_COMPONENT24; window depth bits 0); sixteen apron depth-texture texels match that copy; sampler2DShadow agrees on 8/8 stable points; probes at and match the CPU test at 16/16 locations. Gate 3 apron median () sits under the unquantized floor of 0 because the 8 mm lattice is sunward of texel centers (projected residual ); the gate accepts any median within (an unrendered apron would be about ). Specular on the lit plate face is masked by the binary shadow and does not enter or . The 31 mm majority filter is boundary-only; pass requires , and rises monotonically from 0 to even if individual staircase steps plateau. One map, one checksum—mismatch stops the run. The ideal-map oracle checks metric code; the raster curve checks the shadow map.
Out of scope
Percentage-closer and contact-hardening filters, cascades, atlas packing, a second light, an animated sun, and a soft penumbra. Reverse-Z, a depth-format sweep, and the z-fighting note's fight-fractions. Vendor polygon-offset scales and hierarchical-Z. Reading or from a beauty JPEG.
The cover is the operating point. The sweep is the teaching figure. Bias is a geometric length. Dense meters follow.
Appendix A — Constant-bias sweep and lede map
Metrics are CPU double precision before Neutral. The 31-sample ladder is ; selected rows:
| (mm) | (mm) | ||
|---|---|---|---|
| 0 | 0.509434 | 0.482759 | 0 |
| 16 | 0.283019 | 0 | 0 |
| 24 | 0.188679 | 0 | 11 |
| 36 | 0.018868 | 0 | 15 |
| 40 | 0 | 0 | 20 |
| 80 | 0 | 0 | 56 |
| 120 | 0 | 0 | 91 |
Lede abbreviations map to this run's unrounded tokens:
| lede | this run |
|---|---|
| , , | |
| , | |
| , , | |
| slope | |
| , | , |
| apron median | |
| regime ratio |
Contact strips on the teaching pin: 0, 24, 48, 72, 96, 120 mm, then , then slope-scale. Sweep plot authored sRGB of the curves and strips.
Appendix B — Full meter table
| item | value |
|---|---|
| scene | service-yard-curb |
| / | 32° / 20° |
| shadow resolution / ortho width | / 8 m |
| texel / depth path | 0.015625 m / color-copy |
| / | −3.722583 m / 3.934586 m |
| quantisation step / regime ratio | / 54787.622775 |
| apron / ramp / plate | 0.025005 / 0.073510 / 0.009764 m |
| shadow checksum | a816326e2dbe2366 |
| / Neutral | 3.40 / , , , |
| / | 0.036 m / 0.120 m |
| at , , | 0.509434 / 0.018868 / 0 |
| at , | 0.482759 / 0 |
| at , , | 0 / 0.015 m / 0.091 m |
| slope / | 1 / 0 |
| slope / / | 0 / 0 / 0.013 m |
| 0.040 m, | |
| apron median | −0.000350 m |
| boundary majority / depth format | 31 mm / DEPTH_COMPONENT24 |
| analytic gap / probes | pass / pass |
| asserts | 11 pass / 0 fail |
Renderer row: llvmpipe, OSMesa core 3.3 request; RGBA32F copy of winning fragment ; attachment DEPTH_COMPONENT24; window depth bits 0; sixteen apron texels match the color copy; hardware compare 8/8; encode , Neutral , sRGB OETF on the CPU; map checksum a816326e2dbe2366.
Appendix C — Assertions and formula cheat sheet
Printed: 11 pass / 0 fail. The eleven checks cover window depth, the regime ratio, the apron median, lit and covered regions, the ideal-map gap, probes and the checksum, frame projection, falling acne, a rising gap, an interior operating point, and the slope-scale gap.
Honesty checklist retained from the pre-appendix draft (items 1–7): (1) CPU depth verification; (2) Gate 3 apron median; (3) display tone-mapping constraints; (4) discreteness of ; (5) slope-scale is one marked point; (6) one map, one checksum; (7) rasterization is llvmpipe's.
b* = 0.036 m (36 mm), J = 0.202
A_ramp = 0.509434 / 0.018868 / 0 at 0, b*, b_max
A_apron = 0.482759 / 0
G = 0 / 0.015 / 0.091 m
slope ks=1, bc=0 → A=0/0, G=0.013 m
b_match = 0.040 m, G=0.020 m
regime ratio = 54787.622775 (lede 54788)
apron median = -0.000350 m
checksum = a816326e2dbe2366
asserts = 11 pass / 0 fail