Projected-density rung gate for progressive refinement.
The residency budget (residency-budget.ts) bounds a ladder by BYTES. This
gate bounds it by what the screen can show: once a node already projects
more elements per drawing-buffer pixel than the cap, its next additive rung
is pure overdraw — the density guard's shader ladder would thin it straight
back out (blendable modes), or a max/normal/opaque node would pay the
fragment cost for nothing the eye resolves. So the rung is DEFERRED rather
than fetched, decoded, projected and committed.
Deferral is camera-dependent, so unlike the byte ceiling it is NOT sticky
across runs: the gate remembers, per deferred path, the projected footprint
at which the next rung would fit again (resumeAreaPx), and
takeResumable() hands back the paths whose current footprint has grown
past it (the user zoomed in). The SceneLoader re-kicks refinement for them
(kickRefinementIfIdle). Within ONE run the refusal is folded into the
residency budget's declined set, which is what keeps the documented
"declining retires the loader from anyHasMoreLODs / getLoaderProgress"
invariant (see the residency-budget module docstring) — the loop terminates
instead of re-offering the loader at frame rate.
Density is read through a provider the app pipeline injects
(scene/projected-density.ts measures it per frame; data/ cannot import
scene/). No provider, no record, an off-screen node, or a node that has
loaded nothing yet ⇒ no opinion: the gate never refuses on an absent
signal, and never refuses a first rung. Shaded triangle meshes are excluded
by the projected-density provider because surface tessellation is not stacked
emissive overdraw.
Projected-density rung gate for progressive refinement.
The residency budget (
residency-budget.ts) bounds a ladder by BYTES. This gate bounds it by what the screen can show: once a node already projects more elements per drawing-buffer pixel than the cap, its next additive rung is pure overdraw — the density guard's shader ladder would thin it straight back out (blendable modes), or a max/normal/opaque node would pay the fragment cost for nothing the eye resolves. So the rung is DEFERRED rather than fetched, decoded, projected and committed.Deferral is camera-dependent, so unlike the byte ceiling it is NOT sticky across runs: the gate remembers, per deferred path, the projected footprint at which the next rung would fit again (
resumeAreaPx), andtakeResumable()hands back the paths whose current footprint has grown past it (the user zoomed in). The SceneLoader re-kicks refinement for them (kickRefinementIfIdle). Within ONE run the refusal is folded into the residency budget'sdeclinedset, which is what keeps the documented "declining retires the loader fromanyHasMoreLODs/getLoaderProgress" invariant (see the residency-budget module docstring) — the loop terminates instead of re-offering the loader at frame rate.Density is read through a provider the app pipeline injects (
scene/projected-density.tsmeasures it per frame;data/cannot importscene/). No provider, no record, an off-screen node, or a node that has loaded nothing yet ⇒ no opinion: the gate never refuses on an absent signal, and never refuses a first rung. Shaded triangle meshes are excluded by the projected-density provider because surface tessellation is not stacked emissive overdraw.