Optimizing Your Project for Higher FPS
Enhancing the performance and framerate of Unreal Engine VR applications, whether running standalone or streaming from a PC, can sometimes be challenging depending on the nature of your project. This guide will walk you through generic strategies that can significantly boost your project's performance and framerate with minimal effort.
Meta Quest Link Advanced Graphics Preferences
When streaming from a PC to Meta Quest devices, the default refresh rate is set at 72 Hz
. However, you can increase this to 120 Hz
, which not only enhances the refresh rate but also reduces the rendering resolution, potentially improving performance. Follow these steps to make the adjustment:
- Open the Meta Quest Link app and navigate to the
Devices
tab.
- Choose the device for which you would like to tweak the refresh rate.
- In the device settings, scroll down to the
Advanced
section and selectGraphics Preferences
.
- Choose your desired refresh rate. In this case select a refresh rate of
120 Hz
. After making your selection, clickOK
, and the Meta Quest Link app will restart to apply the changes.
- Once the Meta Quest Link app restarts, go back to the
Devices
tab, select your device, and confirm the refresh rate setting underAdvanced > Graphics Preferences
.
- Now, open your Unreal Engine project and navigate to
Project Settings
. UnderEngine > General Settings > Framerate
, you can fine-tune and experiment with the framerate settings to match your project's requirements.
HTC VIVE Specific Optimizations in Standalone Mode
Headsets like the HTC VIVE Focus 3 and Focus Vision have larger framebuffers, higher eye-buffer size, wider fields of view (FOV), and varying refresh rates compared to HMDs like the Meta Quest series. As a result, performance can differ when running the same content across these devices.
Setting a Custom Pixel Density
If performance on the Focus 3 or Focus Vision is lower than on the Quest, we recommend adjusting the Pixel Density to approximately 0.8
(or a value suited to your content). This reduces the eye buffer size, and matches the resolution of Quest 2, hence increasing FPS:
Setting a Lower Refresh Rate
The ViveOpenXR
plugin provides various Blueprint functions to query the supported refresh rates and adjust the current refresh rate according to your needs:
But, before you'd be able to make these adjustments you have to enable the relevant settings by navigating to Edit > Project Settings > Plugins > Vive OpenXR
and ensure the Enable Display Refresh Rate
option is checked. This option enables the OpenXR extension XR_FB_display_refresh_rate
support which allows your application to dynamically adjust the display refresh rate in order to improve the overall user experience. Please note that You need to restart the engine to apply new settings after changing this setting.
In order to query all the available display refresh rates use the Blueprint function Enumerate Display Refresh Rates
:
At the moment with most devices it returns 75.0
and 90.0
hz values.
To change the current display refresh rate use the Blueprint function Request Display Refresh Rate
:
To obtain the current display refresh rate use the Blueprint function Get Display Refresh Rate
:
If you're looking to squeeze more performance out of your HTC VIVE HMD in standalone mode, consider lowering the target refresh rate from 90hz
to 75hz
. This can help reduce GPU workload and improve overall stability while still maintaining a somewhat smooth experience.
HTC VIVE Optimal Rendering Settings
As a last resort consider adding the following rendering settings to your project's DefaultEngine.ini
under the /Script/Engine.RendererSettings
section and experiment with them until you obtain your desired results:
[/Script/Engine.RendererSettings]
r.Mobile.DisableVertexFog=True
r.Mobile.AllowDitheredLODTransition=False
r.Mobile.AllowSoftwareOcclusion=False
r.Mobile.VirtualTextures=False
r.DiscardUnusedQuality=False
r.AllowOcclusionQueries=True
r.MinScreenRadiusForLights=0.030000
r.MinScreenRadiusForDepthPrepass=0.030000
r.MinScreenRadiusForCSMDepth=0.010000
r.PrecomputedVisibilityWarning=False
r.TextureStreaming=True
Compat.UseDXT5NormalMaps=False
r.VirtualTextures=False
r.VirtualTexturedLightmaps=False
r.VT.TileSize=128
r.VT.TileBorderSize=4
r.vt.FeedbackFactor=16
r.VT.EnableCompressZlib=True
r.VT.EnableCompressCrunch=False
r.ClearCoatNormal=False
r.ReflectionCaptureResolution=128
r.ReflectionEnvironmentLightmapMixBasedOnRoughness=True
r.ForwardShading=True
r.VertexFoggingForOpaque=True
r.AllowStaticLighting=True
r.NormalMapsForStaticLighting=False
r.GenerateMeshDistanceFields=False
r.DistanceFieldBuild.EightBit=False
r.GenerateLandscapeGIData=False
r.DistanceFieldBuild.Compress=False
r.TessellationAdaptivePixelsPerTriangle=48.000000
r.SeparateTranslucency=True
r.TranslucentSortPolicy=0
TranslucentSortAxis=(X=0.000000,Y=-1.000000,Z=0.000000)
r.CustomDepth=1
r.CustomDepthTemporalAAJitter=True
r.PostProcessing.PropagateAlpha=2
r.DefaultFeature.Bloom=False
r.DefaultFeature.AmbientOcclusion=False
r.DefaultFeature.AmbientOcclusionStaticFraction=True
r.DefaultFeature.AutoExposure=False
r.DefaultFeature.AutoExposure.Method=0
r.DefaultFeature.AutoExposure.Bias=1.000000
r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True
r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True
r.EyeAdaptation.EditorOnly=False
r.DefaultFeature.MotionBlur=False
r.DefaultFeature.LensFlare=False
r.TemporalAA.Upsampling=False
r.SSGI.Enable=False
r.AntiAliasingMethod=3
r.DefaultFeature.LightUnits=1
r.DefaultBackBufferPixelFormat=4
r.Shadow.UnbuiltPreviewInGame=True
r.StencilForLODDither=False
r.EarlyZPass=3
r.EarlyZPassOnlyMaterialMasking=False
r.DBuffer=True
r.ClearSceneMethod=1
r.VelocityOutputPass=0
r.Velocity.EnableVertexDeformation=0
r.SelectiveBasePassOutputs=False
bDefaultParticleCutouts=False
fx.GPUSimulationTextureSizeX=1024
fx.GPUSimulationTextureSizeY=1024
r.AllowGlobalClipPlane=False
r.GBufferFormat=1
r.MorphTarget.Mode=True
r.GPUCrashDebugging=False
vr.InstancedStereo=True
r.MobileHDR=False
vr.MobileMultiView=True
r.Mobile.UseHWsRGBEncoding=True
vr.RoundRobinOcclusion=False
vr.ODSCapture=False
r.MeshStreaming=False
r.WireframeCullThreshold=5.000000
r.RayTracing=False
r.RayTracing.UseTextureLod=False
r.SupportStationarySkylight=True
r.SupportLowQualityLightmaps=True
r.SupportPointLightWholeSceneShadows=True
r.SupportAtmosphericFog=True
r.SupportSkyAtmosphere=True
r.SupportSkyAtmosphereAffectsHeightFog=False
r.SkinCache.CompileShaders=False
r.SkinCache.DefaultBehavior=1
r.SkinCache.SceneMemoryLimitInMB=128.000000
r.Mobile.EnableStaticAndCSMShadowReceivers=True
r.Mobile.EnableMovableLightCSMShaderCulling=True
r.Mobile.AllowDistanceFieldShadows=True
r.Mobile.AllowMovableDirectionalLights=True
r.MobileNumDynamicPointLights=4
r.MobileDynamicPointLightsUseStaticBranch=True
r.Mobile.EnableMovableSpotlights=False
r.Mobile.EnableMovableSpotlightsShadow=False
r.GPUSkin.Support16BitBoneIndex=False
r.GPUSkin.Limit2BoneInfluences=False
r.SupportDepthOnlyIndexBuffers=True
r.SupportReversedIndexBuffers=True
r.LightPropagationVolume=False
r.Mobile.AmbientOcclusion=False
r.GPUSkin.UnlimitedBoneInfluences=False
r.GPUSkin.UnlimitedBoneInfluencesThreshold=8
r.Mobile.PlanarReflectionMode=0
bStreamSkeletalMeshLODs=(Default=False,PerPlatform=())
bDiscardSkeletalMeshOptionalLODs=(Default=False,PerPlatform=())
VisualizeCalibrationColorMaterialPath=None
VisualizeCalibrationCustomMaterialPath=None
VisualizeCalibrationGrayscaleMaterialPath=None
r.Mobile.AntiAliasing=3
r.Mobile.FloatPrecisionMode=2
r.OpenGL.ForceDXC=0
r.DynamicGlobalIlluminationMethod=1
r.ReflectionMethod=1
r.Shadow.Virtual.Enable=0
r.Lumen.TranslucencyReflections.FrontLayer.EnableForProject=False
Game User Settings and Engine Scalability Settings
Unreal Engine offers predefined graphics quality profiles known as Engine Scalability Settings, which can be easily adjusted to optimize performance. These settings can be modified directly within the Unreal Editor through the Settings menu on the toolbar or dynamically at runtime using code. Importantly, these settings are universal, meaning changes made in the Unreal Editor will apply to the game when run in PIE (Play In Editor) mode, and settings adjusted via code will also affect the editor itself.
note
The SenseGlove Unreal Engine Plugin includes specialized
console commands that allow you to switch
between different Engine Scalability Settings on the fly. Please note that
these commands require you to set up
SGGameInstance
and
SGGameUserSettings
.
In order to switch between various Engine Scalability Settings, you can use the Get Game User Settings
Blueprint function and then cast it to SGGameInstance
.
important
Unreal Engine's default Blueprint functions only allow you to set Engine
Scalability Settings to Low
or Epic
. To access the full range of settings,
SGGameUserSettings
extends Blueprint access to all Engine Scalability
Settings and includes hardware benchmarking to detect the optimal settings.
Therefore, it's essential to make
SGGameUserSettings
or a subclass of it the default Game User Settings class to utilize all these
features.
The following Blueprint code from the SGBasicDemo-OpenXR example scene demonstrates how to bind numeric keys 1
to 5
to set various Engine Scalability Settings, and key 0
to utilize hardware benchmarking to determine the optimal Engine Scalability Settings:
0
: Use hardware-benchmarking to determine the optimal Engine Scalability Settings.1
: Set Engine Scalability Settings toLow
.2
: Set Engine Scalability Settings toMedium
.3
: Set Engine Scalability Settings toHigh
.4
: Set Engine Scalability Settings toEpic
.5
: Set Engine Scalability Settings toCinematic
.
tip
The
SGBasicDemo-OpenXR
includes an example 3D widget actor that displays the current FPS and Engine
Scalability Settings. This widget can be placed within a VR scene and is
located in All > Content > Blueprints > UI > BP_FPS3DWidget
. The underlying
UMG widget can be found at All > Content > Blueprints > UI > WB_FPS
within
the Content Browser for the SGBasicDemo-OpenXR example scene.
Optimizing Unreal Projects for Mobile
We have the SGBasicDemo-OpenXR project, which has been optimized for mobile. You can explore the project configuration by reviewing the settings inside the Config
folder and compare them with your own project settings. In addition, here are some crucial guidelines and settings that you may want to adjust for further optimization:
General Rendering Settings
Forward Shading: Enable Forward Shading for better performance. It’s more efficient on mobile platforms.
Mobile HDR: Disable this setting. Mobile HDR can significantly affect performance, especially on lower-end devices.
Instanced Stereo: Enable this setting. It is a rendering technique used in Unreal Engine primarily for virtual reality (VR) applications. Its main purpose is to optimize the rendering process when creating VR experiences by reducing the workload associated with rendering two slightly different images for each eye.
Mobile Multi-View: Enable this setting. It is a rendering feature in Unreal Engine designed to optimize the performance of Virtual Reality (VR) applications on mobile devices, particularly when using VR platforms like Google Daydream or Samsung Gear VR. It is similar in concept to Instanced Stereo, but specifically optimized for mobile hardware.
Mobile Anti-Aliasing Method: Use FXAA (Fast Approximate Anti-Aliasing)
or MSAA (Multisample Anti-Aliasing)
. MSAA
is often preferred for mobile as it gives better visual quality without a huge performance hit.
Reflection Capture Resolution: Reduce this value (e.g., 128 or 256) to decrease the memory usage.
Texture Settings
Enable virtual texture support: Disable this setting.
Texture Streaming: Enable texture streaming to ensure textures load progressively, which helps in reducing memory usage.
Texture Quality: Lower the overall texture quality to Medium or Low depending on the target device capabilities.
Texture Compression: Use ASTC compression for Android to ensure the textures are optimized for mobile devices.
Lighting Settings
Use Static Lighting: Prefer static lighting over dynamic lighting for better performance.
Lightmap Resolution: Use a lower lightmap resolution (e.g., 32 or 64) for mobile to reduce memory usage.
Dynamic Shadows: Disable or minimize the use of dynamic shadows. If required, use CSM (Cascaded Shadow Maps) with low resolution and distance.
Distance Field Shadows/Ambient Occlusion: Disable these features as they are costly on mobile platforms.
Post-Processing Settings
Bloom, Lens Flares, and Auto Exposure: Minimize or disable these effects as they can be performance-intensive.
Screen Space Reflections: Disable this setting as it is costly in terms of performance on mobile devices.
Motion Blur: Disable this feature to save on processing power.
Materials and Shaders
Material Complexity: Use simple materials with few instructions and limit the number of textures and shader nodes.
Specular Highlights: Consider reducing or disabling specular highlights on materials to save on performance.
LOD (Level of Detail) Models: Ensure that LODs are set up correctly for all models, with appropriate reduction in polygon count for distant objects.
Level of Detail (LOD) Settings
Mesh LODs: Configure LODs for all meshes to reduce polygon count at distances.
Screen Size: Adjust screen size settings for LODs to ensure they switch at appropriate distances for mobile screens.
Engine Scalability Settings
Resolution Scale: Lower the resolution scale (e.g., 70% or 80%) to improve performance while maintaining visual quality.
View Distance: Set to Medium or Low to reduce the amount of detail rendered at long distances.
Shadows: Set to Low or Off for better performance.
Textures: Set to Medium or Low depending on the device’s capabilities.
Effects: Set to Low to reduce the complexity of visual effects.
note
See Game User Settings and Engine Scalability Settings for more details.
Physics and Collision
Physics Simulation: Limit the use of physics simulation where possible, as it can be expensive on mobile devices.
Collision Complexity: Use simple collision meshes instead of complex ones to improve performance.
Audio Settings
Sample Rate: Lower the sample rate to reduce memory usage and processing load.
Number of Audio Channels: Limit the number of audio channels used in the project to reduce CPU usage.
Rendering API
Vulkan vs OpenGL ES: Test your project with both Vulkan and OpenGL ES to see which provides better performance on your target devices. Vulkan often offers better performance but may not be supported on all devices.
Culling
Frustum Culling: Ensure that frustum culling is enabled to avoid rendering objects outside of the camera’s view.
Occlusion Culling: Enable occlusion culling to avoid rendering objects that are not visible due to being blocked by other objects.