/** * Contribution culling: skip draws whose world AABB projects below a pixel * threshold on screen. Sub-pixel geometry costs a full draw call + vertex * work but contributes at most a flicker of a pixel, so dropping it is * visually near-lossless while cutting draw calls and vertex load on large * models (issue #1682). The threshold is intentionally raised while the * camera is moving: quality matters least mid-gesture, and the cheaper * frames keep interaction smooth exactly when the renderer is under the * most pressure (same policy as contribution culling in Cesium/xeokit-class * viewers). * * The math is a bounding-sphere estimate (half the AABB diagonal projected * at the sphere centre's VIEW DEPTH, not its Euclidean distance — depth is * what perspective projection divides by, so off-axis geometry is not * under-sized). It is exact for a sphere on the view axis and over-estimates * boxes elsewhere, except for one residual: the radial stretch of far-corner * perspective projection can exceed the estimate by at most 1/cos(theta) of * the diagonal half-FOV (~1.7x at fov 60). With the sub-pixel default * thresholds that residual stays visually lossless; treat the threshold as a * perceptual heuristic, not a hard guarantee. */ export interface ContributionCullOptions { /** * Projected AABB radius in device pixels below which a draw is skipped * while the camera is at rest. `<= 0` disables contribution culling. */ pixelRadius: number; /** * Threshold while the camera is interacting/animating. Defaults to * `pixelRadius` (no motion boost). Values below `pixelRadius` are * clamped up to it — motion must never cull LESS than rest. */ interactingPixelRadius?: number; } /** Camera state snapshot needed to project an AABB radius to pixels. */ export interface CullCameraState { /** Camera eye position in world space. */ eye: { x: number; y: number; z: number; }; /** Normalized view direction (eye toward target), perspective mode. */ viewDir: { x: number; y: number; z: number; }; mode: 'perspective' | 'orthographic'; /** Vertical field of view in radians (perspective mode). */ fovYRadians: number; /** Half the vertical world-space extent of the view volume (orthographic mode). */ orthoHalfHeight: number; /** Canvas height in device pixels. */ viewportHeightPx: number; } /** * Resolve the active pixel threshold for this frame. * Returns 0 when culling is disabled (absent options or non-positive radius). */ export declare function resolveContributionThresholdPx(options: ContributionCullOptions | undefined, interacting: boolean): number; /** * Projected radius of a world-space AABB, in device pixels. * * Uses the AABB's bounding sphere (radius = half diagonal). In perspective * mode the sphere is projected at the box centre's VIEW DEPTH (distance * along `viewDir`), so off-axis boxes never read smaller than an on-axis * box at the same depth. When the sphere reaches the camera plane * (depth <= radius: camera inside, beside, or behind-but-overlapping), * `Infinity` is returned and the caller never culls — a box fully behind * the camera is the frustum test's job, not this one's. Degenerate/empty * bounds project to 0 and are culled at any positive threshold. */ /** * Conservative projected radius (device pixels) of the LARGEST single * occurrence of a GPU-instanced template. * * A template's occurrences are scattered inside `unionMin..unionMax` (the * union of their world AABBs), so the union box itself is useless for * contribution culling — bolts spread across a 100m model union to a * model-sized box that never reads small. What CAN be bounded is any single * occurrence: its projected radius is at most `maxOccRadius` (the largest * occurrence bounding-sphere radius) projected at the SMALLEST view depth any * occurrence can have, which is the union box's nearest point along the view * direction. If even that upper bound is below the pixel threshold, no * occurrence can exceed it and the whole template is safely skippable. * * Fails open (Infinity) whenever a bound cannot be established: degenerate * camera, non-finite radius, or the nearest possible occurrence overlapping * the camera plane (minDepth <= maxOccRadius). */ export declare function projectedInstancedRadiusPx(unionMin: readonly [number, number, number], unionMax: readonly [number, number, number], maxOccRadius: number, cam: CullCameraState): number; export declare function projectedAabbRadiusPx(min: readonly [number, number, number], max: readonly [number, number, number], cam: CullCameraState): number; //# sourceMappingURL=contribution-cull.d.ts.map