Visual Effects: A Portal in WebXR

Babylon.js
4 min readMar 7, 2024

We are at a such magic inception point across 3D, Web and XR that it is sometimes hard to stop watching videos of Augmented Reality demos. A few months ago, I stumble upon an augmented reality portal demo made with ARKit and embarked on the journey to rebuilt it on the Web with WebXR and Babylon.js. In this article, I’ll share the steps and lessons I learned along the way.

The demo of this article: an augmented reality portal in WebXR (demo and code)

Creating the Portal

For the portal itself, it was easy to leverage the visual effects that can be rendered with particle systems (see Visual Effects with Particles: a Guide for Beginners). The portal was made by assembling three pillars and adding particle systems. I played a bit with the Particle Editor to get to the right effects. It involved setting the particle emitters as cylinders around each pillar, tweaking their radius and the number of particles.

Portal effect using particles and glow layer (demo and code)

With the addition of a glow layer on the pillars (see Making Meshes Glow), to bring the impression of energy, I was set with a pretty cool portal. The only modification I had to make, when later adding the portal to the full scene, was to limit the glowing to only the portal meshes.

Adding the glow effect on the portal

Using an Occluder

The key to the demo came from a post on our forum where @sebavan and @raananw helped a user to create the effect of a hole on the floor. The effect was achieved by using an occlusion object that hides everything behind it by playing with the relative rendering groups.

Sample occlusion object (demo and code)

Renderable objects can be organized into rendering groups, which act as layers. Layers are rendered in ascending order by ID, starting with the default one (which has the ID of 0).

Sample occluder

Moving this to WebXR, I ended up with a demo where I could launch an AR session in WebXR and place the occluder in front of me on the floor. Detecting the floor and placing an object in AR can easily be done thanks to the magic of WebXR: the HitTest feature does all the work for you (see HitTest in Babylon.js WebXR Documentation).

A hole on the floor in WebXR (demo and code)

Bringing it all together

Now that I had all the building blocks figured out, it was time to get to start the final demo for which I was targeting the following flow:

  • The user starts a session.
  • Places the portal on the floor in the “real world”.
  • Walks and crosses the portal to get to the Hill Valley 3D scene.
  • Turns back to see the real world through the portal.

A lesson from my previous WebXR development experiences was to start with going as far as possible on a regular 3D scene. Testing and debugging an AR scene are slower because of the round trips to test in the XR device.

Steps by steps, the 3D scene was built. It started with loading the Hill Valley Scene, then adding an occluder with a door to see through it, and finally the last part was to build an occluder box around the user in the real world to hide the 3D scene.

First steps to position the occluder (grey/pink-ish areas will be replaced by the camera showing the real world)

The final step of this phase was to add a “reverse occluder”. This is the one you see when you pass through the portal and look back to see the real world.

“Reverse” occluder

At this stage, I was ready to move to the final phase: the final demo in WebXR! It involved changing the position of the various elements to the HitTest Position, add the portal with particles and glowing effects, and align it with the rest of the scene. Debugging between 3D and real word gave some mind twisting visuals but the prize was there at the end!

Final demo and code

Wrapping up

The demo was built and tested using Android. The magic of WebXR delivered when it ran on the Quest 3 out of the box! Time was limited so I took a few shortcuts: this demo could be enhanced in many ways. For instance, instead of using an occluder box in the real world, a ClipPlane could be used to avoid rendering anything until the portal. Another improvement, much needed actually, would be to use a collision plan for the portal, instead of just using the coordinates of the camera to detect on which side of the portal we are. Anyway, I definitely had a lot of fun preparing this demo — and I hope you’ll enjoy trying it!

Thomas Lucchini — Babylon.js Team
https://twitter.com/thomlucc

--

--

Babylon.js

Babylon.js: Powerful, Beautiful, Simple, Open — Web-Based 3D At Its Best. https://www.babylonjs.com/