Thanks for the very detailed explanations :) π
I don't have any bandwidth to take a look at this but this is a very interesting project for anyone wanting to contribute to GD.
4ian on 22 Feb 2020
If anyone can/wants to take a look at this:
I've started looking at the code snippet here: https://codepen.io/Tazy/pen/wJVExB?editors=0010
While I haven't used Javascript in years, I think the main gdjs function around "onGameResolutionResized" (I believe in GDJS.js?) would need to ensure it doesn't scale TextObject using it's normal method, and would instead use the listed function in the snippet around resizing the font. If not GDJS, it might need to be in RuntimeScene.js (specifically gdjs.RuntimeScene.prototype.onGameResolutionResized) and have it exclude TextObjects (or Treat objects differently).
I also believe you might need to disable all of the scaling functionality on the text object itself in the TextObject runtime (likely textruntimeobject.js, textruntimeobject-pixi-renderer.js), to ensure it's scale is always set to 1. This may not be necessary if the above is completed (and incase the user specifically uses scaling events on the object)
I think it would be pretty safe to say font 4px would be the smallest, and then the "BaseFontSize" would always be whatever the player selects as the font size in the editor. I wanted to test this method without any concern of editor functionality to see how it works...but I'm no where near good enough to know how to manipulate any of the functions listed above, or even know if I'm on to something, sadly.
Hopefully if someone does look into this, the above can help. If I'm understanding properly, solution 1 could potentially be applied to regular text objects AND bb text objects, and would (in theory) solve all font scaling...as they're no longer being scaled at all. Any other "blurriness" would be an issue with the font, and not GD5 or Pixi, since they're just rendering the font at the same size Windows would be.
Silver-Streak on 23 Feb 2020
Hello , I am an open source aspirer, trying to learn open source style of programming.
Is this the right place I am looking at : https://github.com/4ian/GDevelop/blob/master/GDJS/Runtime/runtimescene.js
in this file the "onGameResolutionResized" fuunction.
If yes, please help me in understanding what is _layers here.
deadpool1999 on 25 Feb 2020
I _think_ _layers is the call for returning the layer name. I'm not a dev though and could be 100% incorrect, so I'd wait for 4ian, Bouh, or another Contributor to confirm.
Silver-Streak on 25 Feb 2020
I'm not sure we have a precise solution here @deadpool1999. As the label "πββοΈCareful thinking/design or refactoring needed" indicates, there is probably some more complex underderstanding of how text work. I'm not actually sure there are even changes to do in onGameResolutionResized
. For _layers
, the name is pretty much saying it all, it's a variable containing layers. What's layers? You can find this in the documentation or searching a bit in the code :)
4ian on 25 Feb 2020
π1
@4ian So I don't think this is one of the items being covered by GSOC, correct? If not, is this something that you would feel eligible for me to throw another bounty on? If we'd rather wait until GSOC is over to see if any pulls it, I'm happy to wait on that too. π
I can delete this comment to avoid influencing people's decisions, as well.
Silver-Streak on 7 Mar 2020
This is not in the original project idea list, but could be a project if someone want to make a solid proposal for this.
I think though it would be worth a bounty as it's more an in depth investigation that is needed :)
4ian on 7 Mar 2020
π1
Thanks 4ian.
I have posted a bounty on this issue here: https://www.bountysource.com/issues/89023609-changing-resolution-makes-text-objects-blurry-or-distorted
My overall preference/requirements on this (although obviously I'm not the final say):
Preferred:
- Implement Potential Solution 1 above, disabling scaling for text and BBtext objects, instead automatically adjusting the font size up/down based off current resolution vs game default resolution
- Add a toggle to BBText and Text objects, or at the Game Properties level, to allow the game developer to turn this on or off (Nice to have. Would probably allow for this functionality to be applied to other Text objects if they're ever added in the future)
- In theory this may be the "cleanest" solution, both from a visual standpoint (no scaling ever done to text objects themselves, just rendering the font at a new size) and from a code standpoint (no external libraries).
- We'd probably want to set a minimum size of "2" or "4", just to be safe as part of the scaling.
Medium preference:
- Implement Potential Solution 3 above, adding either pixi-richtext (preferred) or pixi-sdf-font
- Pixi-richtext automatically converts fonts to SDF, and applies rich text formatting to them.
- Not as preferential to the other one listed above, as both libraries haven't been updated for over 6 month, they'd need to be maintained separately, and it is basically adding another object type, meaning users would not be able to apply this "fix" to existing games without recreating all of their text objects.
Less preference:
- Implement Potential Solution 4 above, adding a new bitmaptext object from the Pixijs system itself.
- Bitmap Text is used by other engines over the basic text object, for better scaling usage.
- This is less preferred because BitmapText may be a Pixijs v5 only format, and it would be a completely new object type, meaning users would not be able to apply this "fix" to existing games without recreating all of their text objects.
@4ian , not sure if you want to throw the Bounty tag on this issue, or if that tag is used on this repository or not. Thanks for your and @Bouh 's time on this over the past few weeks.
Silver-Streak on 10 Mar 2020
$70 USD on bounty source for this issue, @4ian bounty source tag can be added.
https://www.bountysource.com/issues/89023609-changing-resolution-makes-text-objects-blurry-or-distorted
Bouh on 13 Mar 2020
I got a e-mail about a mention that isn't here, so I'm assuming it was deleted, however it appears someone was asking about where the text runtime objects I mentioned are located.
They can be found here: https://github.com/4ian/GDevelop/tree/master/Extensions/TextObject
Hope this helps anyone looking into this.
Silver-Streak on 18 Mar 2020
π1
Okay, @Silver-Streak I didn't look into Extensions (and checked only GDJS/Runtime), so I thought TextObjects are treated as normal RuntimeObjects, sorry about that, my bad :) Anyway, I want to ask why do we scale TextObjects? I mean we could've changed their font size instead of scaling? Is there any special purpose for scaling the fonts?
Maybe we could have a function like these which sets the font size instead of setting scale? We are already passing the runtimeScene, which means we could get the resolution, and set the font size accordingly.
HarsimranVirk on 18 Mar 2020
@HarsimranVirk I'm not a contributor, and I think 4ian and Bouh/all of the contributors goal is for a careful solution to be put in place for this.
However, if you look at "Potential Solution 1" in the second or third post above, it provides a method to do exactly what you're mentioning. It looks at the "default" resolution for the game, your selected font size, then scales the font size up and down rather than the font itself. It's my personal preferred solution for this since it should avoid all scaling issues altogether for text.
Quoted for posterity:
Potential Solution 1: Do not scale Text objects, keep them at their native size but scale the font size based off the scaling size:
Thread that discusses it - https://www.html5gamedevs.com/topic/36463-pixijs-v4-does-not-remain-sprite-pixelated-as-it-original-is
Code example - https://codepen.io/Tazy/pen/wJVExB
Note: This seems like it might be the "prettiest" option, in that it should accommodate almost every font/text combination, I do not understand how difficult it would be to implement, however.
Silver-Streak on 18 Mar 2020
@Silver-Streak I've been checking on some functions related to resizing, and I strongly believe that the TextObject, or really any other object is not directly scaled at all. I have 2 reasons for that,
I'm not really familiar with the codebase, but if I had to implement the resizing, I wouldn't access each and every object present in the scene (or layer) and scale them up/down individually. This wouldn't be the most efficient way since there could be dozens of objects in a scene. Instead, I'd scale the entire scene or layer, which would result in indirect scaling of all the objects.
I couldn't find any code related to scaling individual objects, (it's possible that there is some code which I really couldn't find) but I found a lot of stuff scaling scenes and layers. I'd need to confirm this with @4ian and @Bouh, however.
I've tried to simplify what I'm trying to say, here, https://codepen.io/harsimran-singh-virk/pen/oNXydEb?editors=0010
I'm not sure if this is the real cause of the problem, but if it is, then a potential solution can be:
- TextObject is bound to scale if it's parent container is scaling, so if we could reverse it somehow, ie, if the parent container is scaling up, we could scale down the TextObject. This would effectively nullify the scaling.
- After the reverse-scaling, we can set the font-size accordingly.
I'm also not sure about how this could be implemented, would definitely require help from @4ian and @Bouh.
HarsimranVirk on 18 Mar 2020
@HarsimranVirk I believe you are correct. TextObject inherits the behavior from (_I think_) GDJS.js around a "onGameResolutionResized" function.
To implement this method I think there would likely need to be a change so it no longer inherits that scaling 1:1 and instead when onGameResolutionResized is called, TextObjects (and BBtextobjects) use this other font size scaling method, instead of just scaling the object itself.
I'll wait for 4ian and Bouh (or another contributor) to chime in, as I only know very basic JS and found the above from poking around, and it may be completely incorrect.
Silver-Streak on 18 Mar 2020
There is no special scaling applied to objects.
All game objects are rendered to a canvas, using the game resolution. The canvas is then stretched to fill the window/page, but not object individually.
This does not seem related to GDevelop. It would be interesting to reproduce the issue of a Pixi sample. Basically, render a text with a font, and put a sprite with some text using the same font and same size next to it.
Then, enlarge the canvas. Check if the text is blurred and differs from the sprite.
If not, then there must be something that we've wrongly done in GDevelop, or we've not properly applied the styles for resizing using nearest neighbours.
If there is a difference, then this should be probably a question for Pixi.js
4ian on 18 Mar 2020
π1
@4ian
Looking at https://codepen.io/Tazy/pen/wJVExB, it seems like they're applying this alternative scaling logic (or lackthereof) to Text objects using Pixi. If I understand correctly, they're basically creating a separate function that handles text scaling for the canvas, basically creating a separate instance of the GDJS "onGameResolutionResize" (or equivalent) that instead of scaling it just changes font size.
So I think you're correct: This is an issue stemming from applying scaling to the whole Pixi canvas (via pixi). However, it makes me think that maybe a general scaling for all items isn't the best way to do scaling? (or at least, breaking text out of that general scaling would solve this issue)
Again, I"m very much a layman, though π So I'm just trying to understand using what little JS I know.
Silver-Streak on 18 Mar 2020
I've bumped up the bounty on this and asked Bountysource to tweet about it in hopes of spurring more interest. https://www.bountysource.com/issues/89023609-changing-resolution-makes-text-objects-blurry-or-distorted π
Silver-Streak on 28 Mar 2020
@Quarkstar This issue is still present in your pixi v5 branch ?
Be sure to make good comparaisons between the versions v4/v5.
Bouh on 6 Apr 2020
This issue is still present in your pixi v5 branch ?
Be sure to make good comparaisons between the versions v4/v5.
Yes, it's still there. I think it looks the same in v4 and v5 branch.
Quarkstar on 6 Apr 2020
@Silver-Streak @4ian Nice discussion here; The first solution posted here is quite simple and should do the job. Are there any obstacles in implementing that solution?
If you want to scale text via font size (not by Pixi's internal scaling), you can create a PIXI.Container
wrapper around a PIXI.Text
. This wrapper would have a custom _render
method:
You can extract the "world" scale from the world transform - say
max(this.transform.worldTransform.a, this.transform.worldTransform.d)
.You set the font size of the internally wrapped Pixi text to
originalFontSize * worldScale
.You apply a downscale to the text's transform
text.scale.set(this / worldScale)
. This will make the "on-screen" size of the text same as before - but using a larger font size.
SukantPal on 14 Apr 2020
@SukantPal
Thank you greatly for chiming in.
While I'm definitely not one that would be able to implement it, could you clarify on the last step? I though the goal would be to avoid any scaling on the text at all. Wouldn't text.scale remain the original size but text font size be changed instead? What does downscaling the text's transform gain?
(This is more curiosity than anything else)
Silver-Streak on 14 Apr 2020
@Silver-Streak Option 1 wants to replace the βscaling factorβ with a larger font size. To nullify the βscaleβ, you need to apply the inverse of it. If you donβt, both the transform scaling and larger font size would be at work..
SukantPal on 14 Apr 2020
π1
Hmm, now I'm more confused. If we're removing any scaling from occurring on that object (Leaving text object scale at 100%), wouldn't the larger font size appear 'normal'/same size as before since it's only being displayed when the window resolution has increased/scaled up accordingly?
Silver-Streak on 14 Apr 2020
@Silver-Streak
Look at this: https://jsfiddle.net/ShukantPal/nwvmh1L2/. It shows the demo.
To see the text without my "font-size adjustment", change the name of the TextWrapper#render
method to something else (just add a letter to the front drender
). This will make the text blurry again.
SukantPal on 14 Apr 2020
π1
As it is another payperiod, I've bumped up the bounty on this again.
https://www.bountysource.com/issues/89023609-changing-resolution-makes-text-objects-blurry-or-distorted
Thanks to SukantPal for all of their input. I'm hoping said input makes it easier for someone to implement.
Silver-Streak on 15 Apr 2020
@Silver-Streak I'm actually ready to do this - I don't know how I'll test if it works locally. @4ian Any guidance to how you develop locally?
SukantPal on 15 Apr 2020
Start there: https://github.com/4ian/GDevelop/blob/master/newIDE/README.md :)
Then I recommend to try the project uploaded by Silver-Streak to reproduce the issue and see what you can do.
4ian on 15 Apr 2020
π1
The balise canvas is stretch in the html directly, so even if you rescale the container and increase the fontSize the result is still blurry.
Note you need change the style.padding too if you don't do this the text is crop on top.
Text is still blurry, i've rescale by x4 the fontSize and downscale to 0.25 the text container.
The font file used:
Silver.zip
Bouh on 15 Apr 2020
@Bouh Hmm, I see. I believe your proposed solution is something like this: https://stackoverflow.com/a/15666143/6805653.
Get the device's pixel ratio, and then
new PIXI.Renderer({ width: yourWidth * ratio, height: yourHeight * ratio, autoDensity: true});
SukantPal on 15 Apr 2020
Pixel ratio is still 1 for me. then it change nothing on my preview.
autoDensity is only on pixi v5 so i use the current branch of @Quarkstar for test.
If i understand correctly autoDensity allow to to pixi to resize the canvas size in CSS ?
But the canvas is already resize at the dimension of the window.
For me the issue in at the root when the pixiRenderer is define, instead use the size from the setting of the game we should use the value of the window.
Values of the game should the used only for set the size of the window.
Tell me if i've lost you in my explaination ^^.
So here my new result.
Bouh on 15 Apr 2020
@Bouh You did kind of lose me there. Here is what I think you said :) - you used somebody's branch that had upgraded GDevelop's Pixi dependency to v5. The window size was set to the game's resolution & the canvas size was set to the window's dimensions. You used resolution: 1
?
SukantPal on 15 Apr 2020
My pixel ratio is always 1, resolution too 1.
The game can have options for set width and height for configure the window of the game. 800x600 by default.
This value is used for configure the window (it's ok) and used at the rescale event of the window and used for redefine the pixiRenderer, but the value stay 800x600.
So the pixiRenderer comptue for a canvas of 800x600, and after the HTML canvas is rescale with CSS rules. If the quality of the renderer is smaller than the HTML canvas, it's logic for me know to have a poor quality result when we rescale the window is apply on the canvas.
(I try draw a cat on a paper A4, i wish my cat on a poster, if my quality is bad on my paper and rescale my image to poster dimension my beautiful draw loose in quality, it's better if a redraw my cat on the poster. I hope the analogy help ^^)
I try to understand how work this part of GD. But it's give me a good result with my technic.
I've open a PR here. See the last commit. And you can try my new build of GD
This work on current master branch under pixi v4.8.6, and it can work also for next branch under pixi v5.
It's only on Text object not yet on BBtext.
Bouh on 16 Apr 2020
I posted it in the PR, but to make sure it's not lost:
Bad news:
This seems to still have scaling issues rather than changing font size, unless I'm misunderstanding:
Here's text at native resolution 1920x1080, font size: 72
Here's the window resolution changed to 1280x720, font size still 72 according to debugger:
You can see it still becomes very distorted once I change the resolution.
(Also, this doesn't appear to fix blurriness on BBText, but I don't think we're trying for that currently)
Silver-Streak on 16 Apr 2020
Some more tests with this build:
Game set to 1920x1080 resolution.
Font: Gravity Pixel Font https://jotson.itch.io/gravity-pixel-font
Font Size: 30
At 1080p (Native game resolution, click for full size):
Window resized to 720p (click for full size):
You can see in the word "PRESS" there is a lot of distortion on the S characters.
However, if I change the game resolution to native 720p (2/3 of 1080p) and change the font size to 20 (2/3 of size 30)
No distortion on any character (click for full size):
Here's the project files:
FontResizeDistortion.zip
Silver-Streak on 16 Apr 2020
@Bouh and I have been talking through this on the discord, so I wanted to post these examples incase anyone else needs to see them, as the difference is noticeable but faint.
Here's 1080p native, zoomed in, with a 1x1 pixel grid.
Notice that the center of each S is the exact same size, ~4 pixels
Here's that same window resized to 720p:
Notice that the top S and bottom S are not equal, among other differences.
So it seems like the font size scaling down isn't working properly, at minimum.
@SukantPal Also, Bouh's knee deep in bug hunting for the recent releases, so if you do want to take a crack at this, any help is appreciated.
(Edit: To be clear, I mean if you want to take a crack at your own implementation, not necessarily what we're seeing with the build Bouh made. Or both. Honestly I'm just happy if we can get this solved. :D )
Silver-Streak on 17 Apr 2020
π1
Something is different between your screen and mine. Maybe the resolution or the pixel ratio like @SukantPal suggest. i guess it's why i can't see the difference with your screen. Because mine are different. I can't reproduce what you see, then i don't know how debug this, i'am very lost.
The electron menu made the mess, but because it's not present in exported game we should not take it in account.
This menu reduce the canvas and affect the CSS size, so i've remove this menu in my preview. For remove this damn electron menu you can just export your game or use my new build below.
I use your project with more information for debug.htmlCanvasSize, cssCanvasSize, pixiRendererSize, pixiRendererResolution, devicePixelRatio, pixelRatioSize, gameSettingsSize, isFullscreen
On my screen 1920x1080, 144hz, with my build with fix and b92, without electron menu in preview:
For the nΒ°4, if i resize to 1279x719, (1px below), the font is prefect!
We can see when the CSS canvas size have decimals, the font is distorted.
It's because electron menu is present and the window cannot be resized bigger than the screen resolution.
What you think, how it is for you ?
Bouh on 17 Apr 2020
Thanks Bouh. I'll check later today.
Silver-Streak on 17 Apr 2020
Hmm... I still get the electron menu in preview.
Also, after exporting the provided project using your build, this is what is shown after building it with electron-builder using yarn:
Is something going weird with how it's handling game resolution now?
Even hitting T again to set it to 1080p does this:
Silver-Streak on 17 Apr 2020
Is something going weird with how it's handling game resolution now?
The weird resolution with decimals? You are not in fullscreen so the canvas is reduce by your title bar.
Press F for set in fullscreen, and G for windowed.
It's a good news to see resolution to 1 everywhere.
Bouh on 17 Apr 2020
The build number is broken, but it's a custom build between b90 and b92 (it's a version similar to b92, but without the lastest commits about the profiler. I've just added the commit to fix electron.
This change nothing for us here.)
You are still not in fullscreen and you have the electron menu. Press F, not F11, F will remove the electron menu, F11 don't.
Bouh on 18 Apr 2020
Yep, I totally missed that. My apologies.
I'm now seeing significant improvement, although still some oddities.
Upscaling tests:
Game resolution 1280x720, font size 24, 720p:
Zoomed in:
Game resolution 1280x720, font size 24, full screen (1080p):
Zoomed in:
Note, on the zoomed in view, I only marked the pure white pixels. It seems like there's some very bizarre sub pixel rendering/color blending happening still, but it is CONSIDERABLY better than the production build.
Downscaling tests:
Game resolution 1920x1080 (1.5x 1280x720), font size 32 (1.5x 1280x720), full screen:
Zoomed in:
Game resolution 1920x1080, font size 32, window rescaled to 720p:
Zoomed in:
Not sure what would impact the color blending like that. I think the most interesting thing is that the 1080p 32 font size scaled to 720p does NOT have the same color blending/subpixel rendering that the 720p 24 font size does.
Silver-Streak on 18 Apr 2020
Yeah, still something weird. I did some digging, and this font is designed for font sizes that are multiples of 5, not 8.
Downscale test:
Game resolution 1080p, font size 30 full screen:
zoomed in:
Game resolution 1080p, font size 30, resized to 720p:
Zoomed in:
Notice that before resize, each S has a width of the line of 6 pixels. Since 720p is 2/3rds of 1080p, that _should_ mean after resize to 720p, each S should be 4 pixels wide (2/3rds of 6). It is instead 3 pixels wide, with 2 pixels on each side of color blending/subpixel rendering.
Upscale test:
Game resolution 720p, font size 20 (2/3rd 30):
Zoomed in:
(Note, 4 pixels wide on the sides, so already different than the scaled down one above)
Game resolution 720p, font size 20, full screened (scaled up to 1080p):
Zoomed in:
Notice that the upscaled one goes from 4 pixels wide to 6 pixels wide. It seems like upscaling is working how I would think it should, but downscaling is being weird?
Silver-Streak on 18 Apr 2020
Just wanted to throw some updates on this as I've been testing with various fonts and seeing some really weird behaviors. We already know Silver.ttf (https://poppyworks.itch.io/silver) runs into issues once scaled, even with these updates.
Even though this font is heavily used in game development, I wanted to test with some other monospaced pixel fonts, so I've tried Monogram here: https://datagoblin.itch.io/monogram and m6x11 (https://managore.itch.io/m6x11).
They also don't do well with downscaling, and the distortion is heavily noticeable. Unfortunately, going to 1279x719 doesn't fix it for any of the above fonts.
Upscaling, again, is fine.
Silver-Streak on 20 Apr 2020
The more I look for solutions, the problem gets worse.
Under PixiV5
The black rectangle should be the text, it's black becauseWebGL: INVALID_VALUE: texImage2D: width or height out of range
And it's normal because i change the fontSize x4, and the fontSize is 300. (300*4=1200) and i rescale the font to 0.25.
But this is just the size for one letter, so if you make a sentence, the renderer for the texture will be huge! (~letters is your sentence x 1200 ), my renderer is 50k of width. And the WebGL dont want a huge renderer to calculate like that, so upscaling the font isn't a good solution ?
My best result for now, 1920x1080 resize to 1280x720, font:30
Zoomed
Bouh on 22 Apr 2020
To be fair, font size 300 is already ridiculous. π
If you can, help me understand why are we rescaling the font size up then down? Wouldn't we just rescale the font size once per resolution?
(Game resolution 1080p, font size 30, game window resized to 720p (2/3rds 1080p), font size would then be scaled to 20 (2/3rds 720p)
Silver-Streak on 22 Apr 2020
Do we want to loop 4ian or SukantPal back in to see if we need to address this differently, or is this something where maybe it'd be beneficial to just have it as a toggle on game settings (Underneath the resolution settings) with a disclaimer "Very large font sizes such as 200+ may not render correctly"?
Silver-Streak on 23 Apr 2020
@SukantPal So @Bouh and I have been hammering away at this on the discord.
Unfortunately we can't seem to crack what the issue may be, the text distortion still happens one way or another. Do you still have time to take a crack at this?
Silver-Streak on 28 Apr 2020
@Silver-Streak
"Since 720p is 2/3rds of 1080p, that should mean after resize to 720p, each S should be 4 pixels wide (2/3rds of 6). It is instead 3 pixels wide, with 2 pixels on each side of color blending/subpixel rendering."
This only applies when the the leftmost pixel is at a multiple of 6px. I think the problem here is that the "S" is not at a multiple of 6px position, so when you scale down, the position of the first pixel is not a whole number. For example, if the position of the first pixel mod 6 is 1px (so 1, 7, 13 is the position of "S"), then the new position after scaling down has a .33 or .66 in it. Since the position of the "S" is not a integer (after scaling down), it the first & last pixels don't entirely overlap with the "S" (hence are blended).
Did you try to moving the position of PRESS by 1, 2, 3, 4, 5 px (so there must be a multiple of 6px position)? I think that might give some insight.
P.S. Are you using a screenshot and zooming in for those pixel-level images?
SukantPal on 28 Apr 2020
For your last question: Yes. screenshot, zoomed in, pixel count.
As for your other question around positioning,, we've tried applying a "draggable" behavior to the text object, and you can watch it distort/become normal again as you move it around the canvas, yes.
Although the above screenshots are mostly focused around the subpixel rendering, that is only part of the concern, and less of a concern than the actual distortion we see on fonts.
Here's an example that shows the distortion more clearly:
And it doesn't appear to be subpixel related as full pixels are being removed/added. This occurs more with more defined pixel fonts such as Monogram (https://datagoblin.itch.io/monogram) or Silver (https://poppyworks.itch.io/silver). Silver has been used in a ton of published games from other engines, and scale to different resolutions without issue.
The distortion we're seeing above _does not_ happen in the codepen example from "Solution 1" at the top of this post either, so we're thinking it has to do with something being applied to the scaling methods.
Edit: Also, shouldn't Pixel Rounding stop the partial pixels (.33/.66) from occurring? because it doesn't seem to be applied (or at least not after a downscale)
Silver-Streak on 28 Apr 2020
Edit: Also, shouldn't Pixel Rounding stop the partial pixels (.33/.66) from occurring? because it doesn't seem to be applied (or at least not after a downscale)
I wish add, even if these settings exist.
Bouh on 28 Apr 2020
@Silver-Streak "Edit: Also, shouldn't Pixel Rounding stop the partial pixels (.33/.66) from occurring? because it doesn't seem to be applied (or at least not after a downscale)"
You aren't scaling down the position of the text explicitly, rather scaling down the canvas gives it that new position on the screen. You can't round down. What you can do is probably shift the text to a multiple of 6px position.
SukantPal on 28 Apr 2020
@SukantPal @Bouh So I think this brings us back to the original idea, right? Removing Text Objects from being scaled down with the canvas, then just rescale their font size/position?
Silver-Streak on 29 Apr 2020
Yes. Iβm concerned whether @4ian would consider that. Instead of scaling down the canvas itself, you set the scale on βstageβ (root container of the scene graph). That scale would propagate down to each text object (and all other display-objects as well), and then the initial concept I showed in my fiddle would kick in (replacing the transformβs scale with a different font size).
SukantPal on 29 Apr 2020
@SukantPal Do you think that would have a performance hit at all?
If not, and it works, I wonder if the good middle ground is make that a toggle in the game project?
I'll defer to 4ian, though.
Silver-Streak on 29 Apr 2020
Hey all!
First I did not get to properly thank you @SukantPal for chiming in here and help on this issue, thanks a lot! π
I've more or less followed the discussion, can anyone confirm if these are true or not?
- The root of the issue comes from the fact that the canvas is scaled.
- By canvas being scaled, we mean this CSS styling:
- If you "shift the text to a multiple of 6px position", is the distortion still there when you scale down?
- Extra question: we won't ever be able to avoid distortion if the game is displayed at a size that is not a multiple of the original size?
- The solution "Instead of scaling down the canvas itself, you set the scale on βstageβ (root container of the scene graph)." is:
- We remove the CSS styling that is used to resize the canvas
- Instead, we set the scale on stage (the root container of the scene).
- Do we change the resizing of the pixi renderer itself?
- We change the renderer of the text object to use the solution of the fiddle of @SukantPal, which is adapting the font size to the scale.
- We do this probably only if the user checked "Dynamically adapt the rendering of the text size to keep a crisp text" (or something like this). And we document somewhere "internally, this update the font size of the rendered text to ensure it's the best size for the game resolution" and that it can have surely a small performance cost.
- Finally, just to come back to the first issue, can you remind me why a "dumb" scaling of the canvas is not working for texts, but seems to give good results for sprites (or bitmap texts)?
My final question can also be formulated: if we add an option to force the game scale to be only a multiple of the on-screen pixels, would that work?
(I know we have answered some of this, but it's a bit hard to follow everything, feel free to answer with links).
Thanks!!
4ian on 29 Apr 2020
@4ian I can at least answer this first one:
If you "shift the text to a multiple of 6px position", is the distortion still there when you scale down?
High level: The answer seems to be yes the distortion is still there, with a "sort of"
It doesn't seem like 6px does it, but moving it does remove some distortion
The "NewObject" text object in our example project starts at X 4, Y 999. If I resize to 720p, it distorts. (notice the S characters on "Press")
If I were to move it to X 6, Y 1002, both multiples of 6, it is still distorted
If I move it to X 7, Y 1006, (both not multiples of 6), it is LESS distorted, but still slightly (compare the "P" on both)
Silver-Streak on 29 Apr 2020
@4ian @Silver-Streak Okay, so regarding the CSS styling: there are two widths/heights of the canvas - CSS/on-screen & the actual "pixel buffer" size. The PixiJS renderer renders into the "pixel buffer". The browser then scales down that buffer to fit the on-screen size.
If initially both are 1920x1080px, then there is a one-to-one mapping between a buffered pixel and an on-screen pixel. Now, if the CSS dimensions go down to 1280x720px, then the one-to-one mapping is lost. Instead, it results in anti-aliasing effects because one on-screen pixel contains the information of 1080/720 = 1.5 "buffered" pixels.
The fix for this is to also scale down the whole scene graph and set the canvas (buffered) width/height to the desired resolution.
canvas.width = w;canvas.style.width = w;// we are already doing thisapp.stage.scale = w / original_width;
Regarding the "scaling down the stage": I am assuming that the positions/dimensions of the objects in the scene graph don't depend on the canvas width. If they do, they could be updated without scaling down the stage, i.e.
- You must scale down the stage if objects are positioned like this:
object.x = 100;object.width = 100;// ORconst initial_canvas_size = <something>;object.x = initial_canvas_size * .75;object.width = initial_canvas_size * .10;// doesn't update if canvas is resized
- If you're objects are positioned like this (e.g. you are using layouts managers), then you might not need scaling down.
stage.width = canvasWidthcanvasWidth.onChange(newCanvasWidth => stage.width = newCanvasWidth)object.x = parent.width / .5object.width = parent.width / .1
SukantPal on 29 Apr 2020
So just following up on this
@SukantPal : Assuming 4ian okays this method, are you thinking you can implement this?
@4ian : Are there any other concerns with this method?
(Feel free to tell me to buzz off if you're both still working this out π )
Silver-Streak on 4 May 2020
@Silver-Streak Sorry I dozed off this thread. https://github.com/pixijs/pixi.js/pull/6600 is getting finalized so BitmapText can be used by users without needing to provide a pre-rendered texture.
I won't be able to fix this issue until May 19 (I'm actually giving AP exams before passing out of 12th grade :))
SukantPal on 8 May 2020
@SukantPal No worries, thanks for the update. Good luck on exams!
I'm hopeful to see this get fixed in any way it can. I'm hopeful it can be fixed for the main text object and text scaling in general (especially since BBText is just as important)
While probably unrelated to this effort, I would note that The JSFiddlel example in your linked item for BitmapFont seems to cut off the top of some fonts at large sizes (and weird blurriness):
Silver.ttf (https://poppyworks.itch.io/silver) at 50 font size:
Windows:
Silver-Streak on 8 May 2020
@4ian : Are there any other concerns with this method?
I think @SukantPal has a better view than me about the right fix, I'm just concerned about the added complexity - I would be keen to have this solution but if we can encapsulate a maximum the fact that the font size is dynamically changed and avoid polluting too much the logic resizing the canvas (though if it's badly implemented now, a fix is welcome!).
Trying to avoid complexity spreading too much in the game engine :)
Now this being said, I'm seeing this BitmapText and that can be a nice solution - it's supported in most game engines and would definitely be helpful in GDevelop! :D
4ian on 8 May 2020
Thanks @4ian! I'm super excited to see the fix from @SukantPal.
(Also Bitmap Font will be an awesome thing to see in the future too)
Silver-Streak on 8 May 2020
@SukantPal Just checking in on this. Had any time to take a look yet?
(Also I hope exams went well.)
Silver-Streak on 23 May 2020
Hey all, as this seems to have lost a bit of steam, and it's a new payweek, I've bumped up the bounty on this again.
https://www.bountysource.com/issues/89023609-changing-resolution-makes-text-objects-blurry-or-distorted is now at $170, if you can take a crack at it @SukantPal π
Edit: looks like the bountysource owner has also chipped in on this due to the site problems they're having. So the bounty is now $190
Silver-Streak on 29 May 2020
π1
Look at this: https://jsfiddle.net/ShukantPal/nwvmh1L2/. It shows the demo.
To see the text without my "font-size adjustment", change the name of the TextWrapper#render method to something else (just add a letter to the front drender). This will make the text blurry again.
I adapted that to GDevelop: https://pastebin.com/ND5chttt
It doesn't changes anything about the issue, so the way to go seems indeed to change the way the canvas is resized.
I also tried to change this:
https://github.com/4ian/GDevelop/blob/0150e197b099daf8608b44aaa4db8cff187e3d4b/GDJS/Runtime/pixi-renderers/runtimegame-pixi-renderer.js#L136-L141
Into this:
this._pixiRenderer.view.style['top'] = this._marginTop + (maxHeight - canvasHeight) / 2 + 'px'; this._pixiRenderer.view.style['left'] = this._marginLeft + (maxWidth - canvasWidth) / 2 + 'px'; this._pixiRenderer.view.width = canvasWidth; this._pixiRenderer.view.height = canvasHeight; this._pixiRenderer.view.style.width = canvasWidth + 'px'; this._pixiRenderer.view.style.height = canvasHeight + 'px';
Like described here:
The fix for this is to also scale down the whole scene graph and set the canvas (buffered) width/height to the desired resolution.
canvas.width = w;canvas.style.width = w;// we are already doing this
Unfortunately this breaks cameras/layers and I am still in highschool, my maths level is too low to really understand how to fix that. I couldn't see if it fixed the blurry text tho.
arthuro555 on 10 Jun 2020
@SukantPal We've actually had a few people take a crack at this but can't figure out if it's a PixiJS scaling issue now or GD5 canvas issue. If you have any time soon to look at this it would be much appreciated.
Silver-Streak on 14 Jun 2020
As a side note, this bounty has been bumped up again and is currently $200. I'm seeing @SukantPal is deep in a bunch of PixiJS PRs right now, so I understand if they're not available to work on this and someone else wants to give it a try.
(Sukant if you are still intending to take a crack at it after you free up let us know here.)
Silver-Streak on 17 Jun 2020
π1
@Silver-Streak I checked out the sample project you gave. I set the game resolution to 200x150 and then scaled it full-screen on my 4K monitor:
The background appears to be blurry like the text.
SukantPal on 18 Jun 2020
@SukantPal I think that may just be that example project and the art/smoothing enabled. Here's an example project made from the first thing I created when learning GDevelop, image smoothing disabled on everything, and scaling set to nearest.
I've added some additional text objects to the title.
Silver-Streak on 18 Jun 2020
To @SukantPal and anyone else looking at this. Even though I bumped up the bounty on Bountysource, they are having system issues so the total isn't reflective. Current bounty on this is $200, and you can confirm that on bounty source by looking at the history.
Thanks for everyone's efforts on this.
Silver-Streak on 25 Jun 2020
β€1
Hmm...the more I read about Pixi 5.3, the more I want to check in on this.
@SukantPal Do you think this is an underlying issue with how Pixi.Text scales, or with how scaling is implemented in GDevelop?
If the former (Pixi.Text caused), do you feel GD5 would be better off implementing BitmapText/BitmapFont rather than trying to work around Pixi.Text scaling limitations?
If the latter (GDevelop caused), are you seeing anything particular with the way it uses PixiJS Scaling that could be improved in general, or is this path forward (scaling text separately) the best way to handle it?
If implementing BitmapFont Generation and the Bitmap Text enhancements from 5.3 is a better solution, I'm happy to update this issue/bounty to switch to that implementation rather than trying to fix an issue that exists with Pixi.Text in general.
Probably also looking for input from @4ian on this one as well, I suppose?
Silver-Streak on 27 Jun 2020
Do you think this is an underlying issue with how Pixi.Text scales, or with how scaling is implemented in GDevelop?
This is a good question, I'm not entirely sure too so any clarification is welcome :)
In both cases, I think a "Bitmap Text" object would be very interesting, because:
- if this issue of blurry text is not solved, it's a good workaround.
- if this issue of blurry text is solved, it's still useful for faster performance (provided you don't run into its limitations, like usage of CJK languages) and to be always 100% sure that you don't have weird scaling issues.
4ian on 27 Jun 2020
π1
@Silver-Streak I'm sorry I haven't been able to get time here. It's just that the treadmill is running faster than I can.
SukantPal on 27 Jun 2020
I see no differences with BitmapText : classic font and with Silver.ttf
The font have always an subpixel rendering.
Bouh on 27 Jun 2020
I see no differences with BitmapText : classic font and with Silver.ttf
The font have always an subpixel rendering.
Yes, I'm seeing the subpixel as well, however I am seeing a reduction in distortion when scaling up/down. Scaling up 1.5 and scaling down 0.75 used to heavily distort the E character, and I'm not seeing that here.
Silver-Streak on 27 Jun 2020
@Silver-Streak I'm sorry I haven't been able to get time here. It's just that the treadmill is running faster than I can.
No worries. Just to make sure I've got the right expectations (and that I'm not hounding you too much :smile: ): Are you still planning to take a crack at this?
Timelines aren't crucial, I just want to make sure I'm aligned with paths forward (and my hopes matching up with reality)
Silver-Streak on 30 Jun 2020
The bountysource issue has now been fixed, and this properly displays the $200 bounty on this. https://www.bountysource.com/issues/89023609-changing-resolution-makes-text-objects-blurry-or-distorted
Silver-Streak on 1 Jul 2020
I see no differences with BitmapText : classic font and with Silver.ttf
The font have always an subpixel rendering.
Taking another look at this, if I set the "antialias: false" instead of true in your jsfiddle, a lot of the subpixel rendering goes away for me. Could just be my tired eyes right now. π
Silver-Streak on 3 Jul 2020
Just to update @SukantPal and others on some additional testing for a workaround.
I had _hoped_ to work around this by starting at a much smaller resolution that has integer multiples that hit both 720p and 1080p, so native resolution 640x360 (2x for 720p, 3x for 1080p).
While doing this, I tested some new fonts to find ones that scaled effectively (monogram.ttf: https://datagoblin.itch.io/monogram, 1980 font: https://arcade.itch.io/1980).
I then applied the most common fix for blurry PixiJS fonts I could find, which was to just modify the text object to scale the fontsize by *5, then scale the text by 0.2.
At first I thought it was successful, only to do some test layouts and realize that when doing this, the font position gets broken. Here's the results:
Example scene exported with some Text objects (and a BBtext object, BBText has other issues in GD5 right now, so ignore that). Scaled up to fullscreen, so 1080p.
Text is very blurry/artifacty.
Here it is with the textruntimeobject-pixi-rendere.js in the exported folder updated, (line 37 updated to be style.fontSize = this._object._characterSize * 5; this._text.scale.x = 0.20; this._text.scale.y = 0.20;)
While the text is now clearer, it's very easy to see that the "PLACE:" line is now in a completely different location than before.
I attempted some other workarounds for this (namely, setting up an event that always repositions that text object to where it should be), but it doesn't correct this behavior.
I wonder if this could somehow be related to the same issue of the editor not displaying text objects at the same position as they appear in preview (https://github.com/4ian/GDevelop/issues/1419), but I'm not knowledgeable enough to be sure. Either way, this unfortunately means the workaround is unusable for at least my game.
Silver-Streak on 10 Jul 2020
π1
Right. I've been digging through the code. So far the issue seems to be pretty straight-forward - there is no way, or at least - no simple way to force canvas' fillText to sample it using different type of the algorithm other than whatever it is using for the implementation.
As you can see above - issue exists even on 1x scale of the text without any resolution changes, showing that it is indeed failure of horizontal-linear sampling.
Solution should be simple enough - as soon as you guys get to PIXI v5 - there needs to be an added BMText component with editor support of angelcode's BMText files. Pixi already does that natively, but resource servers need to be present also.
smoketh on 16 Jul 2020
π2
Thanks for posting this, @smoketh . Wanted to make sure @4ian could take a look at this path forward for any concerns as well as drive emphasis/importance on the move to 5.3.0 or newer.
Edit: and to be clear, the reason why the bottom text in Smoketh's image looks perfect is because it is a sprite object using an image I made in GIMP, not a Pixi/GD5 text object, showing that the scaling issues are isolated to text handling.
Silver-Streak on 16 Jul 2020
Yes I think the best solution for pixel perfect (and performant) texts will be to implement the "Bitmap Text" object, once we have Pixi v5 merged. Thanks for investigating @smoketh!
4ian on 16 Jul 2020
π4π1
Just for record here, PixiJS 5.3.0 has been merged to the master branch. Notifying @smoketh if they want to take a look at the new BitmapFont generation for the BitmapText objects.
Silver-Streak on 20 Jul 2020
@4ian just to confirm, were you saying you were intending to implement BitmapText/BitmapFont, or that it was a good path forward for @smoketh or someone to proceed with?
Silver-Streak on 26 Jul 2020
I don't have plan for it in the very short term (because I first need to land a new version with hot-reloading and Pixi v5, which is already a lot of changes :)), so anyone that want to give a try can go ahead. By copying the existing BBText extension as a starting point, I think it could be not too difficult:
- Copy https://github.com/4ian/GDevelop/tree/master/Extensions/BBText in a "BitmapText" extension.
- Modify
JsExtension.js
to remove BBText specific stuff. - Modify the
bbtextruntimeobject.js
(to rename it tobitmaptextruntimeobject.js
, also inJsExtension.js
). - Implement the Pixi renderer in
bitmaptextruntimeobject-pixi-renderer.js
. - ???
- Profit! ;)
Knowing that we can start with supporting just creation of a bitmap font from a loaded classic font (a "font resource" in GDevelop), then add support for bitmap fonts later.
4ian on 26 Jul 2020
π2
and for reference, assuming this actually fixes the pixel blur when scaling up (and hopefully the distortion when scaling down), implementing this would apply for the bounty I have out on it. (Although I'd love SDF scaling for non-pixel fonts too, any pixel font fix is my main priority right now)
Silver-Streak on 26 Jul 2020
@4ian @Bouh
I've been doing a ton of research and tinkering over the past week. I've written a proposal for a potential fix on this that I've confirmed works, but requires IDE changes.
This does not replace the effort Bouh has completed around Bitmap Font. Bitmap font itself will still bring a great many performance enhancements to text heavy games, but the more I dig the less it looks like it will fix the scaling issues.
I am content with leaving the existing bounty towards Bitmap Font, but I feel this GUI Layer option will actually fix the original intent of this issue/bounty.
I'm happy to post another bounty on it, but I didn't want to open a new issue/feature request on Github without you reviewing the examples/projects I included in the post. (Included project below for posterity)
GUI Layer Proposal Project.zip
Any/all input/feedback is greatly appreciated.
Edit: Additionally, since it seems like Bitmap Text is no longer going to fix blurry/distorted text for pixel perfect games, are we okay with me renaming this to "Implement "Bitmap Text" object to improve text rendering and performance" ? Since that seems like the most relevant beenfits of Bitmap Text now.
Silver-Streak on 24 Sep 2020
I've answered on the forum.
It's true that for now Bitmap Text is not solving the blurry fonts issue in "pixel art" games. I do think though that it could be a definitive solution if we implement the loading of a custom texture... but this might be for later.
4ian on 27 Sep 2020
ct.js also uses pixi and has multiple scaling options, maybe one of the could fix this problem?
Here is the source for their scaling method: https://github.com/ct-js/ct-js/blob/develop/app/data/ct.libs/fittoscreen/index.js
arthuro555 on 9 Nov 2020
Was this page helpful?
0 / 5 - 0 ratings