Optimizing Medusa’s Labyrinth VR

 

With the release of Medusa VR closing, I wanted share some thoughts about optimizing. One of the big task for adding support for VR was optimizing the game while keeping the visual quality. Due to having to render everything once per-eye, we needed to push the optimization even further. With Medusa VR we are targeting 90 fps, about 10 ms, with a GTX 970. Lots of reasons why you want 90 fps for a VR game, but let’s just say low frame rate makes people motion sick.

Some good resources: Super Bunnyhop video: https://youtu.be/x3mMc_0_UtU
http://www.gamasutra.com/blogs/KrisGraft/20160624/275803/Heres_probably_why_VR_made_you_sick_at_E3.php
http://www.gamasutra.com/view/news/282708/PlayStation_VR_has_its_limitations_but_devs_shouldnt_ignore_Sonys_VR_entry.php

Profiling

I started with finding the most performance intensive locations. Console command “Stat UnitGraph” shows calculation time for CPU and GPU, with a nice realtime graph making it easy to see hiccups.

The most expensive location was in the first area, below the stairs looking at the temple, showing at most 21 ms.

If the first step is to find where the game slows down, the second step is finding out why. The most useful tool I found, for figuring out why, was the GPU visualizer (console command “PROFILEGPU”).

The GPU visualizer gives you a snapshot of what the GPU is doing during a frame and the duration for calculating each component. The most expensive component was dynamic lights by far and in Medusa there’s a lot of dynamic lights, every source of fire has a animated light with it. The first compromise I needed to do was to turn off dynamic shadows on all lights. I did leave dynamic shadows on for the light of the torch, because it’s an important tool the player use most of the game.

I did also find UE4´s “Optimization viewmodes” to be incredibly useful for profiling the game.
https://docs.unrealengine.com/latest/INT/Engine/UI/LevelEditor/Viewports/ViewModes/

Epic have some amazing documentation about profiling: https://docs.unrealengine.com/latest/INT/Engine/Performance/index.html

Draw calls

Using console command “Stat Scenerendering” you can see the total amount of draws call during any given time. I usually try to get under 6000 draw calls, but for VR I wanted to go even lower.

I used UE4 Merge Actor (Window – Developer Tools – Merge Actors) to reduce draw calls. By merging all the stones to a couple of clusters, merging props of same type together and merging all the props on the stair, I was able the keep amount of draw calls under 1000.

Settings

UE4 has a lot of good console command you can use to tweak various settings to improve performance. In Medusa we changed them depending on what “Graphics setting” is selected.

You can use the Blueprint node “Execute console command” to easily use console command.

Some of the console commands we used in Medusa:

  • sg.ShadowQuality
  • sg.EffectsQuality
  • r.PostProcessAAQuality
  • foliage.DensityScale

While using optimization viewmodes I did find that there was a lot of shader complexity in the foliage, because of the overlap of transparent objects. Lowering “DensityScale” did improve performance while the change being barely visible.

Level of Detail

Lod (level of detail) is an old technique were closer objects are rendered with more detail than objects that are farther away. Even if the tris count wasn’t a bottleneck, UE4´s “One button solution” made the optimization almost free to do.

Further reading: https://docs.unrealengine.com/latest/INT/Engine/Content/Types/StaticMeshes/HowTo/LODs/

So with a few simply techniques and a couple of comprises I was able to get a solid 10 ms, on a GTX 970. If your looking forward to play Medusa’s Labyrinth in VR you can wishlist it right now! http://store.steampowered.com/app/624560/Medusas_Labyrinth_VR/

Medusa’s Labyrinth VR is going to be out the 24 May for Oculus and Vive.

/Johannes