UNPKG

three-virtual-geometry

Version:

Virtual geometry for three.js WebGPU: automatic cluster LOD and GPU-driven culling for billions of triangles. Independent implementation, not affiliated with Epic Games.

68 lines (67 loc) • 4.16 kB
import type { VirtualMeshData } from '../preprocess/buildVirtualMesh.js'; /** Camera parameters the LOD test needs. Same values the GPU pass uses. */ export interface CutView { /** Column-major world-to-view matrix (camera.matrixWorldInverse.elements). */ viewMatrix: ArrayLike<number>; /** projection[1][1] * viewportHeight / 2: converts view-space error to pixels. */ projScale: number; near: number; /** * Uniform scale of the instance, applied to the sphere radii and errors as the GPU does. `viewMatrix` * must then include the instance's scale in its centers too (view * model). Default 1. */ scale?: number; } /** * CPU reference for the GPU LOD selection (no frustum culling, identity model matrix). * A meshlet is in the cut when its own projected error is within `threshold` pixels and its * parent's projected error is not. Returns one flag per meshlet. * * Use it to test the DAG (see `verifyCutCoverage`) or to pick LODs on the CPU, e.g. for physics or AI. */ export declare function selectCut(data: VirtualMeshData, view: CutView, threshold: number): Uint8Array; /** * CPU reference for the GPU selection with LOD blending (see `VirtualGeometry.lodBlend`): every meshlet that is in * the cut for some threshold in [threshold, threshold * blend], with the blend steps it draws, [lo, hi) of * 0..LOD_FADE_STEPS - 1. `hi[i] === 0` means meshlet i is not drawn. The meshlets with lo <= s < hi form a complete * cut for every step s. */ export declare function selectBlendCut(data: VirtualMeshData, view: CutView, threshold: number, blend: number): { lo: Uint8Array; hi: Uint8Array; }; /** * Checks that a cut draws no surface twice: no selected meshlet has a selected meshlet among its coarser * replacements (recursively). Returns the indices of selected meshlets that overlap a coarser selected one. */ export declare function verifyCutOverlap(data: VirtualMeshData, selected: Uint8Array): number[]; /** * Checks that a cut has no holes: every leaf meshlet (LOD 0) is covered by a selected meshlet on its * path to the coarsest level (itself or one of its replacements, recursively). * Returns the indices of uncovered leaves (empty array = valid cut). */ export declare function verifyCutCoverage(data: VirtualMeshData, selected: Uint8Array): number[]; /** * CPU reference for the GPU instance pass: the contiguous range of meshlets (sorted by LOD level) * that can possibly pass the LOD test for an instance, from distance bounds alone. * * Every LOD and parent sphere lies inside `lodBoundsSphere`, so the distance to any of them is within * [D - R, D + R]. A level can contribute only if its smallest own error could be within the threshold * at the farthest distance and its largest parent error could exceed it at the nearest. With `blend` (see * `selectBlendCut`), the band [threshold, threshold * blend]. * Returns [start, end) or [0, 0] when nothing can be selected. */ export declare function instanceMeshletRange(data: VirtualMeshData, view: CutView, threshold: number, blend?: number): [number, number]; /** * CPU reference for the GPU fast path of the instance pass. Returns the range [start, end) when every * meshlet in it is guaranteed to be selected by the LOD test, for any distance the instance can have, and * the range is at most FAST_PATH_MAX_MESHLETS long. Otherwise returns null (use the per-meshlet pass). * * Guarantee per level, over the distance band [dMin, dMax] of `instanceMeshletRange`: * - largest own error projects to <= threshold at dMin (its closest possible distance), and * - smallest parent error projects to > threshold at dMax (its farthest possible distance). * A small relative margin keeps float rounding on the GPU from flipping a borderline meshlet. * With `blend`, guaranteed means drawn over every pixel: own error below the band, parent error above it. * The caller must also check that the instance is fully inside the frustum (see `cullBoundsSphere`). */ export declare function instanceGuaranteedRange(data: VirtualMeshData, view: CutView, threshold: number, blend?: number): [number, number] | null;