HandlingHighDPI
Handling High DPI (Retina) displays in WebGL
There are an increasing number of devices on the market that have displays with very high pixel densities (DPI), such as the Macbook Pro with Retina display. WebGL applications can take advantage of the higher resolution these devices provide but doing so requires some code changes to the application itself. Fortunately these changes are minor and generally non-disruptive, which makes it easy to prepare your WebGL code for these new devices.
Resizing the Canvas
On High DPI displays browsers will automatically upscale most content to ensure that it appears the right size on screen, which is done behind the scenes to prevent the majority of web sites from breaking. In the case of WebGL content, this causes the canvas to render at it's usual resolution and then upscale to fit the on-screen canvas bounds. The practical effect of this is that an unmodified WebGL application will appear to be rendering at a lower-than-native resolution, which can introduce undesired aliasing.
To avoid this developers should scale the canvas width and height by the value of `window.devicePixelRatio` during setup.
var desiredWidthPixels = 800;
var desiredHeightPixels = 600;
var canvas = document.getElementById("myCanvas");
canvas.width = desiredWidthPixels * window.devicePixelRatio;
canvas.height = desiredHeightPixels * window.devicePixelRatio;
var gl = canvas.getContext("webgl");
`window.devicePixelRatio` describes the ratio between CSS pixels and native device pixels. On most desktops and laptops with low DPI displays devicePixelRatio is 1, which means nothing will be scaled. On devices like the Retina Macbook Pro or Galaxy Nexus the devicePixelRatio is 2. These values aren't required to be integers, however: On the Nexus One the devicePixelRatio reports as 1.5.
Handling Input
It's important to note that even though the resolution of the canvas has increased other values provided by the DOM will not adjust accordingly. A good example is mouse or touch input. Coordinates are still delivered in terms of CSS pixels, and thus must be transformed if you need them to line up exactly with the resized canvas pixels. You also need to keep in mind that the canvas position will still be reported in CSS pixels, so adjustments to account for element offsets should not use the devicePixelRatio.
canvas.addEventListener("mousemove", function(e) {
var canvasX = (e.pageX - canvas.offsetLeft) * window.devicePixelRatio;
var canvasY = (e.pageY - canvas.offsetTop) * window.devicePixelRatio;
// Perform some operation with the transformed coordinates
}, false);