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): var c = document.querySelector("canvas"); var w = c.width; var h = c.height; c.width = w * devicePixelRatio; // devicePixelRatio = 2.0 on a retina screen c.height = h * devicePixelRatio; c.style.width = w + "px"; 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 !
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.
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): var scaleDownByPixelRatio = function() { if(devicePixelRatio > 1) { var canvas = document.querySelector("canvas"); canvas.style.transformOrigin = "0 0"; canvas.style.transform = "scale("+1.0/devicePixelRatio+")"; } } 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): e.screenX // replace by (e.screenX * devicePixelRatio) e.screenX // replace by (e.screenX * devicePixelRatio) e.clientX - rect.left // replace by (e.clientX - rect.left) * devicePixelRatio e.clientY - rect.top // replace by (e.clientY - rect.top) * devicePixelRatio I hope this is useful to anyone
I really hope there's a fix for this in 5.5. Unfortunately the corresponding issue got closed: https://issuetracker.unity3d.com/is...lscreen-in-safari-on-mac-with-retina-displays
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.
Hi, just to let you know i've developed an automated solution for this to use in Unity 5.4.1 and plan to keep it updated until an offical solution is provided https://forum.unity3d.com/threads/webgl-retina-tool-1-0.441429/
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.
@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.
@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.
@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?
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.
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).
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
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.
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).
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.
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.
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.
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?
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.
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.
@tomhog seems to have the only solution visible though (albeit paid) Not sure it handles mobile though - the demo is wrong resolution.
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.