Skip to main content
Up and Coming
June 23, 2013

OpenSceneGraph

I've started working on an integration with OpenSceneGraph (http://www.openscenegraph.org/) and although I don't have a Rift to test with yet what I've done looks pretty close to the Oculus World demo so I'm hoping I've done it right. If there are any OSG developers out there who could test out my code I'd really appreciate it. I found GLSL versions of the shaders in the OpenHMD project (http://openhmd.net/) which are referenced as vertexShaderSource and fragmentShaderSource. I based my work on the night vision effect example from the OpenSceneGraph Cookbook (http://www.packtpub.com/openscenegrap-3-for-advanced-3d-programming-using-api-cookbook/book) and my code uses the functions from that example to create the RTT & HUD cameras as well as the quads. The source is available at https://github.com/xarray/osgRecipes. I have pseudocode where the scene is added to the cameras (step five in the cookbook) and where the cameras are added to the root node (step 7 in the cookbook) because I'm also integrating with a derived type of renderer but you should be able to replace them with what's in the example.




// Because I don't have a Rift yet I just made a OVR::HMDInfo and OVR::Util::Render::StereoConfig and guessed at some values.
myHMDInfo.HResolution = 1280;
myHMDInfo.VResolution = 800;
myHMDInfo.HScreenSize = 0.14976;
myHMDInfo.VScreenSize = 0.0935;
myHMDInfo.VScreenCenter = myHMDInfo.VScreenSize / 2;
myHMDInfo.EyeToScreenDistance = 0.05; //????
myHMDInfo.LensSeparationDistance = 0.03; //????
myHMDInfo.InterpupillaryDistance = 0.025; //?????????

myStereoConfig.SetHMDInfo(myHMDInfo);


const int textureWidth = myHMDInfo.HResolution / 2;
const int textureHeight = myHMDInfo.VResolution;

// Setup textures for the RTT cameras
osg::ref_ptr<osg::Texture2D> leftEyeTex2D = new osg::Texture2D;
leftEyeTex2D->setTextureSize( textureWidth, textureHeight );
leftEyeTex2D->setInternalFormat( GL_RGBA );
osg::ref_ptr<osg::Texture2D> rightEyeTex2D = new osg::Texture2D;
rightEyeTex2D->setTextureSize( textureWidth, textureHeight );
rightEyeTex2D->setInternalFormat( GL_RGBA );

// Initialize RTT cameras for each eye
osg::ref_ptr<osg::Camera> leftEyeRTTCamera = osgCookBook::createRTTCamera(
osg::Camera::COLOR_BUFFER, leftEyeTex2D.get());
OVR::Util::Render::StereoEyeParams leftEyeParams =
myStereoConfig.GetEyeRenderParams(OVR::Util::Render::StereoEye_Left);
osg::Matrixf leftEyeTranslation = osg::Matrixf::translate(
leftEyeParams.ViewAdjust.M[0][3], leftEyeParams.ViewAdjust.M[2][3],
leftEyeParams.ViewAdjust.M[2][3]);
leftEyeRTTCamera->setViewMatrix(leftEyeTranslation);
leftEyeRTTCamera->setProjectionMatrixAsPerspective(
myStereoConfig.GetYFOVDegrees(), myStereoConfig.GetAspect(), 0.3, 5000);
osg::ref_ptr<osg::Camera> rightEyeRTTCamera = osgCookBook::createRTTCamera(
osg::Camera::COLOR_BUFFER, rightEyeTex2D.get());
OVR::Util::Render::StereoEyeParams rightEyeParams =
myStereoConfig.GetEyeRenderParams(OVR::Util::Render::StereoEye_Right);
osg::Matrixf rightEyeTranslation = osg::Matrixf::translate(
rightEyeParams.ViewAdjust.M[0][3], rightEyeParams.ViewAdjust.M[2][3],
rightEyeParams.ViewAdjust.M[2][3]);
rightEyeRTTCamera->setViewMatrix(rightEyeTranslation);
rightEyeRTTCamera->setProjectionMatrixAsPerspective(
myStereoConfig.GetYFOVDegrees(), myStereoConfig.GetAspect(), 0.3, 5000);

// add your scene to the camera, should be something like:
// leftEyeRTTCamera->addChild( scene.get() );
// rightEyeRTTCamera->addChild( scene.get() );

// Create HUD cameras for each eye
osg::ref_ptr<osg::Camera> leftEyeHUDCamera =
osgCookBook::createHUDCamera(0.0, 1.0, 0.0, 1.0);
osg::ref_ptr<osg::Camera> rightEyeHUDCamera =
osgCookBook::createHUDCamera(0.0, 1.0, 0.0, 1.0);

// Create quads on each camera
leftEyeHUDCamera->addChild( osgCookBook::createScreenQuad(
1.0f, 1.0f) );
leftEyeHUDCamera->setViewport(
new osg::Viewport(0, 0, myHMDInfo.HResolution / 2, myHMDInfo.VResolution));
rightEyeHUDCamera->addChild( osgCookBook::createScreenQuad(
1.0f, 1.0f) );
rightEyeHUDCamera->setViewport(
new osg::Viewport(myHMDInfo.HResolution / 2, 0, myHMDInfo.HResolution / 2, myHMDInfo.VResolution));

// Set up shaders (from the OpenHMD project)
osg::ref_ptr<osg::Program> program = new osg::Program;
program->addShader( new osg::Shader(osg::Shader::VERTEX,
vertexShaderSource) );
program->addShader( new osg::Shader(osg::Shader::FRAGMENT,
fragmentShaderSource) );

// Configure state sets for both eyes
osg::StateSet* leftEyeStateSet = leftEyeHUDCamera->getOrCreateStateSet();
leftEyeStateSet->setTextureAttributeAndModes( 0, leftEyeTex2D.get() );
leftEyeStateSet->setAttributeAndModes( program.get() );
leftEyeStateSet->addUniform( new osg::Uniform("warpTexture", 0) );

osg::StateSet* rightEyeStateSet = rightEyeHUDCamera->getOrCreateStateSet();
rightEyeStateSet->setTextureAttributeAndModes( 0, rightEyeTex2D.get() );
rightEyeStateSet->setAttributeAndModes( program.get() );
rightEyeStateSet->addUniform( new osg::Uniform("warpTexture", 0) );


// Add everything to the root, should be something like:
//osg::ref_ptr<osg::Group> root = ?;
//root->addChild( leftEyeRTTCamera.get().get() );
//root->addChild( leftEyeHUDCamera.get().get() );
//root->addChild( rightEyeRTTCamera.get().get() );
//root->addChild( rightEyeHUDCamera.get().get() );
//root->addChild( hudCamera.get() );
//root->addChild( scene.get() );

    54 replies

    Up and Coming
    May 29, 2015
    I applied the texture setup method from the OSG thread to my integration and I'm getting the same flicker and error message. Because I didn't get good results after upgrading to 0.5.0.1 until I updated my video drivers, going up to NVIDIA 352.86 was one of the first things I tried but it didn't seem to help. In fact it caused some sort of sharing error when trying to allocate the ovrSwapTextureSets, at least until I rebooted at which point everything seemed fine. The flickering made me think that perhaps this could be an "off by one" problem so I instrumented my code to make sure the texture ID's in each of the ovrSwapTextureSets matched those in my own osg::Texture2D vectors both at initialization time and at attachment time each frame and everything seemed to line up. I verified that each of my ovrHmd_GetFrameTiming calls lined up with a ovrHmd_SubmitFrame to make sure that I wasn't off by one there. I changed the clear color of my RTT cameras to red just to verify that it was in fact flickering between something red from my cameras to something black from somewhere else. I did some debugging in CodeXL and I noticed in the statics subtree that my front buffer, which has the right dimensions for the DK2, was unbound though that could just be due to the timing of my breakpoint.
    Up and Coming
    June 1, 2015
    Looking at src\osg\glu\libutil\error.cpp it seems like "invalid framebuffer operation" is mapped to GL_INVALID_FRAMEBUFFER_OPERATION_EXT. I did some reading on that error and I'm wondering if the problem could be happening because both my OSG application & the OVR SDK are simultaneously operating on the same buffer. What I've noticed is that I'm getting the error every other frame. I'm getting ovrSwapTextureSet's with a count of two back from ovrHmd_CreateSwapTextureSetGL and I'm getting the errors when I'm using index 0 but not when I'm using index 1. I'm hoping that if I leave the cameras attached for a shorter period of time it might fix this. My idea was to attach the cameras from osg::Camera::setPreDrawCallback and detach them from setPostDrawCallback but I can't seem to get my callbacks to be called yet. While I'm hacking away at that, any thoughts on this approach?
    Up and Coming
    June 14, 2015
    Unfortunately my predraw/postdraw idea didn't pan out. I found that attaching the cameras in a pre-DrawCallback doesn't work; it's probably too late. Detaching from a post-DrawCallback doesn't help; I'm still getting the flickering.

    Even though it would have probably been a bad idea performance-wise I also tried creating Texture2D's on the fly each frame (as opposed to keeping them around in an array) and that didn't help either.
    Up and Coming
    June 19, 2015
    Success, I'm finally flicker free! I was looking through some RTT code that a co-worker of mine wrote and I noticed the following which is apparently a work-around for a bug in OSG.


    osgViewer::Renderer *camRenderer = (dynamic_cast<osgViewer::Renderer*>(camera->getRenderer()));
    if(camRenderer != NULL)
    {
    camRenderer->setCameraRequiresSetUp(true);
    }


    I applied this to my attachCamera call that I make each frame and I put it in as the very first thing, right before I increment the texture index of my ovrSwapTextureSet. Apparently the bug has something to do with the camera not properly resetting itself after an FBO change. I'm going to try and get more details on this but for now I'm just really happy to have survived another SDK upgrade! :)
    New Participant
    June 23, 2015
    Not pixelminer, but I'm currently using osgoculusviewer.
    From what I've noticed, osgoculusviewer has no attachCamera call. So, each frame I call for each of my rtt cameras:
     
    void OculusDevice::attachToCamera(osg::Camera* camera, int eyeOrder)
    {
    osg::Texture2D* texture = m_textureBuffer[eyeOrder]->texture();
    osg::Texture2D* depth = m_depthBuffer[eyeOrder]->texture();

    osgViewer::Renderer *camRenderer = (dynamic_cast<osgViewer::Renderer*>(camera->getRenderer()));
    if(camRenderer != NULL)
    {
    camRenderer->setCameraRequiresSetUp(true);
    }
    if (texture) {
    camera->setViewport(0, 0, texture->getTextureWidth(), texture->getTextureHeight());
    camera->attach(osg::Camera::COLOR_BUFFER, texture);
    }

    if (depth) {
    camera->attach(osg::Camera::DEPTH_BUFFER, depth);
    }
    }

    This call is made in OculusViewer::traverse() before OculusDevice::updatePose(). I also call the camera->detach() function at the end of traverse() to remove the depth and texture buffers.
    All I get is a black screen. Any ideas on how to improve?
    Up and Coming
    June 23, 2015
    Sorry for the confusion; I'd started this thread two years ago (to the day!) with my own OSG integration before pixelminer created OsgOculusViewer. My integration is based on an older version of OSG and is tied into a large framework on top of it. The attachToCamera function I posted is from my code and not OsgOculusViewer. That being said I think pixelminer and I were getting the same flicker with the same error message so I'm hoping my fix will also work in OsgOculusViewer. The fix was just for the flicker so if you're getting a black screen I'm guessing maybe you're having trouble somewhere else. If you were also getting the flicker and the setCameraRequiresSetUp is what actually caused you to go black you may also want to try calling it after your detach instead. I'd actually moved my setCameraRequiresSetUp to my detachCameras function in an attempt to work around a performance problem.

    Though I'm flicker free I noticed I'm only getting 37.5Hz (on a scene which should be running at 150+). I'm pretty certain it's related to the "Poor performance with new SDK" thread (https://forums.oculus.com/viewtopic.php?f=20&t=24361) but I have not confirmed that yet. Is anyone else having performance problems with 0.6.0.0?
    New Participant
    June 23, 2015
    Thanks for the reply :)
    I've tried using camera->detach() before camera->attach, but I've had flicker and one of my eyes was not rendered properly.
    Maybe pixelminer renders his scenes differently, and the camera->attach() call makes problems elsewhere in the code.
    New Participant
    June 26, 2015
    I've tried doing a verification of my cameras right before I would update the rendering index of the Hmd's textures. Unfortunatly, it did not solve the problem: I get more flickering than before. I also have this error message:

    Warning: detected OpenGL error 'invalid operation' at after RenderBin::draw(..)
    RenderStage::runCameraSetUp(), FBO setup failed, FBO status = 0x8cdd


    I get this message error twice (once for each eye) every two frames.

    Also, one of my co-workers found that when the ovrSwapTextureSet has a current index of 1, the image is not rendered properly.
    Up and Coming
    June 26, 2015
    It's interesting that you're having an issue at index 1; for me it was always index 0. In addition to doing a verification at attach time you might also want to verify the indices and context ID at initialization time and make sure they line up. This should eliminate the possibility of it being an "off by one" error as I described in my post on May 29.
    New Participant
    June 26, 2015
    sorry, it was actually index 0. My bad. ^^