Pixels flickering when changing camera zoom

Godot Version

4.2+

Question

I am working on a 2D game where using a sprite2D node for the background (it’s pixels are calculated by a shader code), and a camera2D node for zooming and moving.

Problem (I hope you can see it on this video):

So when i am changing the zoom value, the background textures’ pixels are “moving” or something like that.

Using this code for changing the zoom with the use of Tweens (for the animation):

private readonly float zoomSteps = new float { 5f, 30f, 45f };

public override void _UnhandledInput(InputEvent @event)
{
if (@event is InputEventMouseButton)
{
InputEventMouseButton mouseEvent = (InputEventMouseButton)@event;

        if (mouseEvent.IsPressed())
        {
            if (IsInstanceValid(ZoomTween) && ZoomTween.IsValid())
            {
                ZoomTween.Kill();
            }

            ZoomTween = CreateTween();
            if (mouseEvent.ButtonIndex == MouseButton.WheelUp)
            {
                if (zoomIdx != zoomSteps.Length - 1)
                    zoomIdx++;
            }

            if (mouseEvent.ButtonIndex == MouseButton.WheelDown)
            {
                if (zoomIdx != 0)
                    zoomIdx--;
            }

            ZoomTween
                .TweenProperty(
                    this,
                    "zoom",
                    new Vector2(zoomSteps[zoomIdx], zoomSteps[zoomIdx]),
                    1
                )
                .SetEase(Tween.EaseType.InOut)
                .SetTrans(Tween.TransitionType.Cubic);
        }
    }

I tested it a little bit, and found that when i am not using a Math.Lerp or Tween to interpolate between the start and end values than there is no flickering.
This video shows it:

Code:
private void UpdateCameraZoom(float delta)
{
float newZoomX = zoomSteps[zoomIdx];
float newZoomY = zoomSteps[zoomIdx];

    Zoom = new(newZoomX, newZoomY);
}

I tried the followings:

  • reimported assets with enabled mipmap
  • enabled the snap 2d transforms to pixel option
  • changed the default filter option

Do you have any tip how to solve this?

Thanks in advance.

I can’t really see the problem on the video (maybe because of youtube’s compression) but it’s not the best to change your camera zoom by lerping or tweening. It’s better to jump in integer intervals. 1, 2, 3, 4… if you lerp, there are frames on your screen that are going to be rendered as “pixel_width x 1.274” or “pixel_width x 2.617” which are going to give you that flickering, since pixel positions are absolute integers, your screen can’t draw half of a pixel. Your computer will collapse the value to either showing you the pixel in that frame or not. And this is the flickering you see because of the different sizes of your image lines and colors and the ratios between them changing every frame.

Try using integer steps.

Hi, thanks for the quick answer. I understand your point, but if i am using just integer values for the zoom steps, then the zooming will not be “smooth”, since we are using big steps instead of the float values.

So how to achieve the same smooth animation behaviour as tweet does when using just integer steps?