Downscaling high resolution asset causes blurry jagged edges

Godot Version

4.4

Question

I have a 800x400 image that looks fine if I keep it at that scale on my canvas, but if I downscale it (4-5x), it looks like complete crap and jagged.

If I import it as 80x40, it also looks like crap because its now low resolution.

What are my options here? I’ve imported it with every option under the sun and cannot get a clean looking image.
image

If I zoom in on the editor it looks better, if I scale it up and load the game, it looks fine. But if I keep it as a smaller image it just turns to mush.

The file you uploaded is a .png Have you tried converting it to an .svg?

Yes, even with an svg its the same result. But you can’t convert from a png → svg.

1 Like

What happens if you downscale it in an art program?

Do you have to keep a 800x400 copy of this texture? does your game scale in and out dramatically? If not, then only keep a lower resolution 80x40 texture and use a better down-scaling technique than nearest; for example GIMP has LoHalo and cubic downscaling, Godot and Krita has lanczo


This grainy effect is because Godot (really your GPU) downscales by nearest-neighbor interpolation. This is a much larger problem in 3D games as far-away objects would also be downscaled and look grainy, the solution in 3D is to make mipmaps, automatically downscaling the texture at half-resolution intervals at the cost of more vram usage.

I’m not sure that mipmaps are used in Godot’s 2D renderer, but you can try enabling them in the image’s import options.

1 Like

No, I can keep it as a 80x40 texture, but having to re-export lots of times to get the correct resolution seems like a pain, there has to be a better way, surely?

Mipmaps don’t seem to make a difference at all and I’m using linear texture flitering, not nearest.

You can measure in Godot with the ruler tool to get a accurate desired pixel size

Doesn’t matter for downscaling.

I see, I guess exporting to the correct size is the way then.

Only other question I have then is if I have a 800x400 asset that I want to display at 400x200, dynamically? I guess this would either require 2 seperate assets, or I would have to put up with the jaggedness?

Looks like you can specify linear_mipmap texture filtering on canvas items such as Sprite2D. If your game scales this creatue dynamicly by amounts greater than half then you can set this canvas item to linear_mipmap, if your entire project zooms in and out again by at least a factor of 2 then you can set this project setting to default to linear with mipmap

rendering/textures/canvas_textures/default_texture_filter

But again this will waste some texture memory, it is better to have accurate textures if you do not scale wildly, though mipmaps are a small price to pay.