Luxar Viewer API Documentation - v2026.9.22
    Preparing search index...
    MAX_NEAR_FAR_RATIO: 1200

    Largest near/far ratio the near-plane floor will allow.

    The depth buffer is 24-bit fixed point (three allocates DEPTH_COMPONENT24 for a render target with no explicit depthType, and webgl.renderer.logarithmicDepthBuffer is off), so depth quantization in world units at eye distance d is

    Δz(d) = d² · (far − near) / (near · far) · 2⁻²⁴
    

    — inversely proportional to near. Left unbounded, the inside-the-sphere branch of calculateClippingPlanesFromSphere pinned near to R · MIN_NEAR_RADIUS_FACTOR (2e-6 · R), i.e. a ratio near 6e5:1, which puts Δz at ~4e-2 world units on a diagonal-100 scene viewed from 8.5 units — coarse enough to z-fight visibly, and (because near tracks camera distance) to POP as the camera orbits. Only depth-writing geometry is affected (mesh, and opaque normal-mode geometry — see rendering/blending-state.ts), which is exactly where it was reported.

    Why 1200 specifically. A LARGER C means a smaller floor: less precision, but less clipped. Two hard constraints put a floor under C, and only a soft preference (keep precision) pushes from above — and that preference turns out to be nearly free, so C is set for MARGIN above the binding constraint rather than at it:

    • C > 551, don't clip the zoom target under the scale-multiplier floor. At maximum zoom-in the orbit target sits at minDistance = 1e-3 · diagonal (controls.scaleMultipliers) = 1.905e-3 · R, while far ≈ 1.05 · R. Keeping it in front of the near plane needs 1.05 R / C < 1.905e-3 R. NOTE this assumes the orbit target is at the sphere CENTRE. Panned onto a bbox corner (0.952 · R) the general form (dist + R)/C < 1.905e-3 · R tightens, and for the last ~2% of the zoom-in range the floor overtakes minDistance. All four types are inside the fade-suppressed region throughout that band by construction, so at most the sub-1% line residual described in the next bullet is lost there, and this does not move C. Auto-framing installs a separate distance / ZOOM_IN_FACTOR limit. The projected-bounds fit approaches distance / diagonal = 0.5 for a view-axis-elongated box at the default FOV, raising this target constraint to about 1102; C = 1200 clears it there, with a 1.14x near-plane margin at the most extreme supported zoom. At wide FOVs the ratio falls further and C does not clear this target constraint, as it did not before this change; see the ZOOM_IN_FACTOR note in camera-framing.ts.

    • C ≥ 992, keep everything the floor clips inside the near fade, for all four geometry types. Every one of them already suppresses anything closer than nearCull = 1e-3 · diagonal via perspectiveNearFade (materials/_shared/glsl-lib.ts), and the fade is under 0.01 below 1.0589 · nearCull (the root of smoothstep(1, 2, x) = 0.01, solved rather than eyeballed in tests/.../clipping/_near-fade-model.ts). That single bound is what the tests assert — but what each type DOES with a sub-0.01 fade differs, and the difference is the difference between "lossless" and "very nearly", so it is worth knowing before trusting this:

      Points and GSplats REJECT the vertex outright below 0.01 (both backends), and Mesh discards the FRAGMENT at the same 0.01 (per fragment because a triangle spans depth; a discard rather than a multiply because it writes depth — #1431). For those three the floor is exactly lossless: what it clips was not going to be rasterized at all.

      Lines are the one partial case. They cull only when BOTH endpoints are near, clip a half-near segment onto the nearCull plane, and then apply the fade PER-FRAGMENT as a plain multiply with no reject of its own — their discard is a separate max(rgb) < 1e-4 test on the COLOR, which the fade never enters. So a line fragment inside the clipped band is attenuated to under 1% of its authored contribution but is not necessarily zero, and the floor can take it. That residual is a property of the line shader, not of this constant: no value of C removes it while still bounding the ratio, it predates #1431, and at ≤1% of one fragment inside a 0.1%-of-diagonal shell it is not what sets C. Closing it would mean giving the line shader its own fade reject.

      The worst case is NOT the camera on the sphere surface — it is just OUTSIDE it, at the crossover dist = R · (C+1)/(C-1) ≈ 1.002 · R, the last distance at which the floor still beats the surface term and therefore where the floor sits highest relative to nearCull (fade 0.00755 there versus 0.00725 on the surface). So 2.002 R / C ≤ 1.0589 · 1.905e-3 · R ⟹ C ≥ 992.

    992 binds, and C = 1200 clears it by 20.9%. The margin is deliberate, and it is cheap: going from the minimum-viable 1000 to 1200 gives away 0.03% of the total precision gain (Δz 7.05e-5 → 8.47e-5 world units on the reported pose, against 4.10e-2 before the bound), and buys survival of ordinary tuning elsewhere. Measured: a 10% tightening of nearCull needs C ≥ 1104, and reducing the fade reject headroom to 1.0 needs C ≥ 1051 — C = 1000 would have become silently LOSSY under either, C = 1200 holds.

    The margin is also enforced rather than trusted: the "clipped band is already shader-rejected" property in bounds-math.property.test.ts generates the whole floor-binding region INCLUDING that crossover, a companion test pins the crossover as strictly worse than the surface, and the arithmetic test asserts the constant survives that 10% nearCull tightening — so a future change to nearCull, to the fade band, or to this constant fails there. (Mesh used to be the FULL exception — it had no near fade in either backend at all, so the floor could clip it at full brightness. Since #1431 it carries the same fade with the same 0.01 reject and the same 1.0589 · nearCull headroom, which moves it into the exactly-lossless group with points and gsplats and leaves lines as the only ≤1% residual above.)

    The losslessness argument assumes nearCull and this floor are derived from the SAME bounds, which holds on the metadata and per-frame paths. It can diverge in one narrow case: on a metadata-less scene SceneBoundsCache.ensure never populates, so the materials keep _nearCull's 0.1 default while autoAdjustFromBounds derives its sphere from Box3.setFromObject. On a large metadata-less scene the floor can then exceed nearCull and clip geometry of any of the four types that the fade would have drawn. Compiled Luxar scenes always carry position_bounds, so this is not reachable through the normal loader.

    Measured payoff at the reported pose (R = 52.5, dist = 8.5, far = 61): the floor rises 1.05e-4 → 0.0508 and depth quantization improves 4.10e-2 → 8.47e-5 world units, i.e. 485x finer.

    PERSPECTIVE ONLY — see the boundNearFarRatio parameter of nearPlaneFloor. An orthographic projection maps eye depth LINEARLY to the depth buffer, so its resolution is (far - near) / 2²⁴ regardless of near: the ratio bound buys ortho nothing, while still clipping a slab in front of the eye that ortho (unlike perspective) really does draw — perspectiveNearFade returns 1.0 for ortho, so ALL FOUR geometry types render up to near there. Measured on a diagonal-100 scene at the deepest legal orbit distance: applying the bound under ortho clips 43.8% of the eye-to-target depth versus 0.105% without it, and changes depth resolution by 0.1%.