Improve HighDPI Support (especially for BABYLON.GUI)

Just getting back into Babylon.js development, and I started playing around with BABYLON.GUI. My initial investigations left me with some mixed feelings; I love that it exists, and it’s not nearly as terrible as some of the videogame GUI libs I’ve used in the past. (Unpopular opinion: Crazy Eddie’s GUI, aka CEGUI was terrible.)

For me, the immediate thing I noticed that just seemed plain weird was that it looked rather low-res:

What I didn’t notice at the time (thank you anti-aliasing) was that the rendered sphere is also low-res. See, I’m developing on a MacBook Pro, so I’ve got a nice hdpi (“retina”) screen. These days 95% of the stuff I encounter supports hdpi, so it took me a second to realize what I was actually seeing.

Admittedly, I spent a couple of hours fighting with the AdvancedDynamicTexture to try and overscale and then scale back down, and nothing I did looked right at all. It wasn’t until I realized the entire canvas wasn’t rendering at hdpi that I started stumbling in the right direction.

Here is the final “working” version:

There’s a couple of issues here that I think should turn into Feature Requests and/or bugs.

engine.setHardwareScalingLevel(1 / window.devicePixelRatio);

This is required to get hdpi rendering from Babylon, but I only cobbled it together with a lot of google searching. Oddly enough, the docs say:

By default, Babylon.js will adapt to device ratio in order to produce the best possible quality even on high-DPI devices. (Source: Optimize your scene - Babylon.js Documentation)

That just doesn’t seem to be happening, either locally for me, or on the playground? Regardless, I feel like the docs could use a bit more discussion, since the only forum post I could find talking about enabling hdpi was this one: How to make Babylon GUI look "sharper" on mobile (high dpi) devices - Questions & Answers - HTML5 Game Devs Forum

Clearly, things have changed since then. :wink:

button1.cornerRadius = 12 * dpr * dpr;

So, this caught me off guard. Initially I expected everything to scale down when I changed the rendering scale, but thankfully Babylon has a solution that’s pretty well documented, gui.idealWidth/gui.idealHeight. I set idealWidth to the canvas’s bounding rect’s width, and almost everything worked.

What was broken was cornerRadius and thickness. Ok, cool, multiply by dpr, then? Nope. It’s dpr^2. I have no idea why. (I need to investigate device pixel ratios other than 2x, it might be that it’s just a straight x4, or dpr * 2 that’s required and I wouldn’t know.)

So, basically, is there a reason why these values don’t scale with idealWidth, while positioning and text size do? If so, can we make it more clear?


I mean, now that I’ve figured out the secret sauce to get it working, it works great. And I do get that not everyone wants hdpi turned on; but I think we should default to it all working out of the box, and just give users the ability to turn it off. (Which the docs seems to indicate is the intention; as long as it all worked, I would be happy with the method mentioned in the docs.)

Hey there, I stumbled on this issue myself a couple of days ago, BJS does try to adapt to device ratio indeed. However, if you call the engine.setHardwareScalingLevel() you are overriding it. I was calling engine.setHardwareScalingLevel(1) and it forced the canvas in low-res. Removing it fixed the issue for me.

See, I wasn’t. I literally just started with the basic getting started scene, which doesn’t call setHardwareScalingLevel. Out of curiosity, do you get the right dpi in the playground? (I don’t.)

Have not tested the playground. I have been testing my game with a pretty high res tablet and it seems pretty high dpi to me. Just in case, you could add the value true in engine initialization which basically tells the engine to adapt to device ratio. Probably it is off by default and the docs are not updated.

Yeah, I also did that, too. :thinking:

I just tried on my OnePlus 6, and the playground exhibits the same low-res vs high-res behavior. (To be clear, it’s the most noticeable with the text and curve on the button in my example.)

Since my project is in electron, I can’t try it on my phone, and that’s the only other hdpi device I have access to atm. I’ll get it setup with a normal webserver later tonight and see how it fairs.

In either event, the GUI elements (border/thickness) still have to be multiplied by the square of the dpr to match… that seems like a bug to me.

To toggle back/forth just comment out the setHardwareScalingLevel line and rerun.

Yup we changed the default behavior as lots of ppl were complaining about the mobile perf. I will update the doc ASAP.

Regarding GUI, let me add @Deltakosh to the thread as he might have more insights about it.

@sebavan That’s a tough one, since you’d think you’d want the better quality by default, but I do get that my use case of doing desktop games, not mobile isn’t the 90th percentile of use cases. :smile: So, as long as the docs call out what needs to be done I totally support prioritizing performance over visual quality.

I double checked, and I messed up the parameter order, so passing in true for adaptToDeviceRatio does seems to work identically to my setHardwareScaling hack. (So there’s still issues with border and thickness in the GUI.) But, at least now the docs will make it clear how to make this work!

Would it be worth putting a node in the GUI docs, as well? It might not be obvious to everyone that the reason the text rendering “looks bad” might be because of the device pixel ratio. It wasn’t to me, initially, at least. :sweat_smile:

Can’t agree more! Do you want to update the doc?

Absolutely! Mostly wanted to make sure there was buy-in before I looked into it. I’ll go read the docs on contributing to the docs (I love that that’s a thing. :joy:) and make my way through that this week. (Won’t be today, more than likely.)

1 Like

Thanks a ton!

Sorry that took so long, I had an unexpected work trip, and only just got back to this.

For those who want to follow along:

@Deltakosh Should I also follow up with bugs about adaptToDeviceRatio, idealWidth and cornerRadius/thickness? (Also, maybe a suggestion about exposing adaptToDeviceRatio in the playground ui?)

1 Like