Faking an Infinite Runner in Three.js with a Moving Ground Plane and Fog
The infinite-runner illusion is a common game and visualization pattern, but most tutorials move the camera or the character. Keeping both fixed and scrolling only the environment is simpler to control, avoids coordinate drift, and pairs naturally with fog to hide the seam — a compact, production-ready pattern for any WebGL project that needs an endless scrolling surface.
A character model plays its built-in running animation on a fixed spot while a massive 16,000-unit grass plane shifts backward every frame. Once the plane reaches a -500 offset, its position resets to zero, creating a seamless, infinite runway without moving the camera or the model. The grass texture tiles 64 times in each direction using RepeatWrapping to avoid visible stretching across the large surface.
Linear white fog with a near distance of 280 and a far distance of 1,050 fades the distant ground into white, masking the plane's hard edge and adding depth. A spotlight casts shadows, a hemisphere light fills the scene, and the renderer adapts to window resizes and device pixel ratios.
The full Vue component includes a resource disposal method that cancels the animation frame, traverses the scene to dispose of geometries and materials, and forces a WebGL context loss to prevent memory leaks when the component unmounts.
The decision to move the ground instead of the character or camera keeps the animation loop dead simple: one position update per frame with a hard reset, no accumulation of floating-point errors over long runs.
Using a 16,000-unit plane with a 500-unit scroll window is overkill for the visual effect, but it guarantees the reset is never visible even if the frame rate drops or the scroll speed changes — a brute-force approach that eliminates edge cases.
The fog does double duty: it's an aesthetic choice that also solves the engineering problem of hiding the plane's boundary, turning a visual limitation into a deliberate stylistic feature.