void OculusViewConfig::configure(osgViewer::View& view) const { m_device->setNearClip(m_nearClip); m_device->setFarClip(m_farClip); m_device->setSensorPredictionEnabled(m_useSensorPrediction); m_device->setSensorPredictionDelta(m_predictionDelta); if (m_useCustomScaleFactor) { m_device->setCustomScaleFactor(m_customScaleFactor); } // Create screen with match the Oculus Rift resolution osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (!wsi) { osg::notify(osg::NOTICE)<<"Error, no WindowSystemInterface available, cannot create windows."<<std::endl; return; } // Get the screen identifiers set in environment variable DISPLAY osg::GraphicsContext::ScreenIdentifier si; si.readDISPLAY(); // If displayNum has not been set, reset it to 0. if (si.displayNum < 0) si.displayNum = 0; // If screenNum has not been set, reset it to 0. if (si.screenNum < 0) si.screenNum = 0; //test by Shao si.displayNum = _displayNum; si.screenNum = _screenNum; unsigned int width, height; wsi->getScreenResolution(si, width, height); osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->hostName = si.hostName; traits->screenNum = si.screenNum; traits->displayNum = si.displayNum; traits->windowDecoration = false; traits->x = 0; traits->y = 0; traits->width = m_device->hScreenResolution(); traits->height = m_device->vScreenResolution(); traits->doubleBuffer = true; traits->sharedContext = 0; traits->vsync = true; // VSync should always be enabled for Oculus Rift applications // Create a graphic context based on our desired traits osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits); if (!gc) { osg::notify(osg::NOTICE) << "Error, GraphicsWindow has not been created successfully" << std::endl; return; } _main_camera = view.getCamera(); _main_camera->setName("Main"); // Disable scene rendering for main camera _main_camera->setCullMask(~m_sceneNodeMask); _main_camera->setGraphicsContext(gc); // Use full view port _main_camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height)); // Disable automatic computation of near and far plane on main camera, will propagate to slave cameras _main_camera->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR ); const int textureWidth = m_device->scaleFactor() * m_device->hScreenResolution()/2; const int textureHeight = m_device->scaleFactor() * m_device->vScreenResolution(); // master projection matrix _main_camera->setProjectionMatrix(m_device->projectionCenterMatrix()); // Create textures for RTT cameras osg::ref_ptr<osg::Texture2D> textureLeft = new osg::Texture2D; textureLeft->setTextureSize( textureWidth, textureHeight ); textureLeft->setInternalFormat( GL_RGBA ); osg::ref_ptr<osg::Texture2D> textureRight = new osg::Texture2D; textureRight->setTextureSize( textureWidth, textureHeight ); textureRight->setInternalFormat( GL_RGBA ); // Create RTT (Rendering to Texture) cameras and attach textures osg::ref_ptr<osg::Camera> cameraRTTLeft = createRTTCamera(textureLeft, gc); osg::ref_ptr<osg::Camera> cameraRTTRight = createRTTCamera(textureRight, gc); cameraRTTLeft->setName("LeftRTT"); cameraRTTRight->setName("RightRTT"); cameraRTTLeft->setCullMask(m_sceneNodeMask); cameraRTTRight->setCullMask(m_sceneNodeMask); // Create HUD cameras for left eye osg::ref_ptr<osg::Camera> cameraHUDLeft = createHUDCamera(0.0, 1.0, 0.0, 1.0, gc); cameraHUDLeft->setName("LeftHUD"); cameraHUDLeft->setViewport(new osg::Viewport(0, 0, m_device->hScreenResolution() / 2.0f, m_device->vScreenResolution())); // Create HUD cameras for right eye osg::ref_ptr<osg::Camera> cameraHUDRight = createHUDCamera(0.0, 1.0, 0.0, 1.0, gc); cameraHUDRight->setName("RightHUD"); cameraHUDRight->setViewport(new osg::Viewport(m_device->hScreenResolution() / 2.0f, 0, m_device->hScreenResolution() / 2.0f, m_device->vScreenResolution())); // Create quads for each camera osg::ref_ptr<osg::Geode> leftQuad = createHUDQuad(1.0f, 1.0f); cameraHUDLeft->addChild(leftQuad); osg::ref_ptr<osg::Geode> rightQuad = createHUDQuad(1.0f, 1.0f); cameraHUDRight->addChild(rightQuad); // Set up shaders from the Oculus SDK documentation osg::ref_ptr<osg::Program> program = new osg::Program; osg::ref_ptr<osg::Shader> vertexShader = new osg::Shader(osg::Shader::VERTEX); vertexShader->loadShaderSourceFromFile(osgDB::findDataFile("warp.vert")); osg::ref_ptr<osg::Shader> fragmentShader = new osg::Shader(osg::Shader::FRAGMENT); // Fragment shader with or without correction for chromatic aberration if (m_useChromaticAberrationCorrection) { fragmentShader->loadShaderSourceFromFile(osgDB::findDataFile("warpWithChromeAb.frag")); } else { fragmentShader->loadShaderSourceFromFile(osgDB::findDataFile("warpWithoutChromeAb.frag")); } program->addShader(vertexShader); program->addShader(fragmentShader); // Attach shaders to each HUD osg::StateSet* leftEyeStateSet = leftQuad->getOrCreateStateSet(); osg::StateSet* rightEyeStateSet = rightQuad->getOrCreateStateSet(); applyShaderParameters(leftEyeStateSet, program.get(), textureLeft.get(), OculusDevice::LEFT_EYE); applyShaderParameters(rightEyeStateSet, program.get(), textureRight.get(), OculusDevice::RIGHT_EYE); // Add RTT cameras as slaves, specifying offsets for the projection view.addSlave(cameraRTTLeft, m_device->projectionOffsetMatrix(OculusDevice::LEFT_EYE), m_device->viewMatrix(OculusDevice::LEFT_EYE), true); view.addSlave(cameraRTTRight, m_device->projectionOffsetMatrix(OculusDevice::RIGHT_EYE), m_device->viewMatrix(OculusDevice::RIGHT_EYE), true); // Add HUD cameras as slaves view.addSlave(cameraHUDLeft, false); view.addSlave(cameraHUDRight, false); view.setName("Oculus"); // Connect main camera to node callback that get HMD orientation if (m_useOrientations) { _main_camera->setDataVariance(osg::Object::DYNAMIC); _callback = new OculusViewConfigOrientationCallback(cameraRTTLeft, cameraRTTRight, m_device); _main_camera->setUpdateCallback(_callback); } }
/* Public functions */ void OculusViewConfig::configure(osgViewer::View& view) const { // Create a graphic context based on our desired traits osg::ref_ptr<osg::GraphicsContext::Traits> traits = m_device->graphicsContextTraits(); osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits); if (!gc) { osg::notify(osg::NOTICE) << "Error, GraphicsWindow has not been created successfully" << std::endl; return; } // Attach to window, needed for direct mode m_device->attachToWindow(gc); // Attach a callback to detect swap osg::ref_ptr<OculusSwapCallback> swapCallback = new OculusSwapCallback(m_device); gc->setSwapCallback(swapCallback); osg::ref_ptr<osg::Camera> camera = view.getCamera(); camera->setName("Main"); // Disable scene rendering for main camera camera->setCullMask(~m_sceneNodeMask); camera->setGraphicsContext(gc); // Use full view port camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height)); // Disable automatic computation of near and far plane on main camera, will propagate to slave cameras camera->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR ); const int textureWidth = m_device->renderTargetWidth()/2; const int textureHeight = m_device->renderTargetHeight(); // master projection matrix camera->setProjectionMatrix(m_device->projectionMatrixCenter()); // Create textures for RTT cameras osg::ref_ptr<osg::Texture2D> textureLeft = new osg::Texture2D; textureLeft->setTextureSize( textureWidth, textureHeight ); textureLeft->setInternalFormat( GL_RGBA ); osg::ref_ptr<osg::Texture2D> textureRight = new osg::Texture2D; textureRight->setTextureSize( textureWidth, textureHeight ); textureRight->setInternalFormat( GL_RGBA ); // Create RTT cameras and attach textures osg::ref_ptr<osg::Camera> cameraRTTLeft = m_device->createRTTCamera(textureLeft, OculusDevice::LEFT, osg::Camera::RELATIVE_RF, gc); osg::ref_ptr<osg::Camera> cameraRTTRight = m_device->createRTTCamera(textureRight, OculusDevice::RIGHT, osg::Camera::RELATIVE_RF, gc); cameraRTTLeft->setName("LeftRTT"); cameraRTTRight->setName("RightRTT"); cameraRTTLeft->setCullMask(m_sceneNodeMask); cameraRTTRight->setCullMask(m_sceneNodeMask); // Create warp ortho camera osg::ref_ptr<osg::Camera> cameraWarp = m_device->createWarpOrthoCamera(0.0, 1.0, 0.0, 1.0, gc); cameraWarp->setName("WarpOrtho"); cameraWarp->setViewport(new osg::Viewport(0, 0, m_device->screenResolutionWidth(), m_device->screenResolutionHeight())); // Create shader program osg::ref_ptr<osg::Program> program = m_device->createShaderProgram(); // Create distortionMesh for each camera osg::ref_ptr<osg::Geode> leftDistortionMesh = m_device->distortionMesh(OculusDevice::LEFT, program, 0, 0, textureWidth, textureHeight); cameraWarp->addChild(leftDistortionMesh); osg::ref_ptr<osg::Geode> rightDistortionMesh = m_device->distortionMesh(OculusDevice::RIGHT, program, 0, 0, textureWidth, textureHeight); cameraWarp->addChild(rightDistortionMesh); // Add pre draw camera to handle time warp cameraWarp->setPreDrawCallback(new WarpCameraPreDrawCallback(m_device)); // Attach shaders to each distortion mesh osg::ref_ptr<osg::StateSet> leftEyeStateSet = leftDistortionMesh->getOrCreateStateSet(); osg::ref_ptr<osg::StateSet> rightEyeStateSet = rightDistortionMesh->getOrCreateStateSet(); m_device->applyShaderParameters(leftEyeStateSet, program.get(), textureLeft.get(), OculusDevice::LEFT); m_device->applyShaderParameters(rightEyeStateSet, program.get(), textureRight.get(), OculusDevice::RIGHT); // Add RTT cameras as slaves, specifying offsets for the projection view.addSlave(cameraRTTLeft, m_device->projectionOffsetMatrixLeft(), m_device->viewMatrixLeft(), true); view.addSlave(cameraRTTRight, m_device->projectionOffsetMatrixRight(), m_device->viewMatrixRight(), true); // Use sky light instead of headlight to avoid light changes when head movements view.setLightingMode(osg::View::SKY_LIGHT); // Add warp camera as slave view.addSlave(cameraWarp, false); view.setName("Oculus"); // Connect main camera to node callback that get HMD orientation camera->setDataVariance(osg::Object::DYNAMIC); camera->setCullCallback(new OculusViewConfigOrientationCallback(cameraRTTLeft, cameraRTTRight, m_device, swapCallback, m_warning)); // Add Oculus keyboard handler view.addEventHandler(new OculusEventHandler(m_device)); view.addEventHandler(new OculusWarningEventHandler(m_device, m_warning)); }