Multi-Layer¶
Introduction¶
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.
Contents |
Prerequisite¶
In Unity Editor, go to Project Settings -> Wave XR -> Essence to import the Compositor Layer package.
How to use¶
Note
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.
Component Parameters¶
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). A GameObject for Underlay Alpha blending will be generated automatically during runtime.
Note
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: A curved rectangular layer.
Parameters for different layer shapes: (Read-only during runtime)
Quad:
Width
: Width of the quad layer (in meters).Height
: Height of the quad layer (in meters).
Cylinder:
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).
Note
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.
Note
When layers have the same render priority, the one initialized earlier by Unity MonoBehaviour will be rendered as a Multi-Layer.
Other Parameters¶
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.
Note
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.
Previewing Layers¶
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 APIs¶
The Composition Layer Components provides several APIs for dynamically changing Layer Dimensions. These APIs will check whether the new Layer Dimensions are valid, and return a boolean value accordingly (i.e. true means the dimensions are valid and are updated successfully, vice versa).
For Quad layers:
SetQuadLayerWidth(float inWidth)
: For updating the width of the Quad layer.SetQuadLayerHeight(float inHeight)
: For updating the height of the Quad layer.
For Cylinder layers:
SetCylinderLayerRadiusAndArcAngle(float inRadius, float inArcAngle)
: For updating the radius and arc angle of the Cylinder layer. A new arc length will be calculated automatically if the input values are valid.SetCylinderLayerRadiusAndArcLength(float inRadius, float inArcLength)
: For updating the radius and arc length of the Cylinder layer. A new arc angle will be calculated automatically if the input values are valid.SetCylinderLayerArcAngleAndArcLength(float inArcAngle, float inArcLength)
: For updating the arc angle and arc length of the Cylinder layer. A new radius will be calculated automatically if the input values are valid.SetCylinderLayerHeight
: For updating the height of the Cylinder layer.
Sample Code:
CompositionLayer compositionLayer; //An instance of the Composition Layer which dimensions will be changed
//For Quad layer
if (compositionLayer.SetQuadLayerWidth(/*Put width float value here*/))
{
//Width value is valid
}
if (compositionLayer.SetQuadLayerHeight(/*Put height float value here*/))
{
//Height value is valid
}
//For Cylinder layer
if (compositionLayer.SetCylinderLayerHeight(/*Put height float value here*/))
{
//Height value is valid
}
if (compositionLayer.SetCylinderLayerArcAngleAndArcLength(/*Put arc angle float value here*/, /*Put arc length float value here*/))
{
//Value combination is valid
}
if (compositionLayer.SetCylinderLayerRadiusAndArcAngle(/*Put radius float value here*/, /*Put arc angle float value here*/))
{
//Value combination is valid
}
if (compositionLayer.SetCylinderLayerRadiusAndArcLength(/*Put radius float value here*/, /*Put arc length float value here*/))
{
//Value combination is valid
}
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.
Sample Code:
CompositorLayerManager compositorLayerManagerInstance = CompositorLayerManager.GetInstance();
compositorLayerManagerInstance.MaxLayerCount();
compositorLayerManagerInstance.RemainingLayerCount();
compositorLayerManagerInstance.CurrentLayerCount();
Resources¶
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.
Debugging tools¶
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.