Particles: per-pass frustum culling (main / mirror / shadow) so off-screen particles skip the sort and the main draw #518

Closed
opened 2026-10-07 06:15:02 +00:00 by sky_line · 1 comment
Owner

Found while testing #479's frozen culling camera: off-screen particles still render. The GPU particle pool has no culling: clean_particle_compact.comp gives every live particle a sorted draw key, so every live particle is depth-sorted and drawn each frame by the main view, the mirror and the sun-shadow cascades, wherever it is.

Off-screen quads are cheap to draw (vertex work, then clipped), but the sort grows with all live particles, which matters in particle-heavy places (#435).

Fix (per pass, like #517 for avatars)

  • The compaction pass tests each particle's bounding sphere (position ± its size, ribbons included) against:
    • the main cull frustum (the frozen one when the cull camera is frozen);
    • the mirror frustum, when a dynamic mirror is active;
    • the shadow cascades / sun-swept volume, when particle shadows are on.
  • Main view: only main-visible particles get sorted keys; the rest get the dead key, so the sort and the main draws skip them.
  • Mirror: its own compacted list.
  • Shadow cascades: an unsorted list (shadows don't need back-to-front order).
  • Counters: live vs main-visible vs mirror-only vs shadow-only particles.
  • The particle pick (#481) scans the pool directly and is unaffected.

Done when

  • Frozen cull camera pointed away from particle sources: no particle draws in the main view; particle shadows that fall into view and particles seen in a mirror still render.
  • Sort/compaction GPU time drops with many off-screen particles.
Found while testing #479's frozen culling camera: off-screen particles still render. The GPU particle pool has **no culling**: `clean_particle_compact.comp` gives every live particle a sorted draw key, so every live particle is depth-sorted and drawn each frame by the main view, the mirror and the sun-shadow cascades, wherever it is. Off-screen quads are cheap to draw (vertex work, then clipped), but the **sort** grows with all live particles, which matters in particle-heavy places (#435). ## Fix (per pass, like #517 for avatars) - The compaction pass tests each particle's bounding sphere (position ± its size, ribbons included) against: - the main cull frustum (the frozen one when the cull camera is frozen); - the mirror frustum, when a dynamic mirror is active; - the shadow cascades / sun-swept volume, when particle shadows are on. - **Main view:** only main-visible particles get sorted keys; the rest get the dead key, so the sort and the main draws skip them. - **Mirror:** its own compacted list. - **Shadow cascades:** an unsorted list (shadows don't need back-to-front order). - Counters: live vs main-visible vs mirror-only vs shadow-only particles. - The particle pick (#481) scans the pool directly and is unaffected. ## Done when - Frozen cull camera pointed away from particle sources: no particle draws in the main view; particle shadows that fall into view and particles seen in a mirror still render. - Sort/compaction GPU time drops with many off-screen particles.
sky_line added this to the Slipstream project 2026-10-07 06:15:02 +00:00
Author
Owner

Shipped in 1.1.0 Beta 9 (v1.1.0-beta.9).

Shipped in 1.1.0 Beta 9 (v1.1.0-beta.9).
sky_line 2026-10-07 07:27:55 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sky_line/Slipstream#518
No description provided.