Search Unity

Unity, WebGL and HiDPI screens

Discussion in 'Web' started by alix-fumoleau, Sep 7, 2016.

  1. alix-fumoleau

    alix-fumoleau

    Joined:
    Aug 1, 2016
    Posts:
    2
    Hi, I'm currently developing an app targeting WebGL with Unity 5.4.
    On HiDPI screens such as the retina screen of the Macbook Pro, the texts look a bit blurry which I believe, is due to the webgl canvas content being upscaled to fit the actual pixels of the screen.

    A lot of the answers I found while searching about canvas and webgl (not specifically Unity) mentionned setting the width and height attribute to different values than the style properties on the canvas element.
    For example :
    Code (JavaScript):
    1. var c = document.querySelector("canvas");
    2. var w = c.width;
    3. var h = c.height;
    4. c.width = w * devicePixelRatio; // devicePixelRatio = 2.0 on a retina screen
    5. c.height = h * devicePixelRatio;
    6. c.style.width = w + "px";
    7. c.style.height = h + "px";
    This works well on simple js apps. However with Unity, I'm under the impression that resizing the canvas by any way (width attribute or style.width property) trigger a resize event for Unity and eventually reset the width attribute of the canvas to its own value.
    I've also tried to use style="transform:scale(0.5)" on the canvas, which works well and look exactly as I want it but then the mouse position in Unity is not correct anymore and fixing this seems even harder.

    So, is there a way to tell Unity to make a render of W*H in a canvas of size (W/2)*(H/2) ?

    Thank you !
     
  2. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,666
    While you might be able to hack it somehow (as you have already tried), this is not currently supported in WebGL. I'm sure we will add support in the future, though probably not before our standalone builds actually support this, so that we won't end up adding WebGL-specific APIs for this.
     
  3. alix-fumoleau

    alix-fumoleau

    Joined:
    Aug 1, 2016
    Posts:
    2
    Hey there !

    I managed to hack it by using the css transform scale and editing the input coordinates. This implies to modify the big js file built by unity and as such, is very unlikely to work with future versions of unity. I'm putting my solution here in case anyone is trying to achieve the same effect.

    I added the following js code in the index.html:
    Code (JavaScript):
    1. var scaleDownByPixelRatio = function() {
    2.     if(devicePixelRatio > 1) {
    3.         var canvas = document.querySelector("canvas");
    4.         canvas.style.transformOrigin = "0 0";
    5.         canvas.style.transform = "scale("+1.0/devicePixelRatio+")";
    6.     }
    7. }
    8. scaleDownByPixelRatio();
    And then I edited the fillMouseEventData function in the generated js file by doing the following replacements wherever these variables are used in the function:
    Code (JavaScript):
    1. e.screenX // replace by (e.screenX * devicePixelRatio)
    2. e.screenX // replace by (e.screenX * devicePixelRatio)
    3. e.clientX - rect.left // replace by (e.clientX - rect.left) * devicePixelRatio
    4. e.clientY - rect.top // replace by (e.clientY - rect.top) * devicePixelRatio
    I hope this is useful to anyone ;)
     
    jonas-echterhoff likes this.
  4. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
  5. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,666
    There are no changes to this in 5.5. As I wrote, we will not look more into this, before we have this nailed for standalone builds.
     
  6. tomhog

    tomhog

    Joined:
    Dec 22, 2012
    Posts:
    36
  7. kognito1

    kognito1

    Joined:
    Apr 7, 2015
    Posts:
    331
    My only request on the "official solution" is to make it an option. Rendering at retina resolutions with an integrated gpu might be a challenge! Of course having the option is always nice. Thanks for providing a workaround.
     
  8. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    @tomhog: That would have been handy, but too late. I already have my own auto-hack solution :)
    @Kognito: I agree.

    If using macOS / Safari The hack solution described above seems to bring the entire system almost to a halt. The UI Server becomes irresponsive. If you're patient you can stop/kill Safari and then it's back to normal. We confirmed this multiple systems:

    OS X 10.11.2 with Safari Version 9.0.2
    macOS 10.12.1 with Safari 10.0.1

    Don't know about Safari on Windows though.

    Solution suggestions:
    • Ignore those users.
    • exclude Safari at all (via Browser detection)
    • disable the hack on Safari only (via Browser detection)
    • Wait for Unity version ? to fix this.
    • ?
    I hope this puts a bit more pressure on the issue.
     
  9. tomhog

    tomhog

    Joined:
    Dec 22, 2012
    Posts:
    36
    @atti

    Your issue on Safari may be related to your CSS width/height for the canvas. In the original version of my fix i suffered from an issue in which I'd multiply the canvas width height by the device pixel ratio, then on the next frame it would get multiplied again because the size was getting buffered in some way. This resulted in the canvas doubling each dimension every frame and causing my system to become unresponsive or even crash entirely. The fix requires constraining the canvas dimensions using css.

    My new fix works on all the browsers I've tested and also fixes mouse coordinates which require scaling and offsetting for the canvas to work in all situations. If you download the free version you can probably get an idea of what you need from the source.
     
  10. DarekRusin

    DarekRusin

    Joined:
    Nov 15, 2013
    Posts:
    47
    @jonas-echterhoff Checking in, has anything improved since Unity 5 in this area? Do you guys have any plans to tackle the issue of high dpi on WebGL in the upcoming releases?
     
  11. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,654
    We have been considering adding support for high dpi but we haven't done any work yet. We might look at it at some point but I can't promise anything at this point as it does not seem many people are asking for it.
     
  12. DarekRusin

    DarekRusin

    Joined:
    Nov 15, 2013
    Posts:
    47
    Marco, thanks for getting back. I hope you'll be able to get to this sooner rather than later. Truth be told, I did notice that there aren't that many people begging for this to be done, but perhaps they're like me, resigned to using some home made patch or going with a plugin (the one @tomhog did seems to be working), waiting for official support.

    Because I don't imagine you'd want to leave it like this for a longer while. High DPI screens are more and more popular and we don't want Unity games to look crappy on those shiny big Retina screens :) Especially if the fix is rather easy (judging by the code from the plugin mentioned above).
     
    SNS_Case, jspivack and EmperorTim like this.
  13. Deleted User

    Deleted User

    Guest

    After some digging and tips from others, I ended up here.
    Running into the same problem here for a client. WebGL on a UHD 4K screen.
    Fullscreen is running bordered, and client being annoyed.

    If this can be fixed easily in Unity, let's hope it will be soon. This will only get more a problem with the next gen monitors.

    cheers,

    rob
     
    jspivack and EmperorTim like this.
  14. EmperorTim

    EmperorTim

    Joined:
    Jun 7, 2018
    Posts:
    1
    I'd like to add my name to the list of keen people looking for a native solution. Currently I use a somewhat hacky script to manage it (the one from hbx didn't work for me oddly) but a proper implementation of webgl retina support would be awesome.
     
  15. musspell

    musspell

    Joined:
    Oct 17, 2015
    Posts:
    7
    How can you guys apply those hacks on a gzip compressed build?

    I tried to unzip the file and apply the changes, but then I couldn't compress the file again because I don't know the gzip parameters Unity uses when generating the build. If I try manually compress the file it generates an error when trying to run the project on browser (error: illegal character).
     
  16. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    175
    We don't.
    We build uncompressed and make sure our HTTP server supports compression.
     
  17. musspell

    musspell

    Joined:
    Oct 17, 2015
    Posts:
    7
    I ended up using the Asset from @tomhog . It works very well on the latest Unity version and it seems he managed to work with gzip compression.
     
  18. jspivack

    jspivack

    Joined:
    Feb 21, 2018
    Posts:
    2
    One more vote for needing this fixed... I don't understand why Unity is always a year behind in fixing 4k screens. First the editor was non-functional in 4k and now WebGL.
     
  19. dustinw

    dustinw

    Joined:
    Feb 11, 2013
    Posts:
    7
    This should be addressed. Why even support WebGL if you are going to ignore high DPI screens? Practically all laptops are high DPI these days. My game is blurry on these screens. Not acceptable.
     
  20. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    2,276
    This is not just a problem for 4k but for non-native res. on mobile devices too, given android is working pretty well with webgl (despite the dodgy message Unity pops up by default!).
    It seems Unity's support for webgl needs to be better 'out of the box' but is this issue typical of webgl content or just poor implementation in this case?
     
  21. DonCornholio

    DonCornholio

    Joined:
    Feb 27, 2017
    Posts:
    92
    I also really would need to have this! Generally mobile support needs improvement, like offering proper texture compression.
    It also would be great if the high dpi feature was designed in a way that lets the developer render the 3d content at a smaller resolution and add high res ui on top of that.
    Unity webgl works actually fine on mobile but the high dpi, texture compression and loading times could be improved greatly.
    Please invest a bit more into webgl platform. I know that unity tiny is coming, but it will be some time until 3d will be available and everything is reliable enough for production. Also there are a lot of existing projects that probably won't be ported to tiny and are in desperate need for proper mobile support.
     
  22. kognito1

    kognito1

    Joined:
    Apr 7, 2015
    Posts:
    331
    Unity's "problem" with dpi is emscripten really. That's actually where I had to implement my workaround (where emscripten sets the canvas height/width and where it converts JS mouse events to emscripten mouse events). There's no easy solution here for Unity unfortunately; they'll have to edit emscripten.

    Having said that, I think you guys are greatly overestimating how hard it is to get dpi (or any) scaling working with Unity webgl. I mean yeah annoying it's not supported by default, but working around it is not THAT bad. :D
     
    EmperorTim likes this.
  23. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    2,276
    @tomhog seems to have the only solution visible though (albeit paid)
    Not sure it handles mobile though - the demo is wrong resolution.
     
  24. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    It's fixed in 2019.3 beta.
     
    massimofellucci likes this.
  25. AVK79

    AVK79

    Joined:
    Oct 18, 2016
    Posts:
    4
    To Unity team - Will this get back-ported to Unity 2018.4.x LTS ?
     
  26. Schubkraft

    Schubkraft

    Unity Technologies

    Joined:
    Dec 3, 2012
    Posts:
    1,073
    Sorry, but it will not be backported.
     
  27. massimofellucci

    massimofellucci

    Joined:
    Feb 27, 2018
    Posts:
    5
    I have been searching almost 2 weeks for this answer. Thank you so much
     
  28. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    But video player is broken, just a warning if you need it.
     
    massimofellucci likes this.
  29. ANTONBORODA

    ANTONBORODA

    Joined:
    Nov 16, 2017
    Posts:
    52
    Is constant pixel size still broken on WebGL?
    Seems like setting a 100%/150%/200%... etc scaling in Windows produces the same exact size of the UI elements after the WebGL player has been restarted and this is not how it supposed to be. It does, however, behave properly before the page is reloaded.
    It looks like it's impossible to make a UI on WebGL that gives more "playable" space when you have higher resolution with smaller scaling factor, i.e. controls should stay 100x100 pixels when loaded on a 4K screen with 100% scaling and be 200x200 pixels on 200% scale.
     
  30. Marks4

    Marks4

    Joined:
    Feb 25, 2018
    Posts:
    547
    Yes. It's still broken on the 2020.1 beta version. I sent a bug report.