Build an Advanced Portal Experience

Create a two world portal experience using advanced SDK capabilities


This document provides a brief overview and walkthrough into the construction of a portal experience, built using ‘Blippar's WebAR SDK, A-Frame, Blender(optional).’ It displays an output of a portal model fixed to an identified surface. This portal provides a gateway through a door, to a whole new virtual world! (see here).


The main concept on which the portal experience is built is described in this document.

Portal Experience Logic

The portal experience logic has the following needs:

  • Room 3D model, a Sphere with 360° image/video texture

  • Door 3D model to enter the Room.

  • Hider 3D model, a Sphere with invisible material to make the external surface of the Room invisible on the AR scene.

WebAR SDK API Utilised

It mainly uses the following two WebAR SDK APIs:

  1. SetPortalEntryCallback() API When the user takes the mobile phone closer to the Door 3D model (which is at the origin of the detected surface), SetPortalEntryCallback() API triggers the passed callback.\

  2. DisableTracking(true) API

  • This API disables the Surface Tracking in the callback.

  • This API can also be used to enable the gyro camera experience.

  • Pass the argument as true as in DisableTracking(true) call to enable it.

  • The user can use the gyro camera to experience an entry into a virtual world and look around the inner side of the Room Sphere having 360° image/video material


Follow the below steps to create your AR portal experience web app:

  • Creating the Portal Models in Blender is (STEP 1-OPTIONAL) You can use the portal and hider 3D models that we have already created for your testing purposes from the Github repo here and proceed to STEP 2

  • If you are making your own portal models, make sure the door is at the origin of the detected surface i.e. <a-entity webar-stage> as shown in Fig 1.

Step 1: Create Portal Models in Blender (Optional)

The AR portal experience basically needs two models.

portal.glb containing:

  • Portal Door - A Grid mesh converted into a rectangular door and located at the origin.

  • Portal Room - A Sphere mesh with a 360° image texture

portal-hider.glb containing:

  • Portal Hider - A Sphere mesh to cover/hide the Portal Room mesh. This Portal Hider model will be made transparent so that the Portal Room will look invisible from the outside.

To Create a portal.blend file follow the steps:

  • Open the Blender application

  • Create a New General Blender file.

  • Select all the default objects (Cube, Camera and Light) and Delete them.

  • Save the empty Blender scene as portal.blend file.

To Create and export the GLB model files in Blender follow the steps:

A. Create a Portal Door Mesh

  • Add a Grid mesh

  • Rotate it about the X axis by 90°

  • Switch to Edit Mode, select the inner _Faces_ of the Grid mesh and Delete them

  • Switch to Object Mode and edit the Scale properties as X = 0.200, Y = 0.250

  • Switch to Edit Mode, select all the Faces and Extrude by 0.1

  • Switch to Object Mode and edit the Location properties as Y = 0.1 m, so that the entrance is exactly at the origin.

B. Create a Portal Room Mesh

  • Add a UV Sphere mesh and change its Add UV Sphere attributes to Segments = 32 and Rings = 32

  • Change its Location properties to Y = 1.025, so that the Grid(Door) mesh intersects on the surface of the sphere

  • Switch to Edit Mode, select the sphere's Faces appearing within the door boundary and Subdivide the Edges by setting Number of Cuts = 2

  • Deselect all and Select the sphere's Faces appearing within the door boundary and Delete them_._

C. Add a 360° Texture Image to the Portal Room Mesh

  • Select the Sphere mesh

  • Add a new Material and change its Base Color to Image Texture

  • Click Open and select a 360° image file of your choice

  • Right click on the sphere and select Shade Smooth

  • Click Viewport Shading, Click Display in Material preview mode to verify the 360° texture material

  • Select the Grid mesh

  • Add a new Material and change its Base Color to any color of your choice

D. Create the Portal Hider Mesh

  • Select the Sphere mesh and Duplicate it in the same location

  • Rename the new Sphere.001 mesh as Hider

  • Scale the object to 1.01 across all the axis

  • Go to its Material Properties and Remove its Material Slot

