diff --git a/packages/viewer/src/components/viewer/frame-limiter.tsx b/packages/viewer/src/components/viewer/frame-limiter.tsx index 11155d41f..cb0753170 100644 --- a/packages/viewer/src/components/viewer/frame-limiter.tsx +++ b/packages/viewer/src/components/viewer/frame-limiter.tsx @@ -6,6 +6,20 @@ type FrameLimiterProps = { fps?: number } +// `?disable=draw` (see post-processing.tsx): the page renders no real frames, +// and Chromium's no-damage scheduler then throttles requestAnimationFrame to +// 1Hz on Linux (measured in the headless bake worker — every useFrame system +// ticked once per second and a heavy scene took 300+ seconds to settle). A +// plain timer is never throttled on a visible page, so drive the loop with +// setInterval instead of rAF when nothing is drawn. +const DRAW_DISABLED = + typeof window !== 'undefined' && + new Set( + (new URLSearchParams(window.location.search).get('disable') ?? '') + .split(',') + .map((s) => s.trim()), + ).has('draw') + const FrameLimiter: React.FC = ({ fps = 50 }) => { const { advance, set, frameloop: initFrameloop, scene, clock } = useThree() const renderer = useThree((state) => state.gl) @@ -18,6 +32,7 @@ const FrameLimiter: React.FC = ({ fps = 50 }) => { let then = 0 let i = 0 let raf: number | null = null + let timer: ReturnType | null = null const interval = 1000 / fps function tick(t: DOMHighResTimeStamp) { raf = requestAnimationFrame(tick) @@ -30,13 +45,23 @@ const FrameLimiter: React.FC = ({ fps = 50 }) => { } // Set frameloop to never, it will shut down the default render loop set({ frameloop: 'never' }) - // Kick off custom render loop - raf = requestAnimationFrame(tick) + if (DRAW_DISABLED) { + timer = setInterval(() => { + i += interval / 1000 + advance(i) + }, interval) + } else { + // Kick off custom render loop + raf = requestAnimationFrame(tick) + } // Restore initial setting return () => { if (raf) { cancelAnimationFrame(raf) } + if (timer) { + clearInterval(timer) + } set({ frameloop: initFrameloop }) } }, [fps, advance, set, initFrameloop, renderPaused])