Quick answer: Godot 4 defaults to Linear texture filtering, which smooths pixels when sprites are scaled. For pixel art, you need Nearest filtering which preserves hard pixel edges. Change this in Project Settings > Rendering > Textures > Default Texture Filter.

Here is how to fix Godot 2D sprites blurry when scaled. Your pixel art looked crisp in your image editor, but in Godot 4 everything appears soft and smeared. Characters, tiles, and UI elements all look like they have been run through a blur filter. This is the single most common visual complaint from developers starting a pixel art project in Godot, and the fix takes less than a minute once you know where to look.

The Symptom

Sprites that should have sharp, defined pixels instead appear blurry and smoothed out. The effect is most obvious on pixel art with small source resolutions — a 16x16 character sprite scaled up to fill the screen looks like a watercolor painting instead of crisp blocks of color. Text rendered as bitmap fonts may also appear soft and hard to read.

The blurriness appears regardless of how the sprite is scaled. Whether you set the sprite's scale property, increase the viewport size, or zoom the camera in, the result is the same mushy rendering. Even sprites at 1:1 scale can appear slightly soft if the viewport resolution does not match the window size.

You may notice that the blurriness is consistent — it does not flicker or change as objects move. This distinguishes it from tile seam artifacts, which tend to appear and disappear with camera movement. Blurry sprites look uniformly soft at all times.

What Causes This

Godot 4 defaults to Linear texture filtering for all textures. Linear filtering is the correct choice for HD games with high-resolution art, where smooth interpolation between texels produces better-looking results at varying scales. But for pixel art, it is exactly wrong.

When the GPU scales a texture using linear filtering, it blends neighboring texels together to produce a smooth gradient. A sharp edge between a red pixel and a blue pixel becomes a soft gradient through purple. For pixel art, where every individual pixel is intentionally placed, this destroys the visual style entirely.

The filter setting operates at three levels in Godot 4, and all three need to be correct:

The Fix

Step 1: Change the project-wide default. Open Project → Project Settings → Rendering → Textures and set Default Texture Filter to Nearest. This ensures every new texture and every node without a specific override uses nearest-neighbor filtering.

# This is what changes in project.godot:
# [rendering]
# textures/canvas_textures/default_texture_filter = 0
# 0 = Nearest, 1 = Linear

Step 2: Reimport existing textures. Textures imported before you changed the default still have their old settings baked in. Select all your sprite textures in the FileSystem dock (hold Shift to multi-select), open the Import tab at the top, and change the Filter to Nearest. Click Reimport.

# To reimport all textures via the command line or script:
# Delete the .godot/imported/ folder and reopen the project.
# Godot will reimport everything with the new default.

# Or reimport specific files in code (editor plugin):
var reimporter = EditorInterface.get_resource_filesystem()
reimporter.reimport_files(["res://sprites/player.png"])

Step 3: Set viewport stretch mode. For pixel art projects, go to Project → Project Settings → Display → Window → Stretch and set Mode to viewport. This renders your game at the base resolution you define and then scales the entire viewport up to the window size using nearest-neighbor interpolation. Set your base resolution to your intended pixel art resolution, such as 320x180 or 640x360.

# Example project.godot settings for a pixel art game:
# [display]
# window/size/viewport_width = 320
# window/size/viewport_height = 180
# window/size/window_width_override = 1280
# window/size/window_height_override = 720
# window/stretch/mode = "viewport"
# window/stretch/aspect = "keep"

Step 4: Handle per-node overrides if needed. If specific nodes still look blurry after the above steps, they may have a per-node texture filter set. Check the CanvasItem section of the inspector and ensure Texture Filter is set to Inherit or Nearest.

# Force nearest filtering on a specific node via code
extends Sprite2D

func _ready():
    texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST

Why This Works

Nearest-neighbor filtering (also called point filtering) tells the GPU to pick the single closest texel to the sample point without any interpolation. When you scale a 16x16 sprite up by 4x, each source pixel becomes a clean 4x4 block of the same color on screen. There is no blending, no smoothing, and no loss of the original pixel art sharpness.

The viewport stretch mode is equally important because it controls how the final image reaches the screen. Without it, Godot may render at the window resolution and then scale your sprites, which can introduce filtering even with Nearest set. With viewport mode, the entire game renders at your base resolution first, and only the final composite is scaled up — ensuring pixel-perfect results regardless of the player's monitor size.

"Every pixel art Godot tutorial should start with these two settings. It would save thousands of developers twenty minutes of confused searching."

Related Issues

If you are seeing black lines between tiles instead of blurriness, the cause is related but the fix is slightly different. See Fix: Godot Sprites Showing Black Lines or Gaps Between Tiles for a guide on atlas padding and pixel snap.

If your sprites render correctly but are layered in the wrong order, check Fix: Z-Index Not Working Correctly in Godot 2D for z-ordering troubleshooting.

For shader-related rendering problems like a pink or magenta screen, see Fix: Godot Shader Causing Pink/Magenta Screen.

Nearest filter. Viewport stretch. Crisp pixels.