Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quality of Text and bitmapText #6884

Closed
Bouh opened this issue Sep 15, 2020 · 19 comments
Closed

Quality of Text and bitmapText #6884

Bouh opened this issue Sep 15, 2020 · 19 comments
Labels
👍 Not A Bug Verified issue and is working as intended. Stale Previously “Won’t Fix”, bots should tag with this for inactive issues or pull-requests.

Comments

@Bouh
Copy link
Contributor

Bouh commented Sep 15, 2020

Expected Behavior

Text and BitmapText should be visually equal to a Sprite with the same text and same styles.

Current Behavior

The bitmapText and Text are not equal, and not equal to an Sprite with the same text and style.

  • Black: The image from photoshop with the same default settings found in PIXI.TextStyle ( except font size, see the settings bellow)
  • Red : BitmapText using bitmapFont
  • White: Text

image

image

Steps to Reproduce

https://jsfiddle.net/Bouh/avogx4n1/2/

Environment

@bigtimebuddy
Copy link
Member

BitmapFont.from does not support kerning where Text does. This is a known limitation of using BitmapText & BitmapFont.from.

@bigtimebuddy bigtimebuddy added the 👍 Not A Bug Verified issue and is working as intended. label Sep 15, 2020
@Bouh
Copy link
Contributor Author

Bouh commented Sep 15, 2020

Ok for kerning on x-axis.
What about the lineHeight or the visible offset on y-axis?

@bigtimebuddy
Copy link
Member

BitmapText and Text use different layout methods and are not expected to perfectly line-up in the way you demonstrate. Photoshop also uses a different rasterizing method, so this is not a given.

@Silver-Streak
Copy link

@bigtimebuddy Just to confirm, using bitmap font to generate a bitmap text object at 16 px, then scaling up, it looks like this:
image

But an image made in an editor, then loaded as a texture/sprite, with the exact same font size (16 px) and scaling, looks like this:
image

The Bitmap text is much blurrier than the png loaded as a sprite.

Is that expected behavior?

@bigtimebuddy
Copy link
Member

Can you please provide an example that we can look at rather than just screenshots?

@Silver-Streak
Copy link

Silver-Streak commented Sep 16, 2020

@Bouh Would you be able to provide your example builds with the example project I had?

I'm not sure if this will be helpful to the team here otherwise.

Here's my exported code, though.

app.zip

Here's the source PNG File being used.
GimpImage

(Transparent background, so you might need to click the space above if it looks empty)

@Silver-Streak
Copy link

Silver-Streak commented Sep 16, 2020

Sorry, this is where we get a bit past my personal knowledge. @Bouh if you could pull that info out, it'd be greatly appreciated.

@Bouh
Copy link
Contributor Author

Bouh commented Sep 17, 2020

I have been searching for the origin of this problem for months, I have no conclusions to draw from the research I have been able to do unfortunately :/

I don't even know if it's because of PIXI or GDevelop.

Providing a codesandbox environment that replicates GDevelop is too complex for me.
The trick is that this blurring effect is that on text, the sprites are correct, and there is no difference in the implementation of rendering with objects in GDevelop.

I would understand that since it is not proven that this problem affects PIXI, you won't want to get more involved than that.

I can't tell which element is wrong, I would isolate the problem or understand it I would be happy to provide a test link, but i can't.

I call on others with more knowledge to provide their point of view.

(However this issue was for the visual different result of text, now we're wandering on another one, it's a bit off topic.)

(Thx @bigtimebuddy for the current PR of improvement on kerning! )

@Silver-Streak
Copy link

@4ian Do you know if you'd be able to point out the code generation needed to show the differences between the objects from the export (or any export from the test build)?

Bouh and I are both a bit past our element.

@4ian
Copy link

4ian commented Sep 17, 2020

The way we use Pixi.js in GDevelop has nothing special by itself, so if there is this issue of blurry bitmap font, we should be able to make a JS fiddle with Pixi where we demonstrate the issue :)
@Bouh: let's make a simple example with Pixi.js where we use PIXI.BitmapText, with the same font as the one you used in your example @Silver-Streak
Starting from this, we'll investigate why the font is not blurry in the JS Fiddle and why it's blurry in GDevelop: does it happen when resizing the canvas? Is there some CSS styling on the canvas? Is there a resolution parameter somewhere when we initialize the renderer? Is the way the font is loaded different, etc...

If you can start making a JSFiddle/Codepen with a bitmaptext, using the same font, font size, this can help me then adapting it until we find why it's getting blurry. (In the meantime we can either close this issue as we don't have a proven bug with a reproduction case, but we can continue the discussion here).

