Porting titles from PC and console to mobile can be a tricky process if you don’t have experience working on a mobile platform. The same is true when porting a title to the Oculus Quest, but with the additional challenge that the device is attached to someone’s face where mistakes are far harder to miss. Knowing how to properly optimize the assets of your project can be the difference between a smooth and enjoyable user experience and dropped frames with an overheating GPU. Recently Arm had the great pleasure of being able to present on VR Asset Optimization for the Oculus Start Program. The presentation covered a multitude of techniques that can help VR developers optimize different assets and projects. However, here are my top 5 key take-aways.
Even though textures are exported as PNG, JPEG, TGA, or PSD, they don’t stay in this format when the project runs. Each texture is converted to formats that are designed to be read faster on the GPU, cutting down on bandwidth, and taking less memory in VRAM. While there are lots of options available, the one I suggest for a mobile platform is ASTC (Adaptive Scalable Texture Compression). One of the greatest features of ASTC, which was developed by Arm and AMD, is that it offers a wide variety of options that gives you control over the quality of the compression. The different levels of block sizes can feel intimidating at first. So I suggest you start at 5x5 or 6x6, then scale the block size up for textures for assets that take up less view space. But be sure to experiment with different settings to find out what works best for your project!
Another option you can try in your project would be ETC (Ericsson Texture Compression). But this will often leave your textures with a higher memory footprint, a lower visual quality, and cost you performance at run time. To know more about ASTC, how to use it and the different ASTC encoder options (Arm released an upgrade to ASTC v2.0 encoder this August’20), please check here.
It’s not a surprise to learn that Geometry has a huge influence on performance. The fewer vertices a mesh has, the faster it can compute it. Keeping the vertex count of what’s being rendered can at times be at odd with the artistic vision of the project. This is where Level of Details (LoDs) can help.
LoDs will show lower poly versions of a mesh the further it gets away from the viewer. These models are made in advance and the distance they change is controllable. In more complex scenes where the user sees across a distance, this will help to keep the vertex count down and address another issue, Mirco Triangles. These are triangles that when fully rendered, measure 1-10 pixels. The GPU still needs to do all of the processing on these triangles, but they are actually not contributing much to the final image.
Mipmapping is just like LoDs, but textures! Mipmaps are copies of a texture that are saved at lower resolutions. Based on how much texture space a fragment occupies, an appropriate mip level will be selected when the texture is sampled by the GPU. At first glance, mipmaps seem a little strange. Copies of textures do increase their memory footprint. But in exchange you will improve GPU performance since it will not have to render full resolution images on objects that are far away from the camera. At the same time, it prevents the crunchy look of texture aliasing that comes from rendering a large texture to only a smaller set of pixels. When done in conjunction, Mipmaps and LoDs working together can really speed up the rendering of a scene.
As I mentioned earlier, the fewer vertices that make up a mesh, the faster a GPU can compute it. But even on low poly meshes, there can be issues that will make the GPU work harder. One of the most common of these are long thin triangles. These triangles are made up of two vertices that, when fully rendered, measure tens of less pixels apart, but have the third vertice a long distance away. The reason these cause issues is because a GPU processes pixels in multiple square blocks. This is a particular challenge for a normal triangle because the GPU has to perform calculations on multiple blocks, even though this triangle only occupies a small portion of the view space. The best option is to remove all long thin triangles and keep triangles as close to equilateral as possible. However, this isn’t always an option when LoDs are not being used to remove the triangles when they are further away.
Reducing aliasing for objects with alpha while keeping good performance is a challenge in VR. Alpha testing is a widely implemented form of Alpha compositing that is the default for some game engines. But it can produce server aliasing effects at the edges of objects. Alpha blending is an alternative, but without polygonal sorting it fails to render objects in order, and sorting is a very expensive operation.
Alpha to Coverage (ATOC) can help reduce aliasing by transforming the alpha component output of the fragment shader into a coverage mask and combining this with the multisampling mask. It then uses an AND operator to only render pixels that pass the operation.
The above image shows a basic alpha test on the left, and ATOC on the right. Even with a still image the difference in aliasing is noticeable. But the changes are far more noticeable when the images are in motion, which you can see here. While implementing this can sound rather intimidating, Arm has a simple guide based on what engine you are developing on.
Due to the multidisciplinary nature of VR projects, it’s very hard to pick just 5 tips to talk about. There is so much that goes into making a project great. This is just the tip of the iceberg when it comes to the optimization content you can learn. To learn more about optimizing geometry, textures, or shaders and materials be sure to check Arms Best Practices for Artists. For an even deeper dive into more VR, check out the Advanced VR graphics techniques for Unity with Unity project examples and Unreal with UE4 project examples. Everyone can lend a hand when it comes to optimizing awesome gaming experiences, so be sure to share with the rest of your team!