Skip to content

Add LOD system with UE-style screen-size computation, pre-computed distance thresholds, and mesh streaming culling#66

Draft
Copilot wants to merge 10 commits intomainfrom
copilot/add-lod-system
Draft

Add LOD system with UE-style screen-size computation, pre-computed distance thresholds, and mesh streaming culling#66
Copilot wants to merge 10 commits intomainfrom
copilot/add-lod-system

Conversation

Copy link
Copy Markdown

Copilot AI commented Feb 16, 2026

Implements a complete LOD system for mesh rendering: screen-size thresholds authored per LOD level, pre-computed into squared-distance thresholds at setup, evaluated at runtime via cheap distance² comparison. Meshes beyond all LOD thresholds are culled from the scene and streamed back in when re-entering range.

Core LOD (LodGroup.h)

  • UE-style ComputeBoundsScreenSize using projection matrix coefficients (max(0.5*M[0][0], 0.5*M[1][1])) — handles FOV + aspect ratio natively
  • PreComputeDistances(config, radius, projMatrix) — inverts screen-size thresholds into squared-distance cache at setup time
  • SelectLodLevel(config, worldBound, viewPos) — runtime path, distance² only, no trig/sqrt per frame
  • Returns INVALID_LOD_LEVEL when beyond all thresholds (enables culling)

Mesh LOD Group (MeshLodGroup)

  • Owns LodConfig + per-LOD RDMeshPtr
  • PreComputeDistances(sphereRadius, projMatrix) bakes the distance cache
  • SelectLod(worldBound, viewPos) delegates to pre-computed path

Mesh Streaming & Culling (MeshRenderer)

  • HidePrimitives() / ShowPrimitives() — remove/re-add primitives to the render scene
  • UpdateLod() — on INVALID_LOD_LEVEL, culls mesh; on re-entry, restores it
  • isVisible / culledByLod state tracking with public getters

Component Integration (StaticMeshComponent)

  • LodMeshAssetData holds mesh UUID + screen-size threshold per LOD
  • lodBias runtime tuning, JSON serialization for LOD mesh array

Runtime flow

// Setup: pre-compute once when projection is known
lodGroup->PreComputeDistances(boundingRadius, projMatrix);

// Per-frame: O(N) distance² comparisons, no trig
uint32_t lod = lodGroup->SelectLod(worldBound, viewPos);
// INVALID_LOD_LEVEL → mesh culled from scene
// Valid LOD → mesh visible, switches LOD mesh if changed

Tests

16 test cases covering screen-size calculation, LOD selection with bias, pre-computed distance equivalence, aspect ratio handling, culling transitions (visible → culled → streamed back), and bias-affected culling thresholds.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 4 commits February 16, 2026 07:19
New files:
- render/lod/LodGroup.h: Core LOD data structures and screen-size calculation
- render/lod/MeshLodGroup.h/.cpp: LOD group container for multiple mesh LOD levels
- test/core/LodTest.cpp: Unit tests for LOD selection logic

Modified files:
- MeshRenderer.h/.cpp: Add LOD group support and UpdateLod method
- MeshFeatureProcessor.h/.cpp: Add per-frame LOD evaluation from camera view
- StaticMeshComponent.h/.cpp: Add LOD mesh configuration and bias settings

Co-authored-by: bluesky013 <35895395+bluesky013@users.noreply.github.com>
… LOD

- Remove unused screenHeight parameter from LOD calculation API
- Compute combined AABB across all primitives for LOD selection
- Remove hardcoded 1080.0f screen height from MeshFeatureProcessor

Co-authored-by: bluesky013 <35895395+bluesky013@users.noreply.github.com>
Co-authored-by: bluesky013 <35895395+bluesky013@users.noreply.github.com>
Co-authored-by: bluesky013 <35895395+bluesky013@users.noreply.github.com>
Copilot AI changed the title [WIP] Add a new LOD system implementation Add screen-size based LOD system for static meshes Feb 16, 2026
Copilot AI requested a review from bluesky013 February 16, 2026 07:24
…tion

