Week 1 - In the beginning

Pong: Week 1 - In the beginning

Week one will probably be a slightly longer blog post that will cover the setup and some of the core concepts of WebVR and A-Frame along with my initial creative thinking and explorations. It’s likely that these two voices, the technical and creative will feature heavily in this and future blog posts. On the technical side I learnt about setting up a project with A-Frame and building scenes using components, entities, primitives and assets. On the creative side I explored using limited pallets and fine tuned the animations and reflections.

The technical

In the beginning there was nothing, and then Mike said git clone https://github.com/aframevr/aframe-boilerplate/, then he then said, npm install. And he waited a moment, and he waited some more, then he decided to get a coffee, and when he came back he had created the universe!

Getting started with A-Frame was really easy and it feels great to create a scene like this with just a few key strokes. I had no experience with WebVR before and I was able to get the pre-packaged scene up and running and start manipulating it in around 10 minutes. I’d strongly recommend starting with the boilerplate project. This will help you get your head around how everything works.

One of the first things I noticed was that components in A-Frame are conceptually like html elements. This follows what seems to be a growing trend with many frameworks and libraries at the moment and it works well in this case. It’s a great mental model well suited to describing a VR scene, and one that is already familiar.

You can design an entire scene in the browser using tags that represent physical entities. You can add custom properties to manipulate different aspects of these entities. You can even write your own.

In the boilerplate project, you start with a scene like this:

<a-scene>
  <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
  <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
  <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
  <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
  <a-sky color="#ECECEC"></a-sky>
</a-scene>

You probably have some idea what it’s doing just from reading the tag names and properties. You can play around with this demo scene on CodePen and see how it works. I changed the sphere to purple by changing just one property and I felt a rush of power. I then looked through the API docs to see how else I could bend these entities to my will.

Built-in entities are made up of simple shapes like spheres, cylinders, boxes and other things called primitives. This terminology and other terms and concepts used in A-Frame will be familiar to anyone who has used 3D modelling software. If you are not familiar with any of these concepts, it might be worth reading about the Entity-Component-System pattern that A-Frame uses. I knew just enough about this that this didn’t feel completely strange.

Although you could make an extensive scene using only default primitives, the power quickly went to my head and in less than 30min I had popped the hood and started digging into how A-Frame works. A-Frame is built on top of three.js and each of the component encapsulates three.js and native JavaScript code to build entities that can be used declaratively in HTML.

We can register our own components and build new primitives. There is an extensive API to do this. It’s actually not that hard. Pretty soon I knew enough to shoot myself in the foot. I quickly leant that when building components you shouldn’t use three.js to try and manipulate the scene directly, you want to leave composition of the scene up to A-Frame and build components in a way that plays nice with other entities so that you can layer up different components to create more complex objects. If you don’t keep this in mind there is a chance things are not going to play nice together.

Components, primitives and entities were the main concepts I had to get my head around in the first week. I’m sure I’ll be able to explain these better down the track as well as correct any mistakes I’ve made here but for now, I understand enough so let’s make something!

The creative

I set myself the objective of applying an initial mood to the scene, through the addition of just the sky and ground. This seemed like a fairly humble objective. I started looking through different images of landscapes and I was drawn to the style of landscape in Japanese art and anime. Here are a few examples I collected for inspiration:

mood images

These scenes all feel very tranquil yet still dynamic and interesting. I noticed that one thing they have in common is a limited color palette, perhaps this is a key tool for creating that feeling? I also noticed that light is a strong feature in each of these images and that I tended to choose examples with vivid orange and purple hues. So now I have some guidelines and idea I set out to create that feeling.

I chose the following colors:

To implement the sky I stole the sky gradient component from one of the example scenes on the A-Frame site. This is a simple WebGL shader that I was able to modify to suit my needs. I added some lights, a soft ambient light and a low directional light with stronger colours. The lights are default primitive objects in A-Frame.

Next I added some test objects so I could see the result of the lighting effects. I kept these in to provide a focal point for an otherwise empty scene.

Because I could not resist the need for some experimentation, I decided to implement animated water and not solid ground. I’ve made some cool water effects before using perlin noise and webGL and I was interested to see if I could port some of these to an A-Frame component.

I had some success but as is often the case, I’m not the first person on the internet to have an idea and as is usually the case I’m not the smartest. About a quarter of the way into making my component I found an A-Frame port of this three.js water shader along with a whole bunch of other awesome A-Frame examples. It wasn’t a simple drop in component, it had some bugs with not all properties correctly mapped and some strange clipping bugs but I was able to fix these well enough for my purposes, when I get chance to test this more I will contribute these changes back to the community.

My first attempt was not perfect. I’d over did the contrast and the strength of the water effects. This is easy to do in isolation the strong special effects like this look cool but I’m building the foundation of a scene and there needs to be room to grow. I pared everything back and I am much happier with the result.

I went through various iterations of minor details like the reflective level of surfaces, the opacity of the water and the levels of distortion reflections. In each case when adding features my first inclination was to over apply the intended effect. It always looked right, until the novelty of the special effect wore off.

In the end I went too far the other way and it was not until I tested it on a head set that I found on small screens (the poor quality one I had anyway) the sublty of effects can also lost. There is it seems a narrow sweetspot.

Getting this balance right was not easy, for me it was equally as hard to modify the shader code. I spent a lot of time tweaking values to get everything just right. I have to admit now that I am kind of nervous to hand this over to Una. She’s amazing and will do amazing things but I have become slightly emotionally invested in this scene now and I’m brimming with ideas for where it should go next. I’m scared and excited to let it go. I also want to hear where you think it should go, feel free share some ideas with Una or myself on twitter. We’d love to hear from you!

Finally, I’ve learnt heaps and have a scene with the desired mood, colors and features that I set out in my initial objective. That’s pretty good. It even looks something like what I had in mind! I admit I did take a few detours from my main objective, experimenting with ideas for my next turn.

I justified these by saying it was helping me learn how A-Frame works. That might be true but I had to put these experiments aside for future weeks and focus on my original goal. Maybe I will get to implement some of these or maybe Una will take it somewhere else.

@Una Tag, you're it!