A-Frame - Virtual Reality on the Web Simplified

16 Dec 2015

Today, the Mozilla virtual reality team (MozVR)
released an open-source library for beginners and developers alike to easily
create WebVR experiences. It’s called A-Frame. A-Frame
wraps three.js into custom elements so the HTML and DOM manipulations that web
developers are accustomed to can be used to create 3D VR scenes in the
browser. Under the hood, A-Frame brings the entity component
system, a pattern
common in game development, to the DOM. It supports both desktop, if you got a
Rift, or easier, you can even use a smartphone. This post serves as a
speed-through introduction of A-Frame, refer the
documentation at any time for much more detail.

A-Frame, like the video games that have influenced all of us, ships at a
several difficulty levels. We’ll journey all the way from the comfortable bed
of hierarchical HTML, through the jungles of the core entity-component system,
and finally scale the walls of integration with React.

Check out A-Frame stylin’ with the DevTools.

Enabling WebVR

At time of writing, to view the scenes in VR:

On desktop, get Firefox Developer Edition or Firefox Nightly, and install the
WebVR Enabler Add-on. To use with an Oculus Rift DK2, have the Oculus
runtime installed (0.5.x for OS X).

On mobile, just open any A-Frame site using your phone browser (e.g., Firefox
for iOS, Firefox for Android, Chrome for Android, Safari for iOS).

“Piece of Cake” Difficulty - Codepen

For those that just want to play around with A-Frame immediately, check out the
example on Codepen. Codepen lets you edit code in the browser and
immediately see the result. You’ll see a scene that currenty looks something
like this:

With the introductory Codepen examples, we are exposing a very high-level
abstraction on top of A-Frame, using templated primitives, to ease developers
into the entity-component system. So this should be fairly readable to most. Now
what do we do with this? Click on the Goggles icon to view in VR. And try
modifying some values and see the scene change live.

Try changing the color of the cube (e.g., color="#748B9C" for a rainy day blue).

Try changing the size of the sphere (e.g., radius="0.25" to make it a little baby sphere).

Try changing the position of the cylinder (e.g., position="1 1 1" to raise the roof).

As amazing as that was, a Codepen is still a pen. The ambitions of VR are not
suitable for being fenced in. Like the Kool-Aid Man, we must break out of the
confinements of a coding playground.

“Let’s Rock” Difficulty - Boilerplate

For beginners that want to start playing with some toy scenes locally and hacking away,
check out the basic A-Frame boilerplate.
Boilerplate refers to pre-written reusable code that can be made your own with
minimal modification.

Note that I say this intended for beginners because it focuses on using the
templated primitives abstraction and hides away the underlying engine. For
developers that want to get their hands dirty, I would skip this and move
directly to the entity-component system.

The boilerplate provides the same code found in the Codepen above, but also can
be downloaded as a ZIP package or forked on Github. Once you have the code on
your machine, just modify it in your favorite text editor and fire it up in the
browser.

“Come Get Some” Difficulty - Primitives

For those that want to start writing scenes from scratch in vanilla HTML, check
out A-Frame’s pre-built primitive.

A “primitive” in computer graphics is a basic building block like a cube or a
sphere. They are:

Are pre-fabricated custom elements like <a-cube> or <a-sphere> that combine
recipes of components to achieve the intended result.

Are a convenience and usability wrapper on top of the underlying entity-component system.

Are much cleaner in syntax but are less flexible and composable than using the
entity-component system directly.

<a-cube> wraps a single entity (with the geometry.primitive=box) and
exposes a few component attributes as HTML attributes. Don’t worry about the
attributes that seem unfamiliar, we will go over some of them later and point
to the comprehensive documentation.

A-Frame also has an animation system. Let’s try
makng the cube rotate indefinitely. The animation system also works with the core system,
not just templates.

Caveats

Templates may be subject to flux such as reimplementation or modularization
into a different repository. From a technical standpoint, A-Frame templates and
primitives are somewhat immature and less flexible, but from a product standpoint,
they are more usable and less exotic to newer users of A-Frame. For full flexbility,
we have to dig deeper.

“Damn I’m Good” Difficulty - Entity-Component System

For those that want to be unleashed into the full promised power, flexibility,
and composability of A-Frame, we can finally end the hand-waving and check out
the core entity-component system.

Despite having been abstracted away from the aforementioned templates, A-Frame is built on an
entity-component system. Entities are general purpose placeholder objects.
Components modify the appearance, behavior, or functionality of the entities.
And every object in the scene is an entity whether it be the player, a tree, a
monster, the sky, a sound, lights. Components can be mixed and matched,
composed and overridden. A-Frame comes with a bunch of components, and anyone
can write their own components to have objects look however or do whatever
they want. Check out all of the shipped components,
and check out some third-party custom components at awesome-aframe.

Let’s start with a blank entity:

<a-entity></a-entity>

By default, this lonely entity inherently only has a position, rotation, and
scale in the scene. Without any other components, nothing will render on the
scene. Let’s change that, giving it a geometry (shape) and material (appearance).

There are all of these components that can customize our entities. And all
these attributes that can customize our components. And anyone can write their
own components, having free reign to add any behavior they
can imagine. Some components we might write include a layout component, a
vibrate component, a cloner component, an explode component, a set-on-fire
component. I am very excited to see what people come up with.

The raw entity-component system is what we consider low-level. But all
low-level things are made to be abstracted. Bring on the hot trend of 2015,
React.

“Born to be Wild” Difficulty - React

Note that A-Frame + React integration is experimental and is currently my
personal project. I haven’t yet stress-tested possible performance limitations
that the Virtual DOM may introduce. react-three,
another React library on top of three.js, had limitations because each object
introduced its own requestAnimationFrame. React + A-Frame does not have those kinds of
limitations.

Using React provides the best of all the worlds. The conciseness of A-Frame
templates, the power of the A-Frame core system, and the ecosystem of NPM. The
scene here is pretty concise and easy to read.

To demonstrate how easy it is to create React components, here is the definition
for a dumb <Light> using a stateless React component:

I imagine, with the current state of web development, that people will enjoy
this. I know I will.

Behind the Scenes - Developing A-Frame

Getting more into personal notes, I have been contributing to MozVR and A-Frame over the last
couple months, working on the core entity-component pieces of the system at
A-Frame Core. With Firefox OS
smartphones having “fallen” and with my previous team as well as dissolved,
working in 3D and VR has been immensely exciting. To catch up, I have had to
read and take notes about design, brush up on my linear alegbra, and dive into
the world of 3D rendering. The Design of Everything Things,
Real-Time Rendering, 3D Math Primer,
Rework and Virtual Reality Insider
were all books that came in handy.

The hardest thing about developing on A-Frame was feeling out the target
audience. Should this be for beginners, for everyone and their grandma, for
novices, for seasoned developers? I still don’t feel it’s been quite resolved.
It’s a question that has driven a lot of debates with the API design and
messaging. One instance of contention was the naming of <a-entity> vs. the
former <a-object>. Or whether or not to hide the entity-component system
behind templates and primitives such that A-Frame does not seem too exotic.

The most fun thing about developing on A-Frame was how much there was to learn
and discover. I was just about to hit a ceiling on the Firefox Marketplace
team; after taking the whole React and Redux journey and absorbing everything,
I had well outgrown the project (well, especially since it was dying). Jumping
into 3D and VR, I accumulated noob
gains on 3D
development, rendering, game development patterns, and API design. And working
with a team in-person rather than remotely was refreshing

And there’s more to discover like what standard VR interactions will form and
what will VR web browsing look like? It’s imagining a future that hasn’t come.
Y’all remember bring your A-Frame.