- Add LodPolicy enum (SCREEN_SIZE, DISTANCE) to LodGroup.h
- Add distance field to LodLevel struct
- Add CalculateDistance() for distance-based LOD
- Add SelectLodByDistance() and SelectLodByScreenSize() functions
- Add SelectLodLevel() overload that dispatches by policy
- Update MeshLodGroup with AddLodMesh(mesh, screenSize, distance) overload
- Update MeshLodGroup with SetLodPolicy() method
- Update StaticMeshComponent with LodPolicy support and serialization
- Add comprehensive unit tests for distance-based LOD selection

Co-authored-by: bluesky013 <35895395+bluesky013@users.noreply.github.com>
Copilot AI changed the title Add screen-size based LOD system for static meshes Add LOD policy support for distance-based and screen-size based selection Feb 16, 2026
Copilot AI and others added 2 commits February 16, 2026 14:27
…ction

Replace the dual LodPolicy (SCREEN_SIZE/DISTANCE) system with a unified
approach: users author LOD thresholds as screen-size values, which are
pre-computed into squared-distance thresholds. At runtime, LOD selection
only needs a cheap distance² comparison instead of expensive screen-size
calculation (which requires tan, division, sqrt).

Key changes:
- Add ScreenSizeToDistance() conversion and PreComputeDistances()
- Add CalculateDistanceSq() for squared-distance (avoids sqrt)
- SelectLodLevel(config, worldBound, viewPos) uses pre-computed distances
- Remove LodPolicy enum, distance field from LodLevel
- MeshLodGroup::PreComputeDistances(radius, fov) pre-computes cache
- MeshRenderer::UpdateLod() no longer needs fov parameter
- MeshFeatureProcessor::UpdateLod() no longer extracts FOV from projection
- StaticMeshComponent simplified: removes policy/distance fields
- Tests verify pre-computed distances match screen-size LOD selection

Co-authored-by: bluesky013 <35895395+bluesky013@users.noreply.github.com>
…anceSq)

Co-authored-by: bluesky013 <35895395+bluesky013@users.noreply.github.com>
Copilot AI changed the title Add LOD policy support for distance-based and screen-size based selection Pre-compute distance thresholds from screen-size for O(1) runtime LOD selection Feb 16, 2026
…tation

Replace FOV-based screen-size calculation with UE's projection-matrix-based
approach using ComputeBoundsScreenSize:
- GetScreenMultiple(projMatrix): extracts max(0.5*M[0][0], 0.5*M[1][1])
- ComputeBoundsScreenSize(radius, dist, screenMultiple): UE-style formula
- CalculateScreenSize now takes Matrix4 projMatrix instead of float fov
- ScreenSizeToDistance uses screenMultiple instead of halfTanFov
- PreComputeDistances takes Matrix4 projMatrix instead of float fov
- MeshLodGroup::PreComputeDistances updated to take Matrix4 projMatrix
- Tests updated with MakePerspective and new aspect ratio test

Co-authored-by: bluesky013 <35895395+bluesky013@users.noreply.github.com>
Copilot AI changed the title Pre-compute distance thresholds from screen-size for O(1) runtime LOD selection Add LOD system with UE-style screen-size computation and pre-computed distance thresholds Feb 16, 2026
When a mesh is beyond all LOD thresholds (INVALID_LOD_LEVEL), it is now
culled by removing its primitives from the render scene. When the camera
moves closer and the mesh comes back into LOD range, it is restored
(streamed back in) by re-adding its primitives to the scene.

Changes:
- MeshRenderer: add isVisible/culledByLod tracking, ShowPrimitives/HidePrimitives
- MeshRenderer::UpdateLod: cull on INVALID_LOD_LEVEL, restore on re-entry
- MeshRenderer::Reset: reset visibility state
- Tests: LodCullingWhenBeyondAllThresholds, LodCullingTransition,
  LodCullingWithScreenSizeFallback, LodCullingWithBias

Co-authored-by: bluesky013 <35895395+bluesky013@users.noreply.github.com>
Copilot AI changed the title Add LOD system with UE-style screen-size computation and pre-computed distance thresholds Add LOD system with UE-style screen-size computation, pre-computed distance thresholds, and mesh streaming culling Feb 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants