Fix Your Timestep!
Source: https://gafferongames.com/post/fix_your_timestep/ Author: Glenn Fiedler | Date: 2004-06-10 | Series: Game Physics
Fixed dt
integrate(state, t, dt); render; t += dt is ideal if dt matches refresh and frame always finishes in time; else sim runs fast/slow.
Variable dt
Measure previous frame duration → next dt. Physics behavior depends on dt (feel changes, springs explode, tunneling). Cannot handle arbitrary dt.
Semi-fixed
Clamp substeps to max dt; subdivide leftover. Upper-bounds dt but multiple steps per display; risk spiral of death if sim of X seconds takes >X real time. Mitigate: headroom, or clamp max steps/frame (slow-mo under load).
Free the physics (fixed dt + variable render)
Renderer produces time; simulation consumes it in discrete dt via accumulator:
accumulator += frameTime
while accumulator >= dt:
integrate(current, t, dt)
accumulator -= dt
t += dt
render(state)
Only integrate with exact dt → reproducibility (helps deterministic lockstep). Leftover accumulator time is not discarded.
Render interpolation
Remainder means displayed state is slightly off render time → stutter. Keep previous and current physics state; alpha = accumulator/dt; lerp (slerp quats) for render. Clamp huge frameTime (e.g. 0.25s) after breakpoint/hitch.