Three.js Mobile Performance: Limit Device Pixel Ratio
Limiting the device pixel ratio (DPR) in Three.js is one of the most effective techniques for boosting rendering framerates on mobile devices. Modern smartphones feature high-density displays (such as Retina screens) with pixel ratios of 3x or even 4x, which forces the GPU to render millions of extra pixels. By capping the DPR to a maximum of 2, developers can drastically reduce the workload on mobile graphics hardware, resulting in significantly higher frames per second (FPS), reduced battery consumption, and less device overheating.
Understanding Device Pixel Ratio (DPR)
The device pixel ratio is the relation between physical pixels and logical (CSS) pixels on a screen. On a standard desktop monitor, the ratio is 1:1 (DPR of 1). On a high-end mobile device, the ratio is often 3:1 or higher (DPR of 3+).
When Three.js initializes a renderer, it determines the size of the
WebGL canvas based on the logical dimensions of the container. If you
pass the raw window.devicePixelRatio directly to the
renderer, Three.js scales the canvas resolution to match the physical
pixels of the screen.
The Mobile GPU Fill-Rate Bottleneck
In WebGL rendering, the primary performance bottleneck on mobile devices is often the “fill rate”—the speed at which the GPU can write pixels to the screen.
When rendering at a DPR of 3, the GPU must calculate and render nine times as many pixels as it would at a DPR of 1 (since pixel count scales quadratically: \(3 \times 3 = 9\)). Mobile GPUs are designed to be energy-efficient and thermally constrained; forcing them to process nine times the data for a 3D scene quickly leads to thermal throttling, dropped frames, and lag.
Why Limiting DPR to 2 is the Sweet Spot
To solve this, WebGL developers restrict the pixel ratio. A DPR of 2 is widely considered the optimal limit for mobile devices.
On a small handheld screen, the human eye cannot easily distinguish the visual quality difference between a DPR of 2 and a DPR of 3 or 4. However, the performance difference is massive. Dropping the DPR from 3 to 2 reduces the number of pixels the fragment shader must process by more than 55%. This massive reduction in fragment shader load instantly frees up GPU resources, allowing Three.js to maintain a stable 60 FPS.
Implementing DPR Limits in Three.js
Applying this optimization in Three.js requires just one line of
code. Instead of passing the raw window.devicePixelRatio to
the renderer, you can use Math.min() to cap the value:
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
// Cap the device pixel ratio at 2
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));This ensures that devices with a DPR of 1 or 1.5 render at their native resolutions, while high-density devices with a DPR of 3 or higher are safely capped at 2. This simple adjustment ensures a smooth, highly responsive 3D experience across all mobile platforms without sacrificing visual fidelity.