Four Kitchens
Insights

React VR: an early look at Facebook’s foray into VR

6 Min. ReadDevelopment

As I, 12-year-old Luke, walked aimlessly around the Dave and Buster’s arcade, I wandered into the back of the room and saw what looked like a scene from the future: Two gamers stood on separate platforms four feet off the ground, wearing strange headsets and holding gun-shaped controllers. They spun around, recklessly yelling and shooting at what appeared to be nothing until their turn was up.

Intrigued, I decided to give it a try and challenged my cousin to a round. The D&B’s employee strapped the too-large headset on me and quipped, “Don’t actually walk”, for what I’m sure was the 20th time that day. As the game got started, I remember thinking, “These graphics suck and the lag is making me sick”. I couldn’t even find my cousin in the map, and to make matters worse, I took a couple actual steps and got yelled at by the grumpy D&B’s employee. Suffice to say, my first VR experience left me wondering what all the hype was about. If that was the future, I’d rather stick with my N64.

Almost 20 years later, VR is back, and this time I think it’s here to stay. What was once a cheesy, low-res arcade trick is now available to anyone with a smartphone and can be built by any web developer with JavaScript experience.

The Web Always Wins

Adapting Marc Andreeson’s famous quote, “Software is eating the world”, Eric Elliot, a thought-leader in the JavaScript community asserted, “Software is eating the world, the web is eating software, and JavaScript rules the web.”

It’s true. The web is everywhere, and where the web goes, it takes JavaScript with it. Our JavaScript-based web is resilient, and it’s quickly becoming a contender as a VR platform in its own right.

Even as the WebVR spec is still being drafted, browsers are implementing it. Early on, A-Frame became a solid and tested solution for building WebVR experiences with JavaScript. Coupled with aframe-react, it makes the developer experience very approachable. In fact, that’s the combo we used to build our 2017 Drupalcon WebVR demo. However, as the JavaScript ecosystem goes, it’s not the only WebVR framework out there.

In December of 2016, Oculus (in cooperation with Facebook), announced React VR. At first glance, its code is almost indistinguishable from an app built with aframe-react. However, there are major architectural differences between the two that have implications for even the simplest WebVR projects.

A-Frame and React VR: What’s the Difference?

A-Frame, released in December of 2015, exposes custom HTML elements that make up a declarative and composable layer on top of Three.js, a cross browser JavaScript library for building 3D graphics with WebGL. A-Frame is just HTML, which lowers the barrier to entry and makes it possible to build really fun experiences with minimal effort. Check out my colleague Patrick’s Introduction to A-Frame to see how easy it is to get started building your own experiences with A-Frame + aframe-react.

Here’ the simple Hello World application written with A-Frame + aframe-react from his post:

/**
 * @file index.js
 * Renders VR experience or Editor depending on REACT_APP_ENV value.
 */

import React from 'react';
import ReactDOM from 'react-dom';
import { Scene, Entity } from 'aframe-react';

require('aframe');
require('./index.css');

/**
 * Initial A-Frame Scene.
 * {@inheritdoc}
 */
const InitialScene = () =>
  <Scene inspector="url: https://aframe.io/releases/0.4.0/aframe-inspector.min.js">
    <Entity
      id="entity--box"
      primitive="a-box"
      position={{ x: -1, y: 0.5, z: -3 }}
      rotation={{ x: 0, y: 45, z: 0 }}
      color="#4CC3D9"
    />
    <Entity
      id="entity--sphere"
      primitive="a-sphere"
      position={{ x: 0, y: 1.25, z: -5 }}
      radius={1.25}
      color="#EF2D5E"
    />
    <Entity
      id="entity--cylinder"
      primitive="a-cylinder"
      position={{ x: 1, y: 0.75, z: -3 }}
      radius={0.5}
      width={4}
      height={1.5}
      color="#FFC65D"
    />
    <Entity
      id="entity--plane"
      primitive="a-plane"
      position={{ x: 0, y: 0, z: -4 }}
      rotation={{ x: -90, y: 0, z: 0 }}
      width={4}
      height={4}
      color="#7BC8A4"
    />

    <Entity primitive="a-sky" color="#4286f4" />
  </Scene>;

// Render the InitialScene component in the scene container div.
ReactDOM.render(<InitialScene />, document.getElementById('root'));

