WebXR + Polyfill + Firefox: Low Resolution

Hi all. I’m trying to migrate one of my apps from WebVR to WebXR. Because WebXR isn’t supported on Firefox yet, I’d like to use the WebXR polyfill: GitHub - immersive-web/webxr-polyfill: Use the WebXR Device API today, providing fallbacks to native WebVR 1.1 and Cardboard

When I enter a simple VR test scene on Firefox with an HTC Vive, the resolution is very low. I’ve struggled to figure out why. Here’s the test scene: Babylon Template (posted on my own server because I couldn’t figure out how to load the polyfill in the playground).

The test scene is not low-res when I view it in the Oculus Rift, though the Rift may have WebXR enabled by default (and so perhaps is not using the polyfill).

Any help you could offer would certainly be appreciated! Thanks!

WebXR support is browser dependant, so the Oculus uses the polyfillwhen you are using Firefox.
It would be interesting to see what screen size the device is reporting. Do you have a way to debug the process? When requesting to enter VR there is s even size definition (used to create the buffer to which the scene renders). Can you check the values for the Oculus and Vive?

I don’t have Vive, so I can’t check it myself…

Hi @RaananW. As always, much thanks for your help. I have discovered that if I add this line to my code, it looks great on an HTC Vive, FireFox, with the WebXR polyfill:

engine.setHardwareScalingLevel(0.25); 

The canvas size when initially running in my browser window is a bit less than the resolution in the HTC Vive. My best guess is that BABYLON (or the polyfill) isn’t updating the resolution for the VR headset, instead using the same resolution that’s used in the browser window. Changing the hardware scaling level effectively makes the canvas bigger in terms of dimensions.

But am I right in thinking that I’ll get poor performance if the size of the canvas after hardware scaling ends up being bigger than the resolution of the VR headset? It would be much better if I could detect the proper 1:1 resolution to use in the headset so I could set it exactly when entering VR. I haven’t been able to discover how best to detect the headset resolution, though. Any suggestions?

All the best.

When creating an XRWebGLLayer, the device should return an XRLayer that fits the device that you are running on. It receives a canvas context (which, in general, is the canvas you have in your browser) but it is only using it to render on the device. the width and height can be found at the render target in the default xr experience (during/after session initialization):

xrHelper.renderTarget.xrLayer

can you try logging the xrLayer’s parameters and see what you get? (you can also find it on every frame in the WebXRCamera’s update function).

WebVR used to scale the canvas to make it work. WebXR does it a bit differently, so I am scratching my head, trying to find the reason for that.

Have you tried manually resizing the canvas (before initializing the scene) and seeing if it does something?

Hi @RaananW. Thanks for your quick response. Once I’m in VR, it seems I can get the correct headset resolution, per your suggestion:

xrHelper.baseExperience.onStateChangedObservable.add((state) => {
        switch (state) {
            case BABYLON.WebXRState.IN_XR:
                debugger;  // To access variable names via console.
                break;
        }
});

In the console:

image

The resolution in the headset very much depends on the size of the canvas immediately before entering VR. My canvas has width and height set to 100%, so it always matches the size of the browser window. If I resize my browser (Firefox, Windows, with WebXR polyfill) and make it very small, the resolution in the headset (HTC Vive) after I enter VR is very poor. If I then exit VR, maximize the browser window, and reenter VR, the resolution is much improved (though still not great because my monitor resolution is currently set to only 1280 x 800).

I’ve also experimented with changing the canvas dimensions after I’ve entered VR (e.g., vrHelper.renderTarget.xrLayer.context.canvas.width = 1080). It does change what I see in the headset, but the two eye cameras are no longer aligned, so I think there’s something more I would need to do.

I also tried resizing my browser window while in VR:

You can see that the canvas resizes to match the browser window (per the css), but the portion of the canvas used to render the VR scene stays constant. Could this be related to the problem somehow?

Anyway, this is probably more info than you’re looking for! :slight_smile: Thanks again for all your help.

1 Like

So, this has bothered me a bit, combined with the utility render layer issue.

There was a small bug with the way the engine calculates the initial viewport. For the XR camera (which doesn’t really render) it was using the canvas size and not the XR framebuffer.

Here is a fix - fixing xr framebuffer size issue by RaananW · Pull Request #7730 · BabylonJS/Babylon.js · GitHub

2 Likes

And it will make it to 4.1 :slight_smile:

2 Likes

That’s the same problem I have. I am using Babylon.js v4.1.0
and polyfill in a new iPhone SX with Safari/Firefox/Chrome:
https://osmgo.org/xr/polyfill.html
The VR symbol gets visible and touchable. Frist there is this Cardboard picture
“Place you phone in your Cardboard viewer” before the stereo view.
If I do this in portraid mode, I have to rotate first and the resolution is very bad.


If I allreay have the landscape mode, the resolution is ok.
(There are other problems: no orientation sensors, no scene)

Is it Babylon or the polyfill code?
Please tell me, if I can help to test.

can you try with 4.2.?

Yes, I try
I used the “normal” https://cdn.babylonjs.com/babylon.max.js
On babylonjs.com I can’t find a place to download or link it.
But the playground is using it! And my browser-log tells me a path to use:
https://preview.babylonjs.com/babylon.max.js
(This seems a week source, I often got timeout and placed it locally)

Still the same muddy optic.
If I start in landscape and rotate the phone up and back, it also gets worse.

ok maybe @RaananW can help

You can’t use XR on an iphone.

iOS doesn’t even support WebVR, and WebXR is a long way from being supported (as it seems). I always wanted to see whether or not we can do - WebVR Polyfill -> WebXR Polyfill -> WebXR scene, but this is something I never tested (and as I don’t have a working iphone, i won’t test it in the near future as well).

The VR button that you saw is probably due to an integration of the WebVR experience helper or a different VR camera (the XR experience helper doesn’t have this cardboard-style compensation). But I couldn’t find a reference to it in the code. Is the code fully updated? was it changed?

Regarding firefox - I will have to look into that issue when I get the chance. this probably has something to do with the canvas initialization, but I don’t have a better answer right now.

I know that firefox for the oculus browser had quite a lot of problems with babylon.js (we have field a few issues, still waiting on them to be closed), but there is at least no need for a polyfill there.

Ran a quick check using the polyfill, firefox and the MR emulator - the resolution you start the canvas at is the resolution that will be used in the XR experience. This does make sense, as WebVR required changing the size of the canvas to the right resolution before entering VR. But as we are in XR, we don’t resize the canvas. As a temporary solution enlarge your scene to max before entering XR, it should give you proper resolution in the headset.

What you can also do is force the canvas to resize (the actual canvas resolution). The only way I am going to introduce this kind of step in the framework is if it is impossible to achieve that on the dev level (which i doubt). Adding canvas resizing just for the WebXR polyfill will probably not integrate in the framework.

Thank you for your extended answers and the time effort you spent. :sunflower:
Looks like we could not solve but compensate the resolution problem.

It is not the only problem with the XR experience because:
“the XR experience helper doesn’t have this cardboard-style compensation”
I will write a more general Question for this.

1 Like