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

GWT: New config setting to use native resolution on mobile / Retina / HDPI screens #5691

Merged
merged 10 commits into from Aug 29, 2020

Conversation

MrStahlfelge
Copy link
Member

@MrStahlfelge MrStahlfelge commented Jun 28, 2019

Mobile devices have very high resolutions nowadays. For websites not getting to small, there is a virtual resolution the devices have: CSS pixels. This resolution is very low and games can look blurry.

First approach to get this solved was 9dae9f8. This approach was to set the scaling of the website the game is presented on. This does only work for standalone websites. If the game is presented in an iframe, or in fullscreen mode, it was still using the low CSS pixel resolution. This is mostly the case when GameJolt or Itch are used.

This image shows a libGDX game in fullscreen mode on a 1080 x 1920px screen
Low res

This commit changes the backend itself to use the native resolution (better: the reported native resolution) if GwtApplicationConfiguration.usePhysicalPixels is set to true and removes the old approach.

High res

If it is set to false nothing changes.

For mobile devices, I would recommend to set the flag in most cases. See this imgur album how the flag changes the appearance for a fixed-size or a resizable game in windowed mode and in fullscreen mode:
https://imgur.com/a/D21tqY5

There's one case in which setting to false makes sense, that's why I made this configurable. Fixed size games may become too small when using the native resolution instead the CSS pixels.
Small fixed size game

For Desktops, setting the flag mostly makes no difference. On Retina or HDPI displays setting usePhysicalPixels to false might make sense, too, otherwise you are dealing with very high resolutions. You can set the flag for mobiles only by using
usePhysicalPixels = GwtApplication.isMobileDevice()

For those wanting to try or to use this in existing >games: you can find Jitpack dependencies to use with libGDX 1.9.8 (working with 1.9.9, too), 1.9.10 and 1.9.11 here.

@MrStahlfelge MrStahlfelge changed the title GWT: Fixed density problems on mobile with new config setting GWT: New config setting to use native resolution on mobile / Retina / HDPI screens Jun 28, 2019
@intrigus
Copy link
Contributor

Have a look at https://www.quirksmode.org/m/tests/widthtest.html
Maybe this is no problem, but window.devicePixelRatio changes on zoom.

@MrStahlfelge
Copy link
Member Author

No problem, but a good helper to test this on Desktop. ;)

Go to https://www.golfgl.de/lightblocks/play/ which is compiled without this PR and hit Ctrl-+ multiple times -> devicePixelRatio goes up, the game gets pixelated
With this change and usePhysicalPixels set to true, the game stays sharp.

@MrStahlfelge MrStahlfelge added bug gwt non-breaking w/ config Label for PRs that are non-breaking when configuration or game project is changed labels Aug 28, 2020
Copy link
Member

@SimonIT SimonIT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great addition which works very well. Even our test list looks sharp now! (On my screen with 2560x1440 resolution)
image
I tested it on Google Chrome (Android and Windows), Firefox (Android and Windows) and Edge (Windows)

@MrStahlfelge
Copy link
Member Author

Will clean the conflicts, add changes/wiki article and merge to master later.

Copy link
Member

@crykn crykn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just tested it as well on a mobile phone and with a Retina screen. Works well!

@MrStahlfelge MrStahlfelge merged commit cca4726 into libgdx:master Aug 29, 2020
@MrStahlfelge MrStahlfelge deleted the gwt_hdpi branch August 29, 2020 20:16
@Darkyenus
Copy link
Contributor

It would be nice if this worked with Graphics.getWidth/getBackBufferWidth APIs, as logical pixels and physical pixels are fairly important in scaling of UIs properly.

@MrStahlfelge
Copy link
Member Author

At the moment, it reports the physical pixels as getWidth/getHeight. This change mainly targets mobiles, and this way GWT backend reports the same sizes as Android/RoboVM backends do.

I will check if your suggestion improves the mentioned drawback regarding fixed size games while keeping compatiblity with mobiles!

@Darkyenus
Copy link
Contributor

Just for context: #3709 changes RoboVM to work properly with getWidth/getBackBufferWidth and LWJGL3 already uses it.

@MrStahlfelge
Copy link
Member Author

Thanks. I saw it before and tagged it. If you can, you could help me by giving an example repo on which I can reproduce the differences and why it is bether to not use getWidth, but getBackBufferWidth on iOS and GWT. As I said, at the moment I only see the advantage for fixed width games on GWT. No one should ever have fixed width on iOS, so I don't know what would help this with.
Thanks in advance!

@Darkyenus
Copy link
Contributor

I don't have a repo to show, but I think that there might be a conceptual misunderstanding.

General concept

Feel free to skip this, if you are familiar with it
In the past, when all pixels were the same size, there was no difference between Width and BackBufferWidth. Then high density screens came (Retina, in Apple speak), which had twice (3x, 2.5x, 0.75x, etc.) the pixels, but they were not physically bigger, so the UI elements occupied 2x as many pixels. Because dealing with scales and multipliers everywhere would be ineffective, a new concept was created - logical pixels (or points, in Apple speak). These logical pixels do not have fixed physical size nor they correspond to some fixed amount of real pixels, but a button on a desktop computer will always be, for example, 50 points high. (Buttons on mobile are generally larger, but even there, the buttons are always, for example, 80 points high.) How many pixels that is, is completely orthogonal to that and more pixels = crisper look, but not bigger button. This way it does not matter how expensive your screen is (=what is the pixel density), the button will always have the same size.

The logical pixels/points do vary in size slightly, but their size will be generally the same across one class of devices. For example points on laptop screen will be smaller than on a widescreen monitor (or a TV), but larger than on a mobile. This is to compensate the viewing distance. (So the logical pixel will always occupy more or less the same angle of the field of view.)

Another use of different pixel to point ratios is accessibility - changing DPI/scaling on Windows affects how large logical pixels are, and since things have fixed size in points, it affects their actual size in centimetres on screen. But it does not change the resolution at which the frame is drawn at, so the extra pixels are used for larger, but smoother text (for example).

What does it have to do with libGDX

This isn't about fixed size layout (bad), but about fixed size of UI elements (normal and good). As to why you would use getWidth over getBackBufferWidth (regardless of the backend): getWidth is for UI layout. getBackBufferWidth is for rendering that layout at native resolution. This is very important for fonts (which look terrible when not rendered with knowledge of the size of physical pixels), and also for more complex UI background images. This is essentially the reason why Android and iOS requires you to provide your images in multiple sizes.

TL;DR

getWidth gives you info about how much space for UI elements you have, getBackBufferWidth gives you info about how many physical pixels you have to fill with those elements. Having only getWidth results in properly sized UI (not too tiny on high density displays or too large on low density displays), but everything (text) is blurry. With only getBackBufferWidth the opposite happens. Therefore, both must be correct for UI that does not look out of place.

Added bonus for web: If this gets implemented correctly, scaling the web page in browser will scale the UI of your game, while keeping the visual fidelity, for free!

Copy link
Member

@tommyettinger tommyettinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was asked to review, but I have none of the experience with DPI scaling I would need to evaluate whether this commit is good or not. But it was merged, so hooray!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug gwt non-breaking w/ config Label for PRs that are non-breaking when configuration or game project is changed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants