Skip to main content

screen_space_tess_factor

Function screen_space_tess_factor 

Source
pub fn screen_space_tess_factor(
    desc: &CylinderDescriptor,
    cam: &Camera,
    viewport: (u32, u32),
    target_px: f64,
) -> TessFactor
Expand description

Derive a TessFactor from the cylinder’s projected screen size so the silhouette’s chord error stays within target_px pixels at the given view.

A zoomed-in cylinder (large projected radius) gets a fine mesh; a distant one (small projected radius) gets a coarse mesh — view-dependent LOD, the payoff of meshing analytic surfaces on the GPU from their parameters.

§Math

The chord error of an n_u-gon inscribed in a circle of radius r is ε = r·(1 − cos(π/n_u)). Projecting r to pixels under perspective, r_px = r · (H/2) / (d · tan(fov_y/2)) where H is the viewport height and d is the center’s view-space depth (its projection onto the view direction, view_dir · (center − eye)) — not the Euclidean eye distance, so an off-axis cylinder at the same depth is not under-tessellated. Bounding the screen-space error r_px·(1 − cos(π/n_u)) ≤ target_px and solving: n_u = ceil(π / acos(1 − clamp(target_px / r_px, 0, 2))). A sub-pixel cylinder (r_px ≤ target_px) floors to the TessFactor minimum; a cylinder engulfing the camera (r_px → ∞) requests the maximum.

n_v is fixed at 1: a cylinder’s lateral face is ruled (straight and of constant normal along the axis), so one axial division is geometrically and shading-exact. Sphere/torus surfaces will later need n_v adaptivity too, since they curve in both parametric directions.

The result always passes through TessFactor::new, so the [3, MAX_TESS] clamp and the buffer-overflow guard still apply.