Traversal + Node mask support and anaglyphic stereo example checked in:

144 views
Skip to first unread message

Robert Osfield

unread,
May 17, 2021, 11:10:08 AM5/17/21
to vsg-users : VulkanSceneGraph Developer Discussion Group
Hi All,

I have added support to vsg::Visitor, vsg::ConstVisitor, vsg::RecordTraversal for a uint32_t traversalMask and overrideMask members, and in scene graph utilization of these in vsg::View and vsg::MaskGroup respectively.  I have also added a anaglyphic stereo example to vsgExample to illustrate how to use them.

Changes checked into to the VulkanSceneGraph and vsgExamples:

Those familiar with the OpenSceneGraph will likely know about traversal and node masks already, in principle the VulkanSceneGraph equivalent behavior broadly the same, though the implementation details are a little different.  The key difference is that the OpenScenegraph has a NodeMask on all scene graph nodes, while the VulkanSceneGraph only has the mask on vsg::View and vsg::MaskGroup.

In the case of the OpenSceneGraph there is a test between the NodeVisitor::TraversalMask and Node::NodeMask every time any visitor vists a node, so incurs an:

     if ((visitor.getTraversaMask() & (node.getNodeMask() | visitor.getOverrrideMask)!=0)
     {
         visitor.apply(node):
     }

Even though the vast majority of nodes in the scene graph will have the default NodeMask of 0xffffffff while enables visitation in all circumstances.  This is expensive as it not only adds operations that the CPU has to do, but there are memory fetches and reliance on branch prediction, something that Intel copes OK with, but can really stall an AMD chip.

To avoid this overhead the VulkanSceneGraph limits the Node mask to vsg::View and vsg::MaskGroup, so the cost of evaluation the traversal and node mask is only paid when View nodes or MaskGroup are encountered in a traversal.  This essentially means the cost is zero when you don't actively use MaskGroup in your scene graph.  You only pay for what you use, rather than getting charged a tax just in case you might make purchase some point in the future.

In the case of vsg::View node there is check between the visitors traversalMask and the View's mask value so you can switch of a View by simply setting the mask to 0, or you can set it to mask value specific for that view, with the traversalMask of the traversal being &'d with visitor traversalMask for that subgraph.  This modified traversalMask that can used within the scene graph below to select different subgraphs by using a vsg::MaskGroup.

The vsg::MaskGroup is essentially a switch node that enables traversal of the child when with the test:

   if ((visitor.traversalMask & (child.mask & visitor.overrideMask)!=0)
   {
       child.node->accept(visitor);
   }

Note, we have the same logic applied as the used in the OSG case.  On both cases the overrideMask exists to enable visiting of even nodes/subgraphs that have been otherwise switched off.  This is useful for handling case like where an application is opened up with one of the View's switched off using a mask = 0x0, but the View has a subgraph you want to compile the Vulkan objects for, to the CompileTraversl needs to be able to override the disabling of the subgarph.

For now I've gone with a uint32_t mask, same as with the OSG, but potentially we could use a uint64_t.  Unlike the OSG we wont' see many vsg::MaskGroup in the scene graph so the extra costs in memory will likely be pretty small.

To illustrate vsg::View.mask and vsg::MaskGroup in action I've created a new example, vsganaglyphcstrereo:


This example creates two View's, one for each eye, and uses a custom GraphicsPipelineState to allow each view to have it's own ColorBlendState - so left eye gets enables just writing to Red channel, while the right eye writes to Green and Blue to give us the Red_Cyan stereo image.  Using the cessna.osgt from the OpenSceneGraph-Data:

   vsganalglyphicstereo OpenSceneGraph-Data/cessna.osgt

stereo_cessna.png

The to add use node mask's I added support for using stereo image pairs which can be specified on the command line:

     vsganalgyphicstereo -s textures/left_eye.jpg textures/right_eye.jpg

stereo_images.png

To avoid an questions of copyright took two photos with my phone with a quick homebuilt jig to my phone on the same horizontal and directional axis while I shift it horizontally by 6cms. 

The code required to set up the scene graph is:

    uint32_t leftMask = 0x1;
    uint32_t rightMask = 0x2;
...
            auto leftQuad = createTextureQuad(origin - offset * 0.5f, horizontal, vertical, leftImage);
            auto rightQuad = createTextureQuad(origin + offset * 0.5f, horizontal, vertical, rightImage);

            auto maskGroup = vsg::MaskGroup::create();
            maskGroup->addChild(leftMask, leftQuad);
            maskGroup->addChild(rightMask, rightQuad);

The code required to set up the view's with the same mask and to do a clear between drawing the left and right eyes:

    auto left_view = vsg::View::create(left_camera, vsg_scene);
    left_view->mask = leftMask;
    renderGraph->addChild(left_view);

    // clear the depth buffer before view2 gets rendered
    VkClearAttachment depth_attachment{VK_IMAGE_ASPECT_DEPTH_BIT, 1, VkClearValue{1.0f, 0.0f}};
    VkClearRect rect{right_camera->getRenderArea(), 0, 1};
    auto clearAttachments = vsg::ClearAttachments::create(vsg::ClearAttachments::Attachments{depth_attachment}, vsg::ClearAttachments::Rects{rect});
    renderGraph->addChild(clearAttachments);

    auto right_view = vsg::View::create(right_camera, vsg_scene);
    right_view->mask = rightMask;
    renderGraph->addChild(right_view);

The example also has a main vsg::Camera that the trackball controls, and two vsg::Camera that are relative to this:


    // create the left eye camera
    auto left_relative_perspective = vsg::RelativeProjection::create(perspective, vsg::translate(-shear, 0.0, 0.0));
    auto left_relative_view = vsg::RelativeView::create(lookAt, vsg::translate(-0.5*eyeSeperation, 0.0, 0.0));
    auto left_camera = vsg::Camera::create(left_relative_perspective, left_relative_view, vsg::ViewportState::create(window->extent2D()));

    // create the left eye camera
    auto right_relative_perspective = vsg::RelativeProjection::create(perspective, vsg::translate(shear, 0.0, 0.0));
    auto right_relative_view = vsg::RelativeView::create(lookAt, vsg::translate(0.5*eyeSeperation, 0.0, 0.0));
    auto right_camera = vsg::Camera::create(right_relative_perspective, right_relative_view, vsg::ViewportState::create(window->extent2D()));

The stereo camera setup is just a quick hack for now.  Some point in the future it might have sense for me to provide some convenience functions/classes to do stereo, and integration with OpenXR or other VR libs. 

I only have a early Occulus Rift headset that isn't supported by Linux any more so I can't play on the VR side, unless someone wants to send me a modern headset :-)

Cheers,
Robert.

qiuyao shen

unread,
Jun 2, 2021, 3:59:43 AM6/2/21
to vsg-users : VulkanSceneGraph Developer Discussion Group
Hi Robert,
 to set a node visible/invisible dynamically, do we also use this vsg::MaskGroup?
i.e.  create a vsg::MaskGroup and add soem nodes as its children, then set mask to 0 or 1 to toggle visible/invisable dynamically?

Cheers,
Steve.

Robert Osfield

unread,
Jun 2, 2021, 9:31:21 AM6/2/21
to vsg-...@googlegroups.com
Hi Steve,

On Wed, 2 Jun 2021 at 08:59, qiuyao shen <shenq...@gmail.com> wrote:
 to set a node visible/invisible dynamically, do we also use this vsg::MaskGroup?
i.e.  create a vsg::MaskGroup and add soem nodes as its children, then set mask to 0 or 1 to toggle visible/invisable dynamically?

You can use a vsg::MaskGroup or vsg::Switch to toggle nodes on/off.  MaskGroup and Switch have very similar interface and functionality, MaskGroup is a little more complex in that visiting of children is controlled by a combination of the child's mask and the traversalMask of the visitor that is traversing the scene graph.

MaskGroup is really useful where you want different views to show different parts of the scene graph as illustrated in the vsganaglyphicstereo example.  One might also use it for rendering different parts of the scene graph in a 3d view and a 2d mapview.

Cheers,
Robet.

qiuyao shen

unread,
Jun 3, 2021, 2:06:15 AM6/3/21
to vsg-users : VulkanSceneGraph Developer Discussion Group
Thanks Robert.

Cheers,
Steve.

Reply all
Reply to author
Forward
0 new messages