@themoonrat
Copy link
Collaborator

Tried using roundPixels on the bitmap text object?

@Bouh
Copy link
Contributor Author

Bouh commented Sep 17, 2020

Tried using roundPixels on the bitmap text object?

Yes already tried :)

Here a JSFiddle with the basic stuff, bitmapText and the font used by silver.
There is also some functions for resize the canvas.

@bigtimebuddy
Copy link
Member

If you're scaling with a pixel-looking font, we should probably add a scaleMode option for the BaseTextures so you can set it to nearest instead of linear.

@Bouh
Copy link
Contributor Author

Bouh commented Sep 17, 2020

I have in the past tested these settings with max and low value, there is no influence on the blur.

PIXI.settings.ROUND_PIXELS
PIXI.settings.SCALE_MODE
PIXI.settings.PRECISION_FRAGMENT
PIXI.settings.MIPMAP_TEXTURES
PIXI.settings.ANISOTROPIC_LEVEL

Updated JSFiddle with scaleMode

EDIT: Here a new sandbox with blurry text in some case almost similar to GD.
The code sandbox.
The result in live fullscreen

@bigtimebuddy
Copy link
Member

That example is complicated, let's simplify it more without Pixi:
https://jsfiddle.net/bigtimebuddy/sc8pgL07/

Inherently, rendering text on canvas without antialias & fillText is not possible (unless someone figured this out). If you need a pixel-looking font, you should probably use a bitmap-font generation tool (e.g. bmGlyph) which probably has more options or there are some approaches where you scale render it at a large size and scale down.

Related: https://www.html5gamedevs.com/topic/23136-how-to-disable-font-antialiasing/

The best I could do it by picking the right sizes plus nearest scaleMode. But it's not perfect.
https://jsfiddle.net/bigtimebuddy/wmkxsgcq/

Screen Shot 2020-09-17 at 10 18 12 AM

@stale
Copy link

stale bot commented Dec 19, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the Stale Previously “Won’t Fix”, bots should tag with this for inactive issues or pull-requests. label Dec 19, 2020
@stale stale bot closed this as completed Jan 10, 2021
@darabos
Copy link

darabos commented Oct 12, 2021

I hit this issue and came up with an awful solution. I extract the font texture to a buffer, clip the values, and put it back in the BitmapFont.

Before After
before after
// Make the font.
const f = PIXI.BitmapFont.from('RulerGold', { ... });
// Get the pixels.
const t1 = f.pageTextures[0];
const rt = app.renderer.generateTexture(new PIXI.Sprite(t1));
let data = app.renderer.plugins.extract.pixels(rt);
// Apply thresholds. 200 for colors, 100 for alpha.
data = data.map((x, i) => x < (i % 4 === 3 ? 100 : 200) ? 0 : 255);
// Put the result back into the font.
const t2 = PIXI.BaseTexture.fromBuffer(data, t1.width, t1.height);
f.pageTextures[0].baseTexture = t2;
for (const k in f.chars) {
  f.chars[k].texture.baseTexture = t2;
}

If you have a PIXI.settings.RESOLUTION > 1, set it to 1 before this snippet and back to your resolution after.

@martinsik
Copy link

@darabos Thanks, it works great! (but wtf?)

@kxcrl
Copy link

kxcrl commented Jun 8, 2024

@darabos Ran into the same problem years later, unfortunately.

Most of what you shared is deprecated after v7, so I tried converting it to v8:

  // Make the font.
  const f = BitmapFontManager.install({
    name: 'MyFont', 
    style: {
      fontSize: 12
    }
  });

  // Get the pixels.
  const t1 = f.pages[0].texture;
  const rt = new Sprite(t1);
  let data = app.renderer.extract.pixels(rt);

  // Apply thresholds. 200 for colors, 100 for alpha.
  data = data.pixels.map((x, i) => x < (i % 4 === 3 ? 100 : 200) ? 0 : 255);

  const t2 = Texture.from({
    resource: data,
    width: t1.width,
    height: t1.height
  });

  f.pages[0].texture.source = t2.source;
  for (const k in f.chars) {
    if (k === " ") { return };
    f.chars[k].texture.source = t2.source;
  };

Doesn't work in the current state, unfortunately, but maybe if someone else needs this, it'll point them in the right direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
👍 Not A Bug Verified issue and is working as intended. Stale Previously “Won’t Fix”, bots should tag with this for inactive issues or pull-requests.
Projects
None yet
Development

No branches or pull requests

8 participants