Switzerland in WebGL
September 1, 2015
Case study of Suisse Mania, the cutting edge WebGL-Experience for Migros. You'll find detailed background information and insights in how we worked and built Switzerland in 3D.
Migros is Switzerland’s largest largest employer and retail company. More importantly, the brand is deeply rooted into the DNA of the Swiss people, everything they do gets a lot of attention. During a year, Migros publishes several campaigns and for the 8th time their flagship “Mania” launched. It’s massive and involves road shows, plastic models and stickers available in all 600+ Migros stores all over the country.
Just like the name says, a Mania is all about collecting and this time the theme was of course Switzerland. Everyone could collect 54 plastic models and stickers of famous buildings, attractions and areas. If you shop for at least CHF 20.- (swiss francs) in an Migros store, you’ll get a plastic model and a matching sticker with the purchase. The more you buy - the more you get.
We wanted to create an online experience, where users can seek after those same objects in a playful way. It was clear to us from the very beginning, it had to be a cutting edge 3D-Experience of Switzerland - The question was how?
Probably the biggest decision which affected how the whole project would be structured was how we would build Switzerland and integrate the collectibles. We had two concepts:
- One solution was to create separate scenes for every single collectible, and a general low poly map from which you could navigate into those 54 scenes. This concept would allow us to control loading behaviour and time, but moreover we would have almost no performance issues. Proof of Concept: Scene 1 / Scene 2).
- The other option was to combine everything into one massive scene.
As you might have noticed, we chose the massive scene. It sounded more like a challenge to us and felt more like a game. We imagined how amazing it would be to fly freely through the clouds over that huge landscape without any loading interruptions. The vision was there, so we had to dive into the Wireframing and Design part where we structured the content, thought about gamification-elements and the navigation.
Suisse Mania is all about the journey through Switzerland. In a workshop with Migros we decided that the balloon should be the campaign's main carrier. Everyone love balloons, right? So it was clear that we would implement it somehow in the experience. One idea was to navigate the balloon itself around Switzerland and that the user had to land on specific areas to explore them. For better usability and to make things simpler we fixed it on a defined spline which guides the user through the most important areas.
We dismissed several great ideas like for example “Live Lighting”, which would emulate day/night with a Sky Shader according to the user's local time. At the end we realised that it was too expensive, so we baked light and shadows instead. There were lots of compromises like this and we made some very good but also some wrong decisions. After all, the whole project was a big journey and most importantly: We learned a lot!
Art Direction & UX
It’s a game for kids and that’s why we wanted to create this perfect fairy tale of Switzerland with shining white mountains, blue lakes and Tele-Tubbie-like flatlands with cornfields, tractors and animals. By using icons and large buttons we made it accessible and easy to use on both computers and mobile devices. Since “Suisse Mania” is a 3D-game it was very important how you experience and navigate it. Intentionally we avoided creative interactions and tried to focus on common behaviour like dragging and zooming. But on top you can also use the arrow keys to fly or double-click to jump to a location, which feels quite nice.
We had multiple people working simultaneously on different fields of the 3D world like Modelling the terrain, the main objects and environmental objects. If you count everything together we got an unbelievable amount of over 500k faces in the final scene, which is incredible if you consider that the app also runs on mobile devices.
Before going into the modelling part we first defined which lakes, mountains and roads should be highlighted, where bridges should cross rivers and also on what levels the main lakes have to be. You can see that in the Topographic Guide we’ve created. To start with the map model, we first thought of using real heightmap data of Switzerland, import it into Maya and then modify the mesh to our needs. Unfortunately that attempt failed, it was just too detailed and we couldn’t soften and simplify the mesh like we imagined, we always got an undefined dough mesh. Especially in the most important alpine parts. So we had to do a lot more manual work than we thought. It was a long and tough process getting that mesh done, but at the end we could achieve that playful version of Switzerland we all wanted.
The scene includes 54 main and a lot of environmental objects. In total there are over 100 different models such as trees, cars, fields and animals scattered throughout the map. The main objects had to stand out of the environment and be visually more appealing so the user can recognise it as a game element. Keeping the polycount deep was key, after some objects were place i.e. trees, we merged all of them together and tried to combine and simplify as much as possible. But we recognised that optimising textures had a bigger impact on download time and performance. On a project like this, you can literally work forever and always create new objects and optimize it.
Another very cool thing is the Splatmap shader for the terrain. It uses 6 different channels in a “Splatmap” texture to blend other textures in a layered manner. The result is higher quality texturing. The alternative is rendering a very high-res texture for the whole terrain, but that would not work on all devices.
By using a special shader for the terrain mesh, we could get higher quality textures. The shader takes the big “splat map” texture and a number of smaller textures as an input. The splat map’s red, green and blue channel define how much of texture1, texture2 and texture3 to use at the current pixel, respectively.
A very important part of the project is sound. All landmarks have their very own ambient sound which is looped in the background while the off-speaker is telling insights and stories about it. These recordings were made in German, French, Italian and English. Next to the Suisse Mania Alphorn-Theme which you can hear while flying with the balloon we implemented environmental sounds if the user zooms closer into the world. You can hear birds singing, splashing water, wind and city noises. And all of this in a real 3D sound environment, that means the volume changes according to the user's position on the map and also the direction he is viewing.
On top of that we produced Click-Sounds for a variety of environmental objects like buildings and animals. So if you clicked on a pig it would grunt and a doorbell of a houses would ring. Unfortunately, we had to accept that it is not possible because of some technical limitations. There would’ve been just too much clickable hotspots which made the experience laggy and unusable.
Versions & Fallback
We made three different experiences to reach as many people as possible with a broad range of devices. There are two grades of the WebGL-App, an HD-Version with high quality textures and effects and a SD-Versions with smaller resolution. In addition to that we created an 2D-Version that we used as a fallback for devices and browser which don’t support WebGL. The HD version was always the main one that we’ve worked on, and the SD scene was created automatically from it.
Next to a Whitelist which decided whether you launch HD or SD in the first place, the app is monitoring the framerate all the time. If you’re in HD and the framerate drops below 30fps, we used a trick and rendered the WebGL canvas 50% of the size and zoomed in again with CSS so the GPU has to render less pixels. If that still doesn’t help, a notification pops up where you can switch to SD for a smoother experience. In that way we could prevent to place a switch-page with 3 buttons before the pre-loader. So you can directly jump into the experience.
This is the best experience with all the juicy features for high-end devices like Depth of field, moving clouds, camera drifting, animations and of course higher texture-size.
Reduced experience where we shut down expensive features and shrank texture size and count. As mentioned the SD Version is based on the HD, the flow for creating it was:
- Export the HD scene from Goo Create.
- Batch resize all images using command line tools.
- Import the scene in Goo Create again.
This version ensured that also users with older devices and browsers supporting everything down to IE9. Instead of using WebGL, we generated a huge flat image (60Mio pixels) which was then processed further to over 4000 tiles. The user can pan and zoom seamlessly through those tiles, and everything else stayed the same. Try it out yourself: 2D-Fallback
As per usual we turned to our trusty Google App Engine for the scalability it provides. It stood by us once again and when Migros sent out over a million newsletters to their subscribers the site performed flawlessly despite a couple of thousand simultaneous users.
This was our first larger project using Goo Create to power the experience. With their engine we got a very easy workflow of prototyping and deployments. The guys at Goo really showed us the power of their tool and we had a blast working together with these talented people.
In general, we used JPG for textures and visuals that didn’t need transparency and PNG for the rest. Both these image formats are supported on all our target platforms. To reduce size of the images, we processed them using TinyPNG.
During the project we had a period of time where the app was very unstable because of the lack of optimisations. It had many megabytes of textures and mesh that easily could be stripped off or combined - it wasn’t just done yet.
What we learnt here is that all sorts of strange glitches happen when phones run out of memory. Some Android phones showed black instead of textures. CSS animations glitched. None of these things were really a blocker, with the exception of iOS Safari. When it runs out of memory it just crashes. This prevented us from testing the app in iOS for a period of time, which was bad.