Skip to content

Additional Viewports Per Eye

oneMillionWorlds edited this page Mar 1, 2024 · 7 revisions

This is an advanced use case, allowing for overlay viewports to be applied to each eye that can render additional scenes to be overlaid on the main scene.

These overlay viewports are intrinsically drawn over (in front of) the primary viewport

HandWithOverlayViewport

Examples of when you might want to use this

  • Debug shapes (e.g. a physics engine might draw debug shapes to show where the physics objects truly are. Or the hand joints and attachment points might be rendered on the hand, as in this screenshot) that show without being occluded by the main scene.
  • A "seeing through walls radar" effect; where some outline of an object might be placed in the 3D world where the true object is and that gets overlaid on the main view.
  • A pause menu UI that should be rendered even if its technically occluded by the main scene

This is equivalent to the desktop scenario where you might do this

Viewport overlay = renderManager.createMainView("overlay", camera)
overlay.setClearFlags(false, true, false);
overlay.attachScene(overlayRootNode);

How you set up additional viewports

Call (once, probably in the initialisation of your application or an AppState xrAppState#addAdditionalViewport to give it the root node for this additional scene. It most likely won't be the root node, but an additional one for this scene

viewportConfigurator = xrAppState.addAdditionalViewport(AdditionalViewportRequest.builder(additionalRootNode).build());

The AdditionalViewportRequest builder can be given additional properties to configure how the viewport is produced, including

  • What type of viewport (pre, main, post)
  • What to clearFlags to use (colour, depth, stencil)
  • How to configure the viewport after creation (e.g. adding post processors)

The returned ViewportConfigurator has methods to change the viewport configuration (e.g. adding post processors) or remove it.

Note that just like all additional root nodes the node must be updated by user code, ensure the the following are called (after any spatial changes are made)

additionalRootNode.updateLogicalState(tpf);
additionalRootNode.updateGeometricState();

Why can't Tamarin just be given a viewport

Tamarin needs to fully own the viewport creation process, this is because there are actually 6 viewports (2 eyes triple buffered) that are used in sequence to properly talk to the OpenXr swapchain

Example

See AdditionalViewportExampleState for a full example of this