bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Pixelated text font is blurry

Open Adar-Dagan opened this issue 2 years ago • 8 comments

Bevy version

0.12.0

[Optional] Relevant system information

AdapterInfo { name: "NVIDIA GeForce MX150", vendor: 4318, device: 7440, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "535.129.03", backend: Vulkan }

What you did

I am trying to display text in the joystix font.

What went wrong

The font is rendered blurry.

Additional information

To show this I wrote this short example that renders the text using the font under a png of how it should look:

use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    let mut camera = Camera2dBundle::default();
    camera.projection.scale = 0.5;
    commands.spawn(camera);

    commands.spawn(Text2dBundle {
        text: Text::from_section(
            "Ready!",
            TextStyle {
                font: asset_server.load("joystix.ttf"),
                font_size: 11.0,
                color: Color::YELLOW,
            },
        ),
        ..default()
    });

    commands.spawn(SpriteBundle {
        texture: asset_server.load("ready.png"),
        transform: Transform::from_xyz(0.0, 10.0, 0.0),
        ..default()
    });
}

This generates the following screenshot: blurry_text

The png I used for the image: ready And the ttf file of the font is from here.

Adar-Dagan avatar Nov 24 '23 06:11 Adar-Dagan

Have you tried using the git version of bevy? I think this is fixed in #10537

nicopap avatar Nov 24 '23 08:11 nicopap

I just tried running the same code with the git version and I get the same issue: Screenshot from 2023-11-24 11-08-28

Adar-Dagan avatar Nov 24 '23 09:11 Adar-Dagan

This is a separate problem with Text2d, the text can be transformed arbitrarily so you can't just snap it to a pixel aligned position like with UI text, particularly with rotated text it needs some sort of filtering like the sort of thing that is used for 2.5d pixel art games. The simplest workaround atm is to use the UI to draw the text. There are lots of examples online of how to transform world coordinates to screen coordinates, I think Bevy cookbook has one.

ickshonpe avatar Nov 24 '23 11:11 ickshonpe

This is a separate problem with Text2d, the text can be transformed arbitrarily so you can't just snap it to a pixel aligned position like with UI text

Presumably we could pixel align Text2d, we'd just need to do so after all transforms have been applied (an approach which I think would also solve some of the residual rounding issues we've had with UI). And I suspect that at the moment, the rendering system doesn't even know it's text at that point.

nicoburns avatar Nov 25 '23 18:11 nicoburns

Also running into this issue, has anyone else found a workaround? At the moment considering just making my own text component that simply uses an atlas/sprite since I don't need other types of scaling, but I'd rather this get fixed :laughing:

The simplest workaround atm is to use the UI to draw the text. There are lots of examples online of how to transform world coordinates to screen coordinates, I think Bevy cookbook has one.

Unfortunately this doesn't work for a lot of use-cases, depending how dynamic your ui/text is.

jfaz1 avatar Jan 04 '24 21:01 jfaz1

I'm making a pixel art game and zooming on a small area. I want to just draw everything to that area, including UI. Text2d is working but as others have pointed out, it becomes blurry. Working in the window level is a bit painful in my case. Edit: Font I was using said it was 8px but it was blurry except when I set font size 11 and it's multiples. So this wasn't a issue on bevy side.

aoidenpa avatar Jan 22 '24 14:01 aoidenpa

I'm also having this issue with some pixel art fonts. Most fonts work just fine when you specify the size as indicated by the font maker, but some require using a different size and some just doesn't work at all (it stays blurry).

For example: https://github.com/itouhiro/PixelMplus/releases

The PixelMplus10 variant is only sharp when you set font_size: 11.0, even though it's supposed to be 10px font. The PixelMplus12 variant on the other hand stays blurry at all sizes I've tried.

I wonder what's causing this to happen?

musjj avatar Jun 06 '24 18:06 musjj

With Bevy main / cosmic-text.

image

This cosmic-text issue may be relevant: https://github.com/pop-os/cosmic-text/issues/279

rparrett avatar Aug 22 '24 23:08 rparrett

With #15368:

image

Note: The letter E is slightly stretched, this seems to be due to the font being fractionally offset from the pixel grid, combined with our usage of a threshold to implement the non-smoothed version (due to the current COSMIC Text limitations). I tried other pixel fonts and didn't hit this issue.

Here's the example updated to work with the latest bevy. I also added Msaa::Off since that was interfering with the sprite edges.

use bevy::prelude::*;
use bevy::{color::palettes::css::YELLOW, text::FontSmoothing};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    let mut camera = Camera2dBundle::default();
    camera.msaa = Msaa::Off;
    commands.spawn(camera);

    commands.spawn(Text2dBundle {
        text: Text::from_section(
            "Ready!",
            TextStyle {
                font: asset_server.load("joystix.ttf"),
                font_size: 11.0,
                color: YELLOW.into(),
            },
        )
        .with_font_smoothing(FontSmoothing::None),
        ..default()
    });

    commands.spawn(SpriteBundle {
        texture: asset_server.load("ready.png"),
        transform: Transform::from_xyz(0.0, 10.0, 0.0),
        ..default()
    });
}

coreh avatar Sep 22 '24 17:09 coreh