React VR also makes it is easy to get started. It’s as simple as
$ yarn create react-vr-app ProjectName
and you have a project boilerplate ready to hack.

Looking at the code, React VR appears very similar to aframe-react on the surface. It too provides a declarative and composable API on top of Three.js expressed in JSX. However, that is where the similarities end. Architecturally, A-Frame and React VR couldn’t be more different. The pre-release written by Andrew Imm, one of the creators of React VR, describe its architecture this way:

We followed [React Native’s] pattern by running React and rendering in separate contexts, with an asynchronous bridge for communication between them. In the web browser, this separation is performed with a web worker—your entire React application runs in the worker, while the rendering code that turns scene update messages into actual pixels lives in the main window. This lets the renderer create a tight loop between receiving headset orientation updates and re-rendering the scene, increasing viewer immersion while decreasing the likelihood of motion-sickness.

–Andrew Imm

It looks something like this:

However different React VR and aframe-react’s architectures may be, the code you write turns out to be fairly similar, structurally. Here’s what the above code sample would look like when written with React VR:

import React from 'react';
import {
  AppRegistry,
  Box,
  Cylinder,
  Sphere,
  Pano,
  Plane,
  View,
  Animated,
  SpotLight,
} from 'react-vr';

const AnimatedBox = Animated.createAnimatedComponent(Box);

const InitialScene = () =>
  <View>
    <Pano />
    <SpotLight
      style={{ transform: [{ translate: [-10, 20, 30] }] }}
      angle={90}
      intensity={1}
    />
    <AnimatedBox
      dimWidth={2}
      dimDepth={2}
      dimHeight={2}
      style={{
        color: '#4CC3D9',
        transform: [{ translate: [-2, -4.5, -13] }, { rotateY: 20 }],
      }}
      lit
    />
    <Sphere
      style={{
        color: '#EF2D5E',
        transform: [{ translate: [0, -4.5, -20] }],
      }}
      heightSegments={50}
      radius={2.5}
      lit
    />
    <Cylinder
      radiusTop={1}
      radiusBottom={1}
      dimHeight={4}
      segments={50}
      style={{
        color: '#FFC65D',
        transform: [{ translate: [2, -4.5, -15] }],
      }}
      lit
    />
    <Plane
      dimWidth={13}
      dimHeight={13}
      style={{
        color: '#7BC8A4',
        transform: [{ translate: [0, -7.5, -20] }, { rotateX: -90 }],
      }}
    />
  </View>;

AppRegistry.registerComponent('reactvr_example', () => InitialScene);

export default InitialScene;

Download the React VR code from the Four Kitchens VR project GitHub, and experience the demo yourself:

Why All This Architecture Talk?

Architecture matters because the constraints of a framework directly affect what your application can do, and how easy it is to implement.

For example, while the code written in React VR looks similar to that of aframe-react, you may notice that by nature of running in a WebWorker, it has no direct access to the window object. Where this becomes especially painful is when attempting to reflect routing changes in your application—like changing scenes in a WebVR tour—in the URL.

Another implication of your React VR application running in a WebWorker is that your application cannot not be embedded in an existing website without the use of an IFrame and at that point, communication between the web page and your application becomes difficult.

Unrelated to architecture, another drawback of React VR is that it is immature, and frankly, lacking in documentation. While the bare essentials are present, when compared to A-Frame’s rich example set and documentation, it’s clear React VR has a long way to go in educating its users.

Keep an Eye on ReactVR

Disclaimers aside, React VR has a very promising future. While its architecture leaves a couple gaps in important Web APIs, it also paves the way for compiling your VR experience to multiple runtimes beyond the web. In fact, the new Oculus Home app is powered by React VR backed by a native renderer. If you want to hear more about the future of React VR, watch Mike Armstrong’s React Europe 2017 talk.

While A-Frame remains a solid and tested solution for building stable WebVR experiences, I’m keeping my eye on React VR as it grows and matures. One thing is for sure: React’s community is amazing. If React VR gets the same kind of community support and attention that other React projects do, I think it will quickly become the go-to solution for building VR experiences for the web and beyond.

Remember to check out the companion repo for this post and experience the demo yourself! Hack it up and see if you can’t make it do something fun!