You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to #74. Roadmap Phase 2 item (see #57). Terrain LOD (#78), instanced geometry LOD (#80), and hybrid cluster/standard GAS (#81) each use fixed distance thresholds. These work well for a given scene scale but don't adapt to scene complexity — a 10M-triangle city scene needs more aggressive LOD than a sparse rural DEM. A budget system closes the loop: measure actual frame time, adjust LOD thresholds to hit a target.
Goal
Automatic LOD threshold adjustment that maintains a target frame time (e.g. 33ms for 30fps) by pushing LOD transitions closer or farther based on measured render performance.
Current State
TerrainLODManager uses compute_lod_distances() with a fixed lod_distance_factor — all thresholds scale linearly from tile diagonal
If ema_frame_time > target * 1.1: decrease lod_distance_factor by step (push LOD transitions closer → fewer triangles)
If ema_frame_time < target * 0.9: increase lod_distance_factor by step (push transitions farther → more detail)
Dead band (±10%) prevents oscillation when frame time is close to target
Step size proportional to error magnitude, clamped to avoid large jumps
Bounds
min_lod_distance_factor: floor to prevent quality collapse (e.g. 1.0 — LOD transitions no closer than 1× tile diagonal)
max_lod_distance_factor: ceiling to prevent wasted work when GPU is fast (e.g. 10.0)
Per-frame adjustment clamped to ±5% of current factor — smooth, no pops
Budget Metrics (Beyond Frame Time)
Optional secondary metrics for more precise control:
Metric
Source
Use
Total triangle count
Sum of active GAS triangle counts
Hard cap: if > budget, force LOD up regardless of frame time
Total instance count
IAS instance count
Similar hard cap
GPU memory pressure
cuMemGetInfo free/total
Force aggressive LOD when memory is tight
Frame time is the primary metric. Triangle/instance/memory caps are safety valves, not the main control loop.
Integration Points
TerrainLODManager: already accepts lod_distance_factor — budget system adjusts this value, manager recomputes _lod_distances and re-evaluates tiles on next update()
Toggle: Shift+B or similar keybinding — enables/disables auto-budget
HUD: show target FPS, current EMA frame time, current lod_distance_factor, and direction indicator (↑ increasing detail / ↓ decreasing detail / = stable)
When disabled, lod_distance_factor stays at its last value (no snap back to default)
Context
Follow-up to #74. Roadmap Phase 2 item (see #57). Terrain LOD (#78), instanced geometry LOD (#80), and hybrid cluster/standard GAS (#81) each use fixed distance thresholds. These work well for a given scene scale but don't adapt to scene complexity — a 10M-triangle city scene needs more aggressive LOD than a sparse rural DEM. A budget system closes the loop: measure actual frame time, adjust LOD thresholds to hit a target.
Goal
Automatic LOD threshold adjustment that maintains a target frame time (e.g. 33ms for 30fps) by pushing LOD transitions closer or farther based on measured render performance.
Current State
TerrainLODManagerusescompute_lod_distances()with a fixedlod_distance_factor— all thresholds scale linearly from tile diagonalcompute_lod_level()with fixed thresholds_update_frame()returns, GLFW providesglfwGetTime())Design
Feedback Loop
Controller
A simple exponential moving average + proportional controller:
ema_frame_time = α * frame_time + (1-α) * ema_frame_time(α ≈ 0.1, smooth out spikes)ema_frame_time > target * 1.1: decreaselod_distance_factorby step (push LOD transitions closer → fewer triangles)ema_frame_time < target * 0.9: increaselod_distance_factorby step (push transitions farther → more detail)Bounds
min_lod_distance_factor: floor to prevent quality collapse (e.g. 1.0 — LOD transitions no closer than 1× tile diagonal)max_lod_distance_factor: ceiling to prevent wasted work when GPU is fast (e.g. 10.0)Budget Metrics (Beyond Frame Time)
Optional secondary metrics for more precise control:
cuMemGetInfofree/totalFrame time is the primary metric. Triangle/instance/memory caps are safety valves, not the main control loop.
Integration Points
TerrainLODManager: already acceptslod_distance_factor— budget system adjusts this value, manager recomputes_lod_distancesand re-evaluates tiles on nextupdate()lod_distance_factorparameter, or a separate per-layer multiplierLODBudgetController API
Viewer Integration
lod_distance_factor, and direction indicator (↑ increasing detail / ↓ decreasing detail / = stable)lod_distance_factorstays at its last value (no snap back to default)Implementation Plan
LODBudgetControllerclass — inrtxpy/lod.py, pure logic, no viewer dependencies, fully unit-testablelod_distance_factor, callcompute_lod_distances()to update thresholdsScope Boundaries
Key Files
rtxpy/lod.py—compute_lod_distances(), newLODBudgetControllerrtxpy/viewer/terrain_lod.py—TerrainLODManager(consumes adjusted factor)rtxpy/engine.py— tick loop, frame timing, budget controller instancertxpy/viewer/keybindings.py—SHIFT_BINDINGStableReferences