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

Enable crisp text rendering for pixel fonts #2572

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from

Conversation

DigiEggz
Copy link

@DigiEggz DigiEggz commented Jul 5, 2022

Pixel fonts render with artifacts around the edges of text for devices with high pixel ratios and also for Chromium-based browsers. This compiler flag forces a 3x pixel ratio, eliminating the ghosting effect on both sides of text. Fixes #2568, which has more information on the issue.

Metlmeta added 2 commits July 5, 2022 13:38
Pixel fonts render with artifacts around the edges of text for devices with high pixel ratios and also for Chromium-based browsers. This compiler flag forces a 3x pixel ratio, eliminating the ghosting effect on both sides of text. Fixes openfl#2568 , which has more information on the issue.
@joshtynjala
Copy link
Member

This doesn't feel like a good solution to me. It would be really helpful if you could provide some code/steps that will reliably reproduce this issue so that I (or one of the other contributors) can try to debug it too.

@barisyild
Copy link
Contributor

It's definitely not right to cover up instead of solving the problem.

@barisyild
Copy link
Contributor

@Metlmeta The fonts look pretty neat for me, if you send me a sample project, I can look for a way to solve the actual problem.

@DigiEggz
Copy link
Author

DigiEggz commented Jul 5, 2022

Sure thing! I've included a sample project. The problem stems from when trying to zoom on a low resolution project:

TextDemo.zip

sample

Note: Make sure to use a Windows Chromium browser (Chrome, Brave, etc.) when testing this problem. Results also vary depending on your screen ppi. macOS experiences a similar problem, but only with Retina displays. Let me know if you can't get the issue to appear.

Thank you for your time!

@joshtynjala
Copy link
Member

Thanks! I can reproduce on macOS Safari, Chrome, and Firefox.

@barisyild
Copy link
Contributor

barisyild commented Jul 5, 2022

I think this is flixel problem

also isTextBlurry function name is quite interesting

image

@barisyild
Copy link
Contributor

barisyild commented Jul 5, 2022

I think the cause of the problem is:

flixel draws the textfield as it should be and converts it to a bitmapdata.

As FlxGame scales, it also scales the textfield bitmapdata with itself and degrades the quality.

@barisyild
Copy link
Contributor

Possible Solution: To prevent flxgame scaling, keeping the FlxGame size the same as the canvas size.

@joshtynjala
Copy link
Member

I see that BitmapData.draw() creates a new CanvasRenderer, and it currently does not change the renderer's __pixelRatio value. This could be a clue about what's going on.

@DigiEggz
Copy link
Author

DigiEggz commented Jul 5, 2022

Possible Solution: To prevent flxgame scaling, keeping the FlxGame size the same as the canvas size.

There's still a problem when the resolution is set 1:1. It's smaller in this case, but you can still see a blurring problem going on:
20220705_170827

Setting a CSS image-rendering property of pixelated shows the artifacts more clearly:
20220705_170846

I see that BitmapData.draw() creates a new CanvasRenderer, and it currently does not change the renderer's __pixelRatio value. This could be a clue about what's going on.

That's an interesting point. When I was sifting through that code, I noticed that the FlxText TextFields were never passed the Stage's pixelRatio, presumably because they never use code that passes the renderer.

What threw me through a loop is that even when I manually set a pixelRatio of 2, there is still a blur on one side. Only when I manually set a minimum value of 3 would the pixel fonts render without blurring on either side.

All of this all only applies to the HTML5 canvas renderer - all other rendering is flawless for pixel fonts for Cairo without any special code or changes. Please let me know if you'd like me to test anything; I'd be happy to give any suggestion a shot.

@joshtynjala
Copy link
Member

I see that BitmapData.draw() creates a new CanvasRenderer, and it currently does not change the renderer's __pixelRatio value. This could be a clue about what's going on.

I'm leaning towards this not being a clue about anything — meaning that it's actually the correct behavior. I realized that BitmapData is supposed to always draw display objects at pixelRatio of 1 because it is raw pixels. So that seems to be the correct behavior not to set __pixelRatio on the renderer that BitmapData.draw() creates.

I'm now leaning toward something else being rendered/drawn incorrectly inside the canvas renderer (but probably not the cairo renderer, since that doesn't show the same blurring). Maybe something is being drawn to BitmapData with smoothing enabled when it shouldn't be, or it's being drawn on a fractional pixel when it should be snapping to the nearest integer pixel. It could be that the TextField itself is drawn/rendered correctly, but an intermediate BitmapData or CanvasRenderingContext2D that the TextField is drawn to first, before being merged with other display objects, is what doesn't get drawn correctly.

It's still a bit tricky to debug because Flixel is involved, which adds complexity over OpenfL. Especially since I don't know the Flixel internals well (other than knowing that it ends up drawing pretty much everything to BitmapData).

@DigiEggz
Copy link
Author

DigiEggz commented Jul 6, 2022

I first noticed this problem on a macOS Retina display. The text looked slightly muddy, whereas it looked perfectly clean on a non-Retina display Mac (in both Firefox and Chrome).

A friend sent me a screenshot of his game client (on Windows) and I noticed the text looked even worse - even more so than on the Retina screen. It was especially confusing because he had the same pixel ratio as me. Instead of having a slight haze, there was heavy blurring on both sides of the text. When I tested on Windows, I realized I could reproduce the blurry text, but only on Chrome.

Is there a reason why the text looks perfectly clear on Windows Firefox with a pixel ratio of 1, but not in Chrome? I'm worried it's some sort of browser rendering engine disparity.

Edit: I noticed that in the "1 to 2 pixel ratio demo" of this post, the author does something similar where they multiply by 3 to get non-blurry text. Not sure if it applies to this issue or not, but I found the problem similar to the one faced here.

Edit 2: This Stack Overflow question looks to be highly related.

@joshtynjala
Copy link
Member

Edit 2: This Stack Overflow question looks to be highly related.

It sure does. Unfortunately, the new canvas properties that address the issue don't seem to be fully supported yet.

@DigiEggz
Copy link
Author

DigiEggz commented Jul 6, 2022

At this point I don't think it's a fault with OpenFL. HTML5 canvas wants to anti-alias anything other than graphics and it depends on the browser to decide how to render the text: https://stackoverflow.com/questions/47139528/html5-canvas-text-anti-aliases-in-chrome-not-in-firefox

Users would either have to use a different rendering system for text or OpenFL could expose a new TextField variable (something like pixelFont?) that forces a pixelRatio of 3 for that specific TextField variable when set. Alternatively, all CanvasTextFields could have a default of 3 for their pixelRatio instead of the default of 1.

In all of the tests I ran, the only way I could get all browsers and high pixel density screens to render correctly was by scaling by 3. When I tested the "geometricPrecision" variable in Chrome, it still didn't get rid of the aliasing.

Please let me know your thoughts and what we could do to circumvent the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HTML5 text artifacts for pixel fonts
3 participants