E. Export the Portal GLB

  • Select both the Grid and Sphere meshes

  • Go to File -> Export -> glTF 2.0 (.glb/.gltf)

  • On the right side panel of Blender File View dialog, go to Include tab and check Selected Objects (if not checked)

  • Enter the name as portal.glb

  • Click Export glTF 2.0 button

F. Export the Portal Hider GLB

  • Select the Hider mesh

  • Go to File -> Export -> glTF 2.0 (.glb/.gltf)

  • On the right side panel of Blender File View dialog, go to Include tab and check Selected Objects (if not checked)

  • Enter the name as portal-hider.glb

  • Click Export glTF 2.0 button

Step 2: Setup Base Code Using the WebAR SDK Example

  • Purchase the Blippar License for your domain and download the WebAR SDK zip file. Extract the files and two folders named blippar and example will appear.

  • Rename the example folder to portal-webar (or any name of your choice).

  • Copy the portal.glb and portal-hider.glb files created in the previous step (if you skipped the previous step copy them from this link) and paste it in the models folder.

Step 3: Import Portal models

  • Open the WebAR SDK folder in Visual Studio Code (VSC)

  • Click open portal-webar / index.html file

  • Under <a-assets> tag, do the following:

  • - Remove the following line

<a-asset-item id="astronaut" src="models/astronaut.glb"></a-asset-item>
  • +Add the following lines to import portal glb files as asset items

<a-asset-item id="portalhider" src="models/portal-hider.glb"></a-asset-item>
<a-asset-item id="portal" src="models/portal.glb"></a-asset-item>
  • Under <a-entity webar-stage>

  • - Remove the following line

<a-entity gltf-model="#astronaut" id="astronaut_1" rotation="0 0 0" position="0 0 0" scale="0.25 0.25 0.25" webar-loadmonitor="elType: glb"></a-entity>
  • + Add the following lines to add the portal models as AFRAME entities, scaled to 3.0 on all the axis

<a-entity gltf-model="#portalhider" id="portal_1" rotation="0 0 0" position="0 0 0" scale="3.0 3.0 3.0" webar-loadmonitor="elType: glb"></a-entity>
<a-entity gltf-model="#portal" id="portal_2" rotation="0 0 0" position="0 0 0" scale="3.0 3.0 3.0" webar-loadmonitor="elType: glb"></a-entity>

Step 4: Add Surface Landing Animation

<script src=""></script>
  • - Remove the following lines from the example code

<!-- Refer API:Functions documentation for more details -->
  // Give a callback when the WebAR Stage <a-entity webar-stage> is ready to display the 3d object
  WEBARSDK.SetStageReadyCallback(() => {'Stage is ready now!!!');
  • + Add the following lines of code under <body> and before <a-scene webar-scene> element to:

  • Create a custom landingcursor A-Frame component.

  • The landing cursor A-Frame ring object/entity created in the following steps uses this landingcursor component.

  • When initialised call WebAR SDK's SetStageReady() callback to emit landit event to start landingTimeline animation sequence.

  • Listen to cursorend mixin animation's animationcomplete event (animationcomplete__cursorend), to make portal objects visible and then cursor object invisible.

  var portalObject = undefined;
  var portalHiderObject = undefined;

  AFRAME.registerComponent("landingcursor", {
    init: function() {
      WEBARSDK.SetStageReadyCallback(() => {
        console.log('Stage is ready now!!!');
        portalHiderObject = document.getElementById('portal_1');
        portalObject = document.getElementById('portal_2');

        // First, show the surface landing animation

      this.el.addEventListener("animationcomplete__cursorend", e => {
        // Second, show the 3D object
        portalHiderObject.setAttribute('visible', true);
        portalObject.setAttribute('visible', true);

        // Hide surface landing cursor
        this.el.setAttribute('visible', false);
  • + Add the following lines of code under <a-assets> to:

  • Add a timeline asset <a-timeline id="landingTimeline"> in A-Frame's <a-asset>. It applies two timeline animations, cursorbegin and cursorend to the selected cursor entity (#landing).

<a-timeline id="landingTimeline">
  <a-timeline-animation select="#landing" name="cursorbegin"></a-timeline-animation>
  <a-timeline-animation select="#landing" name="cursorend"></a-timeline-animation>

+ Add the following lines of code under <a-assets> to:

  • add the animation mixin element <a-mixin id="landeffect" ...> which will be later used by the cursor ring object and it defines the following two animations:\

    • cursorbegin to make the cursor visible

    • cursorbegin to scale up the cursor object

<a-mixin id="landeffect"
 animation__cursorbegin="property: visible; from: false; to: true; dur: 1; autoplay: false"
 animation__cursorend="property: scale; to: 0.75 0.75 0.75; dur: 2000; easing: easeInOutElastic; autoplay: false"
 scale="0.0001 0.0001 0.0001"
 position="0 0 0"
  • + Add the following attribute to:

  • Add an animation-timeline attribute to A-Frame's <a-scene webar-scene> to link the landingTimeline element defined above

animation-timeline__1="timeline: #landingTimeline; loop: false; startEvents: landit;"
  • + Add the following line of code under <a-entity webar-stage> to:

  • Define the cursor ring object <a-ring landingcursor id="landing" mixin="landeffect" ...> which will be animated to scale up when a surface is detected

<a-ring landingcursor id="landing" mixin="landeffect" color="#FBB42C" material="opacity: 0.4; transparent: true" radius-inner="0.8" radius-outer="1" rotation="-90 0 0" segments-phi=30 segments-theta=96></a-ring>

Step 5: Add Portal Entry Logic

  • + Add the following lines of code under <script> tag which is before the <a-scene webar-scene> element:

  • To get a callback using WEBARSDK.SetPortalEntryCallback(), when the user goes closer to the Door which is at the origin of the detected surface i.e <a-entity webar-stage>

  • Once the Portal Entry callbackFunction is invoked, the WEBARSDK.DisableTracking(true) API is called to disable surface tracking and enable the gyro camera which is when the user's mobile phone camera is virtually inside the Room sphere model.

let closenessRatio = 0.25;

WEBARSDK.SetPortalEntryCallback(() => {
  console.log("Entered the portal door");

 let enableGyroCam = true;

  // Position to the center of 360 view
  // Its a one way portal. No going back to the real world
  portalObject.object3D.position.set(0, 0, 3.0);
  portalHiderObject.object3D.position.set(0, 0, 3.0);
  console.log("Enabled gyro cam");

Step 6: Hide Portal Backside

  • + Add hider-material attribute to <a-entity gltf-model="#portalhider" ...> as in the below code:

<a-entity gltf-model="#portalhider" id="portal_1" rotation="0 0 0" position="0 0 0" scale="3.0 3.0 3.0" webar-loadmonitor="elType: glb"
  • + Add the following lines of code under <script> tag which is before the <a-scene webar-scene> element to:

  • Define a custom A-Frame component which makes the Hider model and the object that is appearing behind this Hider model invisible.

  • Enable this by setting the material's colorWrite to false.

AFRAME.registerComponent("hider-material", {
  init: function () {
    this.el.addEventListener('model-loaded', this.update.bind(this));
  update: function () {
    this.el.object3D.traverse(function (child) {
      if (child.isMesh) {
        child.material.colorWrite = false;

Step 7: Start the HTTPS Server

  • Configure the Live Server VSC Extension settings.json to setup a self-signed HTTPS server.

  • For more details, refer the documentation on Develop Locally.

  • Click Go Live to start the HTTPS Server

  • Load the HTTPS server url in your mobile browser to start the WebAR portal experience

Step 8: Full Source Code

The full source code of this Portal WebAR example is available in the Github repo here.

Resulting Portal WebAR Experience