Width-factor normalization for the auto rule. Fill cost scales with
RENDERED width, and authored max_width is in world units — not
comparable across scenes (a nanometre scene authors 500, a normalized
one 0.5). The factor is therefore PROPORTIONAL to the on-screen width
at the opening framing (node extent fitted to a nominal viewport):
Deliberately order-of-magnitude, not exact: openingPx is the
authored width times a nominal px-per-unit, but the line shaders draw
about FOUR times that. Two factors of 2 stack — the line scale
luxarLineScale is res.y · |P11| = res.y / tan(fov/2), i.e. twice the true px-per-unit conversion,
and the shader then consumes the result as the quad's HALF-extent
(aQuadCorner.y ∈ {-1,+1} in shader-glsl.ts) — on top of which each
primitive draws its own support multiple (see
_shared/line-capsule.ts). Left uncorrected on purpose: a ~4× small
factor keeps the capsule longer, which is the right bias for a quality
default. An nD bounds diagonal (extra non-spatial dims) only grows the
denominator, which is conservative in the same direction. A node
TRANSFORM, on the other hand, does NOT cancel: both terms are
authored, so the ratio itself is transform-free — but the rendered
width is not. The shader converts width against the VIEW-space depth
(width * luxarLineScale / dist in shader-glsl.ts) without
the model matrix, while the extent that sets that depth carries it. A
node scaled by s therefore draws s× thinner, relative to its own
extent, than this estimate says: a scaled-up node can reach the
threshold earlier than its true rendered width warrants (the ~4×
slack above absorbs the first two octaves of that), a scaled-down one
keeps the capsule longer. Order-of-magnitude, as stated.
The width term is the node's MAXIMUM authored width, and that is the
one deviation biased the other way: a node of a million hairlines
carrying one fat line reads as a million fat lines and can flip to the
quad on fill cost it never pays. Deliberate — .zattrs records
max_width and no width distribution — and the cost of being wrong
here is the cheaper primitive on an unusual scene, never a broken one.
Floored at 1 because the shader clamps thin lines to minPixelWidth
(1.5 px in shader-glsl.ts) — below the clamp, fill cost stops
shrinking with width. With the 4× above, the floor in fact holds until
a line draws roughly 6 px rather than releasing exactly at the clamp;
same conservative direction. Measured: capsule GPU cost grew
~2.8× from the thin bench arms to the width-3 arms at equal count,
i.e. ~linearly in rendered width, which is what a linear factor
models. Nodes without authored bounds fall back to factor 1
(count-only) rather than guessing.
Width-factor normalization for the auto rule. Fill cost scales with RENDERED width, and authored
max_widthis in world units — not comparable across scenes (a nanometre scene authors 500, a normalized one 0.5). The factor is therefore PROPORTIONAL to the on-screen width at the opening framing (node extent fitted to a nominal viewport):openingPx = max_width / bboxDiagonal × NOMINAL_VIEWPORT_PX widthFactor = max(1, openingPx / MIN_RENDERED_WIDTH_PX)
Deliberately order-of-magnitude, not exact:
openingPxis the authored width times a nominal px-per-unit, but the line shaders draw about FOUR times that. Two factors of 2 stack — the line scaleluxarLineScaleisres.y · |P11| = res.y / tan(fov/2), i.e. twice the true px-per-unit conversion, and the shader then consumes the result as the quad's HALF-extent (aQuadCorner.y ∈ {-1,+1}inshader-glsl.ts) — on top of which each primitive draws its own support multiple (see_shared/line-capsule.ts). Left uncorrected on purpose: a ~4× small factor keeps the capsule longer, which is the right bias for a quality default. An nD bounds diagonal (extra non-spatial dims) only grows the denominator, which is conservative in the same direction. A node TRANSFORM, on the other hand, does NOT cancel: both terms are authored, so the ratio itself is transform-free — but the rendered width is not. The shader convertswidthagainst the VIEW-space depth (width * luxarLineScale / distinshader-glsl.ts) without the model matrix, while the extent that sets that depth carries it. A node scaled by s therefore draws s× thinner, relative to its own extent, than this estimate says: a scaled-up node can reach the threshold earlier than its true rendered width warrants (the ~4× slack above absorbs the first two octaves of that), a scaled-down one keeps the capsule longer. Order-of-magnitude, as stated.The width term is the node's MAXIMUM authored width, and that is the one deviation biased the other way: a node of a million hairlines carrying one fat line reads as a million fat lines and can flip to the quad on fill cost it never pays. Deliberate —
.zattrsrecordsmax_widthand no width distribution — and the cost of being wrong here is the cheaper primitive on an unusual scene, never a broken one.Floored at 1 because the shader clamps thin lines to
minPixelWidth(1.5 px in shader-glsl.ts) — below the clamp, fill cost stops shrinking with width. With the 4× above, the floor in fact holds until a line draws roughly 6 px rather than releasing exactly at the clamp; same conservative direction. Measured: capsule GPU cost grew ~2.8× from the thin bench arms to the width-3 arms at equal count, i.e. ~linearly in rendered width, which is what a linear factor models. Nodes without authored bounds fall back to factor 1 (count-only) rather than guessing.