Skip to content
pixi-silk
GitHub repository
Reference

Resolution & DPR

createSilkApp maps the canvas 1:1 to device pixels, even at fractional DPRs, follows DPR changes and renders filters at screen resolution.

Updated pixi-silk 1.0.1View as Markdown

createSilkApp gives you a canvas whose pixels are the screen’s pixels. Exact edges need that as much as they need the shader: if the browser rescales the canvas, every edge goes soft.

Switch between 1x and your device resolution.

Create a sharp canvas#

import { createSilkApp } from 'pixi-silk';

const silk = await createSilkApp({
    parent: document.getElementById('stage')!,
    background: 0x000000,
    maxResolution: 3,
});

silk.app; // the Pixi Application
silk.width; // CSS pixels
silk.resolution; // device pixels per CSS pixel
silk.setResolution(1); // compare at 1x, null returns to devicePixelRatio
silk.destroy();

The canvas fills parent, so the parent needs a size. Every other option is a Pixi ApplicationOptions field and passes through.

OptionDefaultWhat it does
parentrequiredElement the canvas fills
maxResolution3Upper bound for the resolution, to cap memory and fill rate
fixedResolutionnoneForces a resolution instead of following devicePixelRatio
onResizenoneCalled after every size or resolution change, with the size in CSS pixels
inheritFilterResolutiontrueNew Pixi filters render at the renderer resolution
touchAction'pan-y pinch-zoom'CSS touch-action of the canvas
preference'webgl'Renderer Pixi tries first. See renderers

What it sets up#

The backing store is sized from devicePixelContentBoxSize, so one canvas pixel is one device pixel, even at a DPR of 1.5 or 2.625. Rounding cssWidth * dpr yourself can be off by one pixel. The browser then resamples the whole canvas and blurs it. Safari has no device pixel box, so there the size is rounded.

The canvas follows DPR changes, such as browser zoom or a move to another display.

MSAA is off (antialias: false), because the shader already computes coverage. Pixel rounding is off too (roundPixels: false), so slow motion moves by fractions of a pixel instead of snapping.

Pixi filters render at resolution 1 by default, which blurs everything behind a filter on a retina screen. createSilkApp sets Filter.defaultOptions.resolution to 'inherit'. Turn that off with inheritFilterResolution: false.

Pixi sets touch-action: none on its canvas, which stops the page from scrolling on phones. The default here lets the page scroll. Use touchAction: 'none' for a canvas that handles drags itself.

Your own Application#

If you create the application yourself, use the same settings:

await app.init({
    preference: 'webgl',
    antialias: false,
    autoDensity: true,
    resolution: window.devicePixelRatio,
    roundPixels: false,
});
Filter.defaultOptions.resolution = 'inherit';

This does not size the backing store to exact device pixels or follow DPR changes. For that, use createSilkApp or copy its ResizeObserver code.

Render textures and filters#

A SilkGraphics in a render texture or behind a filter is anti-aliased at that target’s resolution. Give render textures the renderer’s resolution to keep them sharp on retina screens. The render texture experiment shows the difference.

API reference: createSilkApp, SilkAppOptions, SilkApp

Go deeper

Experiments on this page

Full-screen scenes. Each one also opens in Studio with its source.