Unreal Engine 4: Anti-Aliasing on the Oculus Quest
Updated: Aug 14, 2020
This article is part of our series on “Designing for the Oculus Quest”, where we give our readers some tips, tricks and to-do lists on creating realistic, high-fidelity VR applications for the Oculus Quest.We strongly believe that in the accelerating landscape that is xR, it is important to pay it forward. We acknowledge that we would not be where we are were it not for the largesse of so many among the developers & designers in the xR community. These articles that we put up is attempt at paying back in kind.
Let’s take it for granted that you’ve found yourself here, on this page, reading this article, after having encountered more than a few artefacts (read "jagged lines") in your VR environment, particular along the edges of polygons or all across any thin-lines or grooves that are more than a few steps away from your immediate location.
To capture a user’s interest, and keep them “immersed” in your environment, it is crucial that you present them with a noise-free, distraction-free picture. Taking that as our gospel, you must rid yourself off those flickering, jagged lines, or risk giving your users a sub-par experience.
There are any number of filtering algorithms used to tackle this issue of anti-aliasing across the evolving world of computer graphics. While we recommend that you read them to truly appreciate the engineering behind graphical interfaces, we know you’re probably in a hurry for answers, so let’s not beat around the bush anymore!
General Guidelines for VR Level Design
Jumping straight into it, “Project Settings” is your first port of call when you begin to fix aliasing on your UE4 Oculus Quest project.
We’ve been using the most recent version of Unreal Engine (4.23), at the time of writing, so while some changes are expected version-to-version, the general principle remains the same.
Here are some mandatory to-dos as far as your “Project Settings” are concerned:
Plugins > OculusVR > Launch Oculus Performance Window – Select ‘Mobile’ in Target Platform and follow all the recommended settings. As good practice avoid messing around with the settings on your own; Oculus is notorious for seeing builds fail or not working as you’d expect them to, when they are dabbled with.
Plugins > OculusVR > Mobile > FFR Level – We would recommend either Low or Medium setting; this also helps in optimizing overall performance. A higher FFR will increase aliasing on the edges of the VR field of view.
Plugins > OculusVR > Mobile – Turn off Chroma Correction. This will give you accurate more representation of colors as you view your scene on the editor.
Project > Target Hardware – Select Mobile/Tablet & Scalable 3D or 2D. Editor will present you with some recommended changes.
Platforms > Android > Build – Make sure you have 'Support armv7’ and only one of these activated - either ‘Support OpenGL ES3.1’ or ‘Support Vulkan’.
Platforms > Android > Advanced APK Packaging > Package for Oculus Mobile Devices – Make sure you have Oculus Quest selected here.
A few additional points to make sure off:
Immersive Mode in Devices beyond KitKat to be enabled; if disabled, it causes immense aliasing all over the map.
Mobile HDR to be turned off, always.
Mobile Multi-View & Mobile Multi-View Direct to be turned on.
Post Processing, in general for the Oculus Quest, is big no-no. Expect massive frame-drops and rendering issues; and avoid it at all costs.
Try to keep Reflections, Real Time Shadows, Dynamic Materials and Particle Systems to a minimum and avoid Dynamic Lights. The lower processing overheads your project has, the better is its performance (ergo, fewer jagged lines!).
Pro Tip: Go to Settings > Preview Rendering Level and select Android ES3.1 or Vulkan (whichever is relevant to your requirement) to preview your map material, colours, and lighting exactly the way it would show on the Quest. However, do remember that this will not mimic performance on the Quest.
The more interactive you want to make your VR experience, the chances that you’ve had to use text-based elements usually go up. While we would love to tell you more about how to create intuitive, interactive, “hands-on” experiences while keeping text-based callouts to a minimum, that is an article for another day!
For today, just know that Stereo Layers are the most important, and straight-forward, components to help you create sharp, alias-free UIs. However, avoid over-using them in your scenes, and think carefully about the requirement of UIs in the first place – try to minimize their usage as far as possible. Avoid having many unique Widget Blueprints clustered together in your scene (thus ensuring that they don’t all appear within your FoV in one frame). Avoid Widgets that have translucent components, as they take a larger toll on performance.
Setting Up Stereo Layers on UE4
Create your Widget Blueprint first on the UMG Editor; please make sure you set the height and width of the UI before you start creating it - as shown in the image below.
Next create an Actor Blueprint for this widget; add a widget component and set the Widget Class as your Widget Blueprint and set the height and width on the Draw Size parameter exactly same as the one you set in the Widget Editor.
Now add a Stereo Layer Component and attach it to the root node; make sure the scale matches the widget component exactly, as shown in the image below.
Adjust the following settings in the Details panel linked to your Stereo Layer.
Rotate the Z-Axis of the Widget component by 180°, so that it faces the other way.
Now, in your blueprint editor, add the following code to your Event Tick node.
Follow all this, and you should be good to go! The edges, and text, on your UI should be significantly alias-free once you build your project to the Quest.
3D Models / Assets
Meshes that reside in your level can broadly be divided into two segments - static and dynamic. While preparing assets for a Quest experience you need to optimize for more than just Texture Size and Polycount. You must optimize for the number of meshes that are on your map, the number of material slots on those meshes and the number of unique materials the meshes are using (and hence referencing every frame). Try to combine all your static objects and their UVs into as few Texture-Atlases as possible. This is will immediately, significantly reduce your draw calls and you will see an uptick your frame rate.
Use the console command ‘Stat SceneRendering’ while playing your scene to track your total Draw-Calls.
As a rule, avoid having thin or extensively detailed meshes at distance; ideally, reduce anything that is at a distance to just a flat texture, without too many details, thin-lines or edges. Having detailed meshes more than 10 – 15 feet (at world scale) from the user usually ends up generating those jagged lines. Setting up a proper hierarchy of LODs is, therefore, key here.
Minimize the use of skeletal meshes, they are a heavier hit on performance than their static counterparts; and where skeletal meshes are unavoidable, optimize for the number of bones, the fewer the better.
Sometimes, the simplest, and optimized of meshes will alias just because there is another mesh in very close proximity, and thus falling within the periphery of your FoV. Also, remember overlapping faces are guaranteed to cause aliasing and jittering.
Try to avoid redundant complexities in your scene as much as possible, and always remember the limited maneuvering space you have processor overheads while building for the Quest. Incorporate as much simplicity in the framework of your level as possible.
Restrict Draw-Calls at any given time ~ 30-40 per frame.
Restrict Polycount at any given time ~ 75000 – 100000 per frame.
Keep UMG Widget/UI Elements to a minimum, use textures instead of UI components wherever possible and where UMGs are unavoidable, use Stereo Layers wherever you do not need Dynamic UI elements.
Combine the meshes, material slots and UVs; use Texture Atlases to minimize materials and meshes.
Last, but not least, don’t forget those all-important Project Settings (all the way at the top of this article!).