Compositor layers let you render certain forms of content such as text, video, or textures with higher quality than traditional eye-buffer rendering can achieve. To understand the benefits that compositor layers provide, and how you can use OVROverlay to implement them, let’s start by understanding the differences between compositor layers and eye-buffer rendering.
Eye-buffer rendering is widely used by Oculus apps to render scenes. The Oculus VR runtime allocates a swap chain, which contains a collection of eye buffers. It is a set of textures, and for each frame, the Unity app simply renders the contents of the scene into one of those textures. Under this scenario, the Unity client app is only responsible for rendering its contents into the swap chain. After that, it is VR runtime’s job to take the eye buffer content from the swap chain and perform the scan out operation to draw that content to the physical screen. This process is known as Timewarp.
Compositor layers are useful for displaying information, text, video, or textures that are intended to be focal objects in your scene. They are also useful for displaying simple environments and backgrounds to your scene.
The reason why compositor layers can provide higher visual quality is that it’s always advantageous to only perform Timewarp by sampling from a layer’s texture directly, as opposed to using the layer texture to first render to the eye buffers, and then performing Timewarp on the resulting eye buffer. A good example is video rendering. Therefore, layers can be thought of as a way of passing a texture directly to Timewarp, as opposed to using the texture to render to the eye buffers.
Objects and textures rendered as compositor layers also render at the frame rate of the compositor, the refresh rate of the HMD, instead of rendering at the application frame rate. Because of this, the compositor layers are less prone to judder and are ray-traced through the lenses. This improves the clarity of the textures or text displayed on them.
OVROverlay is a script available in the Oculus/VR/Scripts folder that enables the compositor layers.
OVROverlay supports up to 15 layers in a single scene. However, each scene cannot contain more than one cylinder and one cubemap layer per scene. If a compositor layer fails to render, only quads fall back and are rendered as scene geometry. Cubemaps and cylinders are not displayed at all. A common example is when you attempt to render more than the maximum number of compositor layers. If you need to support more than 15 objects, you can combine planar elements into a single RenderTexture and use a single OVROverlay layer.
The OVROverlay script contains several configuration settings.
Select the type of overlay. Options available are Overlay, Underlay, and None.
Set the depth of the layer. It is used to determine the ordering of layers in the scene. The overlay/underlay with smaller compositionDepth is composited in the front of the overlay/underlay with larger compositionDepth. For example, a scene with numerous overlays and underlays would be -
[Camera] (Overlay) 2 / 1 / 0 [Eyebuffer] -1 / 0 / 1 (Underlay)
Ignore composition depth. Check the No Depth Buffer Testing checkbox to ignore the composition depth.
You can chose to ignore the depth hierarchy in certain situations, like loading or pausing a screen overlay, and have your OVROverlay layer always render on top of the scene.
Note: It’s possible for an object that should be behind another object, in terms of distance from the camera, to be drawn in front because it is implemented as an overlay and you’ve chosen to ignore the composition depth. This sends conflicting cues about the depth of these objects, which can be uncomfortable.
Select the shape of the overlay layer. Options available are Quad, Cubemap, and Cylinder compositor layers.
Quad layers are a flat texture with four vertices. Most commonly used as a panel to display text or information in a scene.
Cubemap layers are textures that contain six squares to form a cube to surround an object. Most commonly used for reflections and background or surroundings of a scene. You can also use it for low overhead loading or startup scenes. See the Cubemap Screenshots page for more information about cubemaps.
Cylinder layers are a single texture that is wrapped around the camera in a cylinder. Most commonly used for curved UI interfaces.
Equirect layers are a single texture that is wrapped into a sphere and projected to surround the user’s view. Most commonly used for 360/180 video playback.
Offcenter Cubemap layers are cubemaps where the centroid is moved forward on the z axis 30 degrees, enabling higher fidelity, in terms of more pixels, in front of the user.
Fisheye sets up OVROverlay to display a fisheye image. You can adjust transform settings to change the FovX, FovY, Horizon, and Meridian of the Fisheye layer.
Associate the texture that you’d like to render on the the overlay layer. If you leave it as None, which is the default option, it uses the renderer.material main texture, if available.
Select if the content rendered to the overlay is dynamic, which means if the texture should be updated each frame while the overlay persists. This checkbox is automatically checked when a rendertexture is associated with the layer.
Select if you want to protect the layer with HDCP on Rift and L1 Widevine DRM on Oculus Quest.
For Oculus Quest: To enable support on Oculus Quest you must also render the OVROverlay layer as an External Surface and select Protected Content in Player Settings > Virtual Reality > Oculus.
Select the Is External Surface checkbox to identify that the layer will be used to pass through textures or video from an external Android Surface.
This feature allows the creation of Android Surface and lets Timewarp layer manage it. In your Unity project, you can create a quad overlay and render the Surface texture directly to the TimeWarp layer. For more information about rendering surface texture, go to the Animated Loading Screen tech note.
Use the External Surface Width and External Surface Height to define the size of the output.
When you select Cylinder or Offcenter Cubemap layer, you can define a single input texture that consists of both, the left and the right image. Set the texture as Left Texture. Do not set the same texture for both eyes.
Unchecking this box opens the Source Rects dialog where you can define how the left and right texture are positioned in the single input texture. ‘Monoscopic’, ‘Stereo Left/Right’, and ‘Stereo Top/Bottom’ presets are available for quick selection.
Override any global color settings for the layer. Select the Override Color Scale checkbox to set a Color Scale and Color Offset input.
Underlays depend on the alpha channel of the render target. Do the following to add underlays:
Set alpha to 1, if a scene object that should occlude an underlay is completely opaque. If the occluder is transparent, i.e., alpha 0<1), you must use
Underlay Transparent Occluder.shader from the VR/Resources folder.
Note: Overlays do not require any special handling for transparency.
Underlay Imposter.shaderfrom the VR/Resources folder to draw imposters in the delta space. Ensure you perform this operation after all opaque textures are drawn, but before the alpha. This allows the underlay to show through the empty space.
In the following example, most of the scene geometry is rendered to the eye buffer. The application adds a gaze cursor as a quad overlay and a skybox as a cubemap underlay behind the scene.
Take a note of the dotted sections of the eye buffer, indicating where OVROverlay has punched a hole to make the cubemap underlay visible behind scene geometry.
Check if the cubemap in the scene is transparent. If yes, use
OVRUnderlayTransparentOccluder, which is required for any underlay with alpha less than 1. If it is stereoscopic, specify two textures and set the size to 2.
The center of a cylinder overlay game objects is used as the cylinder’s center. The dimensions of the cylinder are encoded in
transform.scale as follows:
To use a cylinder overlay, your camera must be placed inside the inscribed sphere of the cylinder. The overlay fades out when the camera approaches to the inscribed sphere’s surface. Only half of the cylinder may be displayed, so the arc angle must be smaller than 180 degrees.
Offcenter cubemap compositor layers are useful for increasing resolution for areas of interest/visible areas by offsetting the cubemap sampling coordinate. They are similar to standard cubemap compositor layers.
Attach the OVROverlay script to an empty game object and specify the texture coordinate offset in the Position Transform field. For more information, see OVROverlay in the Unity Scripting Reference.
Overlay layers should almost always be world-locked, which means that they maintain their position with respect to the world behind it.
Overlays are world-locked by default. To make a head-locked overlay, make the layer (usually a Quad) a child of
OVRCameraRig center eye anchor.
We have listed a few common use cases for using compositor layers and different OVROverlay features.
It is extremely important for video playback apps to use compositor layers instead of rendering to the eye buffers that Unity ordinarily renders into.
There are two ways to use OVROverlay to display high quality video:
Lightweight loading screens can be added using two OVROverlay layers.
For more information, open the OVROverlay sample from the SampleFramework folder.
To add a gaze cursor or targeting reticle (or similar), add an OVROverlay quad to your scene as a child of the
OVRCameraRig center eye anchor.
We have demonstrated OVROverlay features in the OVROverlay Sample documentation. You can open the OVROverlay sample from the SampleFramework folder in Unity Editor.