Wednesday, September 3, 2014

Titans of Space has been ported to Samsung GearVR

To me, Oculus and Samsung's partnership in bringing the GearVR into existence is pivotal in the rebirth of VR, especially when it comes to going mainstream, and I couldn't be more proud to be a tiny part of it as an early developer.

I thought I would go into detail of some of the challenges I faced while porting to the GearVR.  Since I did not create something from the ground up for mobile, and instead started with something that many are already familiar with, it was quite an undertaking to port the experience to a mobile device while still retaining the essence of the experience.  I had never touched an Android device beforehand, so it was all new. But, you know what they say about a deadline and a project!

While mobile devices today are getting more powerful by leaps and bounds, I quickly learned that porting something originally made for the PC to a mobile device and still have it run at 60 FPS was not an easy task. A lot of game systems required a rewrite, which I basically was going to do anyway so this was simply great motivation to get started.   It's just amazing to me that Unity can build games for a mobile phone using pretty much the same project that I've been using to build for PC's. To get things running fast though, Oculus provided a lot of helpful performance tips for the early developers. I ending up having to do several things:


1) Drop the vertex count way down. I started with 4.5 million vertices (across both eyes) and brought it down to 100K total (50K per eye). Had Carmack not explicitly said to target 50K per eye, I honestly never would have taken such a strict limitation seriously, but it really helped.  Most of the 4.5 million was in the cockpit detailing, the planets and stars, and the individual stars in the background. In Titans of Space for DK1, there are nearly 200K vertices used for rendering the background stars. This made them look pretty clean especially when zooming in, but definitely not an option for mobile. I stuck a custom LOD system on the planets and stars and tuned it the best I could to use the minimum number of vertices to give the appearance of a sphere at varying sizes and distances.

2) No more layered cameras. Before this, my usual approach was to render the cockpit on top of the "external" view of planets and space etc. That approach made it extremely easy to keep the player at the origin (to avoid jittery geometry), easy to keep the player at 1:1 scale (to avoid near plane clipping while also needing to have giant far clip planes for the planets and stars), and easy to decouple the ICD of each camera layer so that the player can feel like he's normal size but the surrounding space can feel huge even if it isn't huge within Unity's coordinate system.

 With those conveniences taken away, I redesigned it all to work with a single camera setup. This required reworking how the big stars are renderered at distance, it required implementing a floating origin, it required turning the individual stars into an actual pre-rendered skybox. Fortunately skyboxes finally work in VR as of Unity 4.5+ -- I just had to set up my own skybox rendering system to get a high quality cubemap (4K on a side), with real stars and milky way background lined up perfectly etc.

3) Pay attention to texture limits. No more 8K textures (which were only occasionally helpful anyway), and I had to be careful not to use too many uncompressed textures. Uncompressed textures are great for closeup detail with the zoom feature, and for normal maps that don't pop in and out, but they eat up a lot of storage space and memory, which are somewhat limited on a mobile device. I had to choose more carefully which textures to leave uncompressed.

4) Reduce draw calls down to ~100 or lower at any one time.  In Unity, things that share materials and don't move (static) can be batched, but there's not a whole lot that can be made static in Titans of Space now. The cockpit and everything in it used to be static and thus was very batchable, but not anymore due to not using layered cameras.  To make things worse, dynamic batching was broken for me on the mobile device for a few Unity versions and/or mobile SDK versions, and that forced me to be even more aggressive with this at the time.  I mainly addressed this by simplifying the cockpit and removing the debris field that surrounds the player.

5) Make shaders more mobile friendly.  There were a few nice-to-have features that I decided weren't worth the GPU cost, like having the limb of a gas giant ever so slightly translucent.  There's no point in having a giant, uh... gas giant be rendered on top of everything else as a transparent object -- the resulting overdraw hits fill-rate limits very easily so that had to go.  Planets like Earth also have a lot of overdraw. In the DK2 version, Earth has clouds that float above the surface, but the GearVR version just has the clouds combined with the surface texture.  The base of the cockpit is no longer translucent.  Lots of little compromises like that.

6) Figure out how to use one project to support both DK2 and GearVR. The Titans of Space project is about 5 GB in size and it's a huge pain to switch back and forth between Standalone PC and Android platforms, but I wanted to keep it all in one project as most of the changes I make for one platform apply to the other. However, there are a ton of details that differ, such as the level of detail in the cockpit, the nicer looking Earth vs the mobile-friendly Earth, certain options, etc.

I've kept a checklist of things to do every time I switch platforms, and I've automated other things via a central "is this a mobile build or not" checkbox and scripting defines.   There are some things I would do differently with the project knowing what I know now -- like making more use of prefabs to swap in and out depending on the platform rather than just activating/deactivating parts of the scene hierarchy.

In any case, the end result is, what you see on DK2 is what you see on GearVR, with the exception of a few changes to the cockpit and other easy-to-miss features that don't significantly impact the experience.


I learned a lot from the Oculus/Samsung partnership. Thanks to their combined wizardry, I have great hopes for compelling and rock-solid VR experiences on a mere mobile device. It's been both fun and maddening to watch /r/oculus speculate on the various rumors that had been swirling around. I have zero doubt that a new mainstream household activity has just come into being: taking the GearVR over to the couch to relax in VR. Also, being able to walk over to a family member (with device in hand) and say "hey check this [entirely other world] out" is cool too. :)