Pixel Scaling in p5.js – Retro Look with Sharp Edges

When drawing pixel art or retro-style graphics in p5.js, images often appear blurry when scaled up. This is caused by default image interpolation applied by browsers. To preserve crisp, pixel-perfect edges, this behavior must be overridden explicitly.

Objective

- Draw a small image (e.g., 64×64 pixels).
- Display it scaled up on the main canvas.
- Ensure sharp, non-blurry edges — no smoothing.

Solution Overview

The method involves:

  • Using the WEBGL renderer for full texture control,
  • Creating an off-screen createGraphics() buffer,
  • Disabling interpolation with setInterpolation(NEAREST, NEAREST),
  • Manually flipping and translating coordinates to simulate 2D behavior in WEBGL.

Example Code

let pg;
let pixelSize = 10;

function setup() {
  createCanvas(800, 800, WEBGL);
  noSmooth();
  canvas.imageSmoothingEnabled = false;

  pg = createGraphics(64, 64, WEBGL);
  pg.noSmooth();
  pg.imageMode(CORNER);
  pg.pixelDensity(1);
  pg.ortho();

  pg.push();
  pg.scale(1, -1);
  pg.translate(-32, -32);

  pg.background(192);
  pg.noFill();
  pg.stroke(0);
  pg.rect(0, 0, 64, 64); 
  pg.rect(2, 2, 60, 60); 
  pg.rect(4, 4, 56, 56);
  pg.ellipseMode(CENTER);
  pg.fill(90);
  pg.ellipse(32, 32, 54, 54);
  pg.pop();

  imageMode(CENTER);
  this._renderer.getTexture(pg).setInterpolation(NEAREST, NEAREST);
}

function draw() {
  background(90);
  scale(1, -1);
  scale(pixelSize);
  image(pg, 0, 0);
}

Key Points

  • Why WEBGL? — Only in WEBGL mode can texture interpolation be changed to NEAREST.
  • Why ortho() and scale(1, -1)? — The WEBGL coordinate system flips the Y axis. These adjustments simulate typical 2D top-left-based layouts.
  • imageMode(CORNER) and CENTER — Proper positioning depends on matching mode with transform logic.

Result

The output appears crisp and blocky as expected from pixel art, even when upscaled 10× or more. No anti-aliasing or smoothing occurs. This replicates the visual style of old video game systems or emulators.

Pixel Scaling Result Image

Conclusion

With careful setup, p5.js supports clean, pixel-perfect rendering without the need for external tools or shaders. createGraphics(), WEBGL, and setInterpolation() together offer full control for retro-style rendering and grid-based visuals.