Performance-Tuning a WebVR Game

For the past couple of weeks, I have been working on the VR version of one of my personal favorite puzzle games, the Nonogram , also known as Picross or Griddlers. They are puzzles where you must figure out which usually cells in a grid are coloured in by using column and line counts. I thought this would be perfect for an excellent, relaxing VR game. I call it up Lava Flow .

Since Lava Flow is meant to become a casual game, I want it to launch quickly. My goal is for the whole online game to be as small as possible and insert under 10 seconds on a 3-G connection. I also wanted it to operate at a consistent 60 frames per second (fps) or better. Consistent frame price is the most important consideration when developing WebVR applications.

Measure 1st

Before I can enhance the performance or size, I need to understand where I’ m starting. The easiest method to see how big my application is really is to use the Network tab of the Firefox Developer equipment. Here’ s how to use it.

Open up the Network tab of Opera developer tools. Click disable cache, then reload the page. At the end of the page, I can see the overall page size. When I started this particular project it was at 1 . 8MB.

My application utilizes three. js , the popular open up source 3D library. Not surprisingly, the largest thing is three. js by itself. I’ m not using the minified version, so it’ s more than 1MB! By loading three. min. js instead, the size is now 536KB vs 1110KB . Less than 50 % the size.

The game utilizes two 3D models of rocks. They are in GLB format, which is compacted and optimized for web use. My two rocks are already weighing within at less than 3KB each, therefore there is not much to optimize right now there. The JavaScript code I’ ve written is a bunch of small documents. I could use a compressor later to lessen the fetch count, but it’ s not worth worrying about however.

Image compression

The next biggest resources would be the two lava textures. They are PNGs and collectively add up to 561KB.

I re-compressed the 2 lava textures as JPEGs along with medium quality. Also, since the bundle map image doesn’ t have to be as high resolution as the color structure, I resized it from 512× 512 to 128× 128. That will dropped the sizes from 234KB to 143KB and 339KB in order to 13KB. Visually there isn’ big t much difference, but the page is currently down to 920KB.

The following two big things are a JSON font and the GLTFLoader JavaScript collection. Both of those can be gzip compacted, so I won’ t worry about all of them yet.


Now let’ s enjoy the game and make sure everything remains working. It looks good. Wait around, what’ s that? A new system request? Of course , the audio files! Requirements isn’ t triggered until the 1st user interaction. Then it downloads more than 10MB of MP3s. Those aren’ t accounted for by the DefaultLoader because I’ m launching it through audio tags rather than JavaScript. Gah!

I actually don’ t really want to wait for the backdrop music to load, however it would be wonderful to have the sound effects preloaded. Plus sound elements don’ t have the manage I need for sound effects, nor could they be 3D-capable. So I moved those to become loaded as Audio objects with the AudioLoader within three. js. Now they may be fully loaded on app begin and are accounted for in the download period.

With all of the audio (except the background theme), everything is second . 03 MB. Getting better.


There is a strange glitch where the whole scene breaks when rebuilding the game board. I have to figure out what’ s going on generally there. To help debug the problems, I need to view the frames per second inside of VR Immersive setting. The standard stats. js module that most three. js applications use actually works by overlaying the DOM element on top of the WebGL canvas. That’ s fine usually but won’ t work whenever we are in immersive mode.

To address this, I created a small class called JStats which draws stats to a little square anchored to the top of the VR view. This way you can see it all time inside of immersive mode, no matter what path you are looking.

I also created a simple timer course to let me measure how long a specific function takes to run. After a small testing, I confirmed that any where from 250 to 450 msec is needed to run the setupGame function that occurs every time the player gets to a new degree.

I dug to the code and found two items. First, each cell is using its copy of the rounded rectangle angles and material. Since this the exact same for every cell, I can just make it once and reuse this for each cell. The other thing I recently found is that I’ m creating the written text overlays every time the level changes. This particular isn’ t necessary. We just needs one copy of each text item. They can be reused between levels. Simply by moving this to a separate setupText function, I saved several 100 milliseconds. It turns out triangulating text is extremely expensive. Now the average board set up is about 100 msec, which shouldn’ t be noticeable, even on a cellular headset.

As a last test I used the network keep track of to throttle the network right down to 3G speeds, with the cache impaired. My goal is for the screen in order to first be painted within one second and the game ready to enjoy within 10 seconds. The system screen says it takes 12. thirty six seconds. Almost there!

Two steps forward, one take a step back

As I worked on the overall game, I realized a few things had been missing.

  • There ought to be a progress bar to indicate the fact that game is loading.
  • The tiles need sound effects whenever entering and exiting the mouse/pointer.
  • There should be music every time you complete a level.
  • The particular splash screen needs a cool typeface.

The improvement bar is easy to build because the DefaultLoadingManager provides callbacks. I actually created a progress bar in the CODE overlay like this:

< progress id="progress" value="0" max="100"> < /progress>

Then up-date it whenever the loading supervisor tells me something is loaded.

THREE. DefaultLoadingManager. onProgress = (url, loaded, total) => 


Combined with some CSS design it looks like this:

Battling bloat

Next up can be music and effects. Adding the additional music is another 133KB + 340KB, which bloats the app upward nearly another half a megabyte. Uh oh.

I could get a little bit of that back along with fonts. Currently I’ m making use of one of the standard three. js fonts which are in JSON format. This simply not a terribly efficient format. Documents can be anywhere from 100KB to 600KB depending on the font. It turns out three. js can now load TrueType fonts straight without first converting to JSON format. The font I selected was called Hobby of Evening by deFharo, plus it’ s only 80KB. Nevertheless , to load TTF file requires TTFLoader. js (4KB) and opentype. minutes. js which is 124KB. So I’ m still loading more than prior to, but at least opentype. min. js will be amortized across all of the fonts. It doesn’ t help these days since I’ m only making use of one font, but it will help later on. So that’ s another 100KB or so I’ m using up.

The lesson I’ ve learned today is that optimization is definitely two steps forward and one take a step back. I have to investigate everything and invest the time polishing both the game plus loading experience.

The overall game is currently about 2 . 5MB. Utilizing the Good 3G setting, it takes thirteen. 22 seconds to load.

Audio revisited

Once i added the new sound effects, I thought associated with something. All of them are coming from FreeSound. org which generally provides them within WAV format. I have used iTunes in order to convert them to MP3s, but i-tunes may not use the most optimized structure. Looking at one of the files I discovered it had been encoded at 192KBps, the arrears for iTunes. Using a command collection tool, I bet I could shrink them further.

I actually installed ffmpeg and reconverted the 30-second song like this:

ffmpeg -i piano. wav -codec: the libmp3lame -qscale: a 5 keyboard. mp3

It proceeded to go from 348KB to 185KB. That’ s a 163KB savings! As a whole the sounds went from 10MB to 4. 7MB, greatly decreasing the size of my app. The total down load size to start the game without the music is now 2 . 01MB.

Sometimes you get a freebie

I loaded the game to my internet server here plus tested it on my VR headsets to make sure everything still functions. Then I tried loading the public edition in Firefox again with the system tab open. I noticed something strange. The total download size is smaller! Within the status bar it says: second . 01 MB/1. 44 MB moved. On my local web machine where I do development, it states: 2 . 01 MB/2. 01 MEGABYTES transferred. That’ s a huge distinction. What accounts for this?

I believe it’ s because my community web server does gzip compression setting and my local web machine does not. For an MP3 file this particular makes no difference, but for extremely compressible files like JavaScript it could be huge. For example , the three. min. js file is 536. 08KB uncompressed but an astounding 135. 06KB compacted. Compression makes a huge difference. And now the particular download is just 1 . 44MB, plus download time over Good 3-G is 8. 3 seconds. Achievement!

I normally perform all of my development on the nearby web server and only use the community one when the project is prepared. This a lesson to look at everything plus always measure.

In the long run

These are the classes I learned while tuning our application. Making the first version of the game is easy. Getting it ready for discharge is hard. It’ s a long slog, but the end results are so worth it. The between a prototype and an online game is sweating the little details. I really hope these tips help you make your own great WebVR experiences.

I am an author, specialist, and recovering engineer. Formerly to the Swing Team at Sun, the particular webOS team at Palm, plus Nokia Research. I spread the term of good user experiences. I reside in sunny Eugene Oregon with my spouse and genius Lego builder kid.

More articles by Josh Marinacci…

If you liked Performance-Tuning a WebVR Game by Josh Marinacci Then you'll love Web Design Agency Miami

Add a Comment

Your email address will not be published. Required fields are marked *