Search Unity

WebGL is rendered in low resolution for pages with viewport meta tag

Discussion in 'Project Tiny' started by laserval, Aug 16, 2019.

  1. laserval


    Aug 15, 2019
    I am seeing poor resolution in Web builds using WebGL on devices with high DPI, when the page has a viewport meta tag. The tag is used to make mobile browsers use the actual screen size instead of assuming the page is 980px (apparently the convention among mobile browsers).

    For example, building a release build of the HelloWorld sample project and adding the following HTML tag to <head>:

    Code (html):
    1. <meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0">
    Opening this in Chrome on Android will give you a blurrier game than without the viewport meta tag. See the attached images.

    Default generated page: default.jpg
    With viewport meta tag: with-viewport-meta.jpg

    I believe the reason for this is that the Project Tiny runtime is using the wrong dimensions for the canvas and ignoring the DPI.

    To fix the default behaviour, I modified the generated {projectname}.js:

    In _js_html_getFrameSize, multiplied the innerWidth/innerHeight with devicePixelRatio

    Code (javascript):
    1. function _js_html_getFrameSize(wPtr, hPtr) {
    2.     HEAP32[wPtr >> 2] = window.innerWidth | 0;
    3.     HEAP32[hPtr >> 2] = window.innerHeight | 0
    4. }
    6. // changed to:
    8. function _js_html_getFrameSize(wPtr, hPtr) {
    9.     HEAP32[wPtr >> 2] = (window.innerWidth * window.devicePixelRatio) | 0;
    10.     HEAP32[hPtr >> 2] = (window.innerHeight * window.devicePixelRatio) | 0
    11. }
    In _js_html_setCanvasSize, add the height and width in CSS pixels to the style attribute on the created canvas element.

    Code (javascript):
    2. canvas.setAttribute("style", "touch-action: none;");
    4. // changed to
    6. canvas.setAttribute("style", "touch-action: none; height: " + height / window.devicePixelRatio + "px; width: " + width / window.devicePixelRatio + "px;");
    When I did this, the game is rendered in reasonable resolution on a mobile device. The canvas is rendered in high DPI, then the HTML element is given the correct CSS pixel size on the page.
    Unfortunately it results in much higher rendering resolution in the canvas on pages that lack a viewport tag, since the mobile browser defaults to 980px wide screen.

    Avoiding using the tag presents problems when you want to embed a game in an iframe, where you might not have control over what meta tags the top page has.

    I suspect there is a better way to handle this!