Multi-Layer is a feature that leverages the Wave Multi-Layer Rendering Architecture to display textures on layers other than the eye buffer which Unity is rendering to.
Textures displayed using Multi-Layer have a better visual quality since the texture is sampled directly from the source texture when performing Asynchronous Timewarp (ATW), instead of rendering it to the eye buffer first, and then performing ATW.
We recommend using Multi-Layer to display textures of the main subjects in a scene, such as video and text, as it will provide a better user experience.
In Unity Editor, go to Project Settings -> Wave XR -> Essence to import the Compositor Layer package.
How to use¶
Not all devices support Multi-Layers (e.g. VIVE Focus or VIVE Focus Plus do not support this feature).
For devices that do support Multi-Layers, the maximum number of layers allowed can be obtained by calling the Native API WVR_GetMaxCompositionLayerCount() through the Wave Native API C# wrapper. Different devices may have different max layer counts.
The API will return zero on a device that does not support Multi-Layers.
To use Multi-Layer in your project, simply attach a Compositor Layer Component onto a Game Object in your scene and configure the related parameters listed below.
Layer Type: Select the type of the layer.
- Overlay: Displayed on top of the eye buffer, will not be occluded by objects rendered to the eye buffer.
- Underlay: Displayed underneath the eye buffer, can be occluded by objects rendered to the eye buffer (might not be compatible with transparent shaders that does Alpha blending).
Generate Underlay <LayerShape> Mesh : Available when Underlay is selected as Layer Type
- The component will generate an underlay mesh using the current layer parameters. This is necessary for displaying an underlay as the mesh has a material with a custom shader on it which is responsible for punching a hole in the eye buffer to make the Underlay visible.
Using Underlay will introduce a slight performance overhead when compared to Overlay since a custom shader is needed for a special blending operation in order to make the Underlay visible.
Composition Depth: Determines the rendering sequence of layers. The layer with the smallest composition depth will be rendered first. Here is an example of how the rendering sequence of the layers can be interpreted:
Layer Shape: Select the shape of the layer.
- Quad: A flat rectangular layer that resembles a quad primitive in Unity.
- Cylinder(Experimental): A curved rectangular layer.
Parameters for different layer shapes:
Width: Width of the quad layer (in meters).
Height: Height of the quad layer (in meters).
Radius: The radius of the full cylinder formed if the curved surface wraps around in a full circle (in meters). You can adjust the curvature of the layer by changing the radius.
Locked Parameter: Choose to lock the value of Arc Length or Arc Angle when adjusting the radius. Locks Arc Length by default.
- Lock Arc Length: Use this option when you want to maintain the aspect ratio of the layer (Aspect ratio = Arc Length : Height)
- Lock Arc Angle: Use this option when you want to maintain the solid angle of the layer when viewed from the apex of the solid angle.
Arc Length: The arc length of the curved surface (in meters).
Arc Angle: The center angle of the arc of the curved surface (in degrees).
Height: Height of the cylinder layer (in meters).
To display the source textures without stretching them, the aspect ratio of the source texture and the layer should be the same. For Quad layers, the aspect ratio is Width : Height, while that of Cylinder layers is Arc Length : Height.
Left/Right Texture: The source textures of the layer. In most cases, both left and right textures should be the same unless you are trying to display special stereoscopic textures.
Dynamic Layer: Determines whether the texture content of the layer will be updated. Select this option if the texture content will be altered(e.g. the texture is a video), disable it to preserve performance otherwise.
Render Priority: The rendering priority of the layer. When Multi-Layer auto fallback is enabled in WaveXRSettings , layers with a higher render priority and are within the maximum layer count will be rendered as Multi-Layers, while the others will be rendered in Unity.
For example, if the max number of Multi-Layers supported is 3 and there are 5 Compositor Layer components simultaneously, the three layers with higher render priority will be rendered as Multi-Layers and the remaining 2 layers will be rendered in Unity.
When layers have the same render priority, the one initialized earlier by Unity MonoBehaviour will be rendered as a Multi-Layer.
Head-lock Layer: Normally, a layer is placed in a fixed location in the world space. To lock the layer to a position in head space(i.e. the layer will follow the headset), simply place the Game Object that the Compositor Layer component is attached to under the Main Camera Game Object as a child object.
Position: The position of a layer is determined by the transform position of the Game Object that the Composition Layer component is attached to.
Rotation: The rotation of a layer is determined by the transform rotation of the Game Object that the Composition Layer component is attached to.
The position and rotation of a layer is applied to its origin. The origin of a quad layer is the center of the quad, while that of a cylinder layer is the center of the full cylinder formed if the curved surface wraps around in a full circle.
You can preview your layer in the Editor Scene View by selecting Show <LayerShape> Preview and hide it by selecting Hide <LayerShape> Preview.
Here are some examples to give you an idea on how your layer will look like in Scene View:
Compositor Layer Manager APIs¶
When using Compositor Layer components, a Compositor Layer Manager will be created automatically in the scene. This Manager provides a few APIs for you to access information about layer count.
CompositorLayerManager.GetInstance(): Static method for retrieving the current Compositor Layer Manager instance.
Use this method to retrieve the Manager instance before calling the other APIs.
MaxLayerCount(): Returns the max number of layers supported on the current device.
RemainingLayerCount(): Returns the number of layers that can be created.
You should use this function to check the remaining number of layers available for you to create if you plan to create new layers during runtime.
CurrentLayerCount(): Returns the number of created layers.
CompositorLayerManager compositorLayerManagerInstance = CompositorLayerManager.GetInstance(); compositorLayerManagerInstance.MaxLayerCount(); compositorLayerManagerInstance.RemainingLayerCount(); compositorLayerManagerInstance.CurrentLayerCount();
The imported resources of the Compositor Layer Feature Pack can be found in Assets/Wave/Essence/CompositorLayer.
You can find scripts and shaders that the Multi-Layer feature uses, as well as sample scenes for your reference.
When Development Build in Build Settings is selected or you are previewing a scene in the Unity Editor Play Mode, you will gain access to the Multi-Layer debugging tools.
If a layer cannot be displayed, a debug placeholder will be generated according to the scale, position and rotation settings of the layer. The debug placeholder will show one of two warnings, listed below, as to why the layer cannot be displayed:
- Device does not support Multi-Layer: Shows when you are in Play Mode or the device your app is running on does not support Multi-Layers.
- Number of Multi-Layers exceeded max count allowed: Shows when layers cannot be created due to reaching the maximum number of layers supported. For example, if the device supports up to a maximum of three layers and your scene has four, the first three layers will be displayed normally and the fourth one will have a placeholder with the text Number of Multi-Layers exceeded max count allowed on it.