# How do you stop pixel-art sprites from shimmering when the camera eases?

**URL:** <https://forum.kirupa.com/t/how-do-you-stop-pixel-art-sprites-from-shimmering-when-the-camera-eases/681026>\
**Category:** web dev\
**Created:** [April 30, 2026, 7:00am UTC](https://forum.kirupa.com/t/how-do-you-stop-pixel-art-sprites-from-shimmering-when-the-camera-eases/681026 "2026-04-30T07:00:14Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Quelly](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/quelly/32/31386_2.png) [@Quelly](https://forum.kirupa.com/u/Quelly)\
**Post date:** [April 30, 2026, 7:00am UTC](https://forum.kirupa.com/t/how-do-you-stop-pixel-art-sprites-from-shimmering-when-the-camera-eases/681026/1 "2026-04-30T07:00:14Z")

</div>

What’s up everyone? I’m working on a little canvas pixel-art game and I’m trying to add a smooth easing camera, but my sprites start shimmering when the camera moves slowly (looks like half-pixel sampling). If I round the camera position I lose the smooth feel, and if I don’t, nearest-neighbor still looks weird.

```js
const scale = 4;
const cam = { x: 0, y: 0 };

function draw(ctx) {
  ctx.imageSmoothingEnabled = false;
  ctx.setTransform(scale, 0, 0, scale, 0, 0);

  const cx = cam.x; // tried Math.round(cam.x)
  const cy = cam.y;

  ctx.translate(-cx, -cy);
  drawTilemap(ctx);
  drawSprites(ctx);
}

```

What’s the cleanest way to keep smooth camera easing while guaranteeing pixel-perfect alignment so the scene doesn’t shimmer?

Quelly

---

<div class="post-metadata">

**Author:** ![VaultBoy](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/vaultboy/32/31832_2.png) [@VaultBoy](https://forum.kirupa.com/u/VaultBoy)\
**Post date:** [April 30, 2026, 8:28am UTC](https://forum.kirupa.com/t/how-do-you-stop-pixel-art-sprites-from-shimmering-when-the-camera-eases/681026/2 "2026-04-30T08:28:27Z")

</div>

shimmering is basically your camera doing a slow-mo “subpixel slide” so the sampler keeps flipping which source pixel wins each frame.

keep the eased camera as floats, but snap only the _render transform_ to the screen pixel grid (1/scale in world units):

```auto
const scale = 4;
const snap = v => Math.round(v * scale) / scale;

function draw(ctx) {
  ctx.imageSmoothingEnabled = false;
  ctx.setTransform(scale, 0, 0, scale, 0, 0);
  ctx.translate(-snap(cam.x), -snap(cam.y));

  drawTilemap(ctx);
  drawSprites(ctx);
}

```

you still get smooth easing in the camera math, but the actual draw lands on exact pixel boundaries so nearest-neighbor stops doing that “sparkle” thing.
