Fix Blurry and Jagged Sprites When Scaling in Phaser CE: Texture Filtering, Mipmaps, and Asset Strategy
The actual cause of blurry and jagged sprites in Phaser CE
When sprites look jagged or blurry at non-native scales in Phaser CE, the culprit is almost always texture filtering — not your asset dimensions, not your scale values. Phaser CE sits on top of PIXI.js, and depending on how the renderer initializes, it can end up using nearest-neighbor sampling. That mode looks crisp at a 1:1 pixel ratio and awful everywhere else.
One line, placed before your game is created, changes that:
PIXI.scaleModes.DEFAULT = PIXI.scaleModes.LINEAR;
This switches the default to bilinear interpolation, which blends neighboring pixels when the texture is sampled at a non-native size. It won’t make an 0.11-scale card look like a full-resolution image, but it removes the hard pixel staircase edges that make small sprites look broken. Start here before anything else.
About that third parameter in load.image
The signature for this.load.image() in Phaser CE is:
this.load.image(key, url, overwrite);
That third argument is an overwrite flag — a boolean that tells the loader whether to replace an existing cache entry with the same key. It has nothing to do with mipmaps. So setting it to true won’t affect rendering quality at all.
Mipmaps: what they actually require
Mipmaps are pre-generated lower-resolution copies of a texture stored alongside the original. The GPU picks the right level automatically based on how small the texture is being drawn, which gives much cleaner results than bilinear filtering alone at heavy downscales.
The constraint: standard WebGL 1.0 only supports mipmaps on power-of-2 textures. That means dimensions that are 128, 256, 512, 1024, 2048 pixels, and so on. Your 700×1050 card assets don’t qualify. Trying to generate mipmaps on a non-power-of-2 texture in WebGL 1 either silently fails or falls back to clamped addressing with no mipmaps.
To use them properly you’d need to resize your source art to something like 512×1024 or 1024×2048, then enable mipmap generation on the base texture after loading:
var base = PIXI.BaseTextureCache['your-image-key'];
if (base) {
base.mipmap = true;
// Mark all renderer contexts dirty so the texture re-uploads
base._dirty[0] = true;
base._dirty[1] = true;
base._dirty[2] = true;
base._dirty[3] = true;
}
At 0.11 scale you’re rendering a 700px-wide texture into roughly 77 pixels — an 89% reduction. That’s exactly the range where mipmaps earn their keep. At 0.35 scale, bilinear filtering alone is usually fine.
Multiple resolution assets: more practical than it sounds
The multi-asset approach feels like a lot of work upfront, but for a card game it maps cleanly to the states you already have: a small “in hand” size, a medium “played” size, and a large “hovered” size. You don’t need a full mipmap pyramid — two sizes is usually enough.
Load them under separate keys, then swap textures as the scale crosses a threshold during your tween:
// Preload
this.load.image('card-full', 'assets/card_700x1050.png');
this.load.image('card-small', 'assets/card_175x263.png'); // ~0.25x pre-rendered
// In your tween onUpdate callback
if (cardSprite.scale.x < 0.2 && currentTexture !== 'card-small') {
cardSprite.loadTexture('card-small');
// Adjust scale since the base size changed
cardSprite.scale.setTo(cardSprite.scale.x * 4);
currentTexture = 'card-small';
} else if (cardSprite.scale.x >= 0.2 && currentTexture !== 'card-full') {
cardSprite.loadTexture('card-full');
cardSprite.scale.setTo(cardSprite.scale.x * 0.25);
currentTexture = 'card-full';
}
A 175×263 card rendered at 0.44 scale looks dramatically better than a 700×1050 card at 0.11. The swap is invisible during the tween if you pick the threshold right.
Canvas renderer fallback
Phaser CE falls back to Canvas rendering on some systems. The PIXI scale mode setting only affects WebGL. For Canvas, smooth scaling depends on the browser’s imageSmoothingEnabled property on the 2D context, and you can nudge Phaser toward it with:
game.stage.smoothed = true;
If you’re not sure which renderer you’re running, log game.renderType — it returns 1 for Canvas, 2 for WebGL.
Where to start
In order of effort and likely impact: add the PIXI.scaleModes.DEFAULT line first and see how far that gets you. If the 0.11 and 0.17 scale states still look rough, add a single smaller version of your card assets for those states. Mipmaps are worth it only if you need the extra quality and can commit to resizing your art to power-of-2 dimensions.
