#ifndef STEREO_MANAGER_H #define STEREO_MANAGER_H #include #include #include #include #include #include #include #include #include "types.hpp" namespace osg { class FrameBufferObject; class Texture2D; class Texture2DArray; } namespace osgViewer { class Viewer; } namespace SceneUtil { class MWShadowTechnique; } namespace Stereo { class MultiviewFramebuffer; class StereoFrustumManager; class MultiviewStereoStatesetUpdateCallback; bool getStereo(); //! Sets up any definitions necessary for stereo rendering void shaderStereoDefines(Shader::ShaderManager::DefineMap& defines); //! Class that provides tools for managing stereo mode class Manager { public: struct UpdateViewCallback { virtual ~UpdateViewCallback() = default; //! Called during the update traversal of every frame to update stereo views. virtual void updateView(View& left, View& right) = 0; }; //! An UpdateViewCallback that supplies a fixed, custom view. Useful for debugging purposes, //! such as emulating a given HMD's view. struct CustomViewCallback : public UpdateViewCallback { public: CustomViewCallback(View& left, View& right); void updateView(View& left, View& right) override; private: View mLeft; View mRight; }; //! Gets the singleton instance static Manager& instance(); //! Constructor //! //! @Param viewer the osg viewer whose stereo should be managed. //! @Param enableStereo whether or not stereo should be enabled. //! @Param enableMultiview whether or not to make use of the GL_OVR_Multiview extension, if supported. //! @Param near defines distance to near camera clipping plane from view point. //! @Param far defines distance to far camera clipping plane from view point. explicit Manager(osgViewer::Viewer* viewer, bool enableStereo, double near, double far); ~Manager(); //! Called during update traversal void update(); void updateSettings(double near, double far) { mNear = near; mFar = far; } //! Initializes all details of stereo if applicable. If the constructor was called with enableMultiview=true, //! and the GL_OVR_Multiview extension is supported, Stereo::getMultiview() will return true after this call. void initializeStereo(osg::GraphicsContext* gc, bool enableMultiview, bool sharedShadowMaps); //! Callback that updates stereo configuration during the update pass void setUpdateViewCallback(std::shared_ptr cb); //! Set the cull callback on the appropriate camera object void setCullCallback(osg::ref_ptr cb); osg::Matrixd computeEyeProjection(int view, bool reverseZ) const; osg::Matrixd computeEyeViewOffset(int view) const; const std::shared_ptr& multiviewFramebuffer() { return mMultiviewFramebuffer; } //! Sets rendering resolution of each eye to eyeResolution. //! Once set, there will no longer be any connection between rendering resolution and screen/window resolution. void overrideEyeResolution(const osg::Vec2i& eyeResolution); //! Notify stereo manager that the screen/window resolution has changed. void screenResolutionChanged(); //! Get current eye resolution osg::Vec2i eyeResolution(); //! The projection intended for rendering. When reverse Z is enabled, this is not the same as the camera's //! projection matrix, and therefore must be provided to the manager explicitly. void setMasterProjectionMatrix(const osg::Matrixd& projectionMatrix) { mMasterProjectionMatrix = projectionMatrix; } //! Causes the subgraph represented by the node to draw to the full viewport. //! This has no effect if stereo is not enabled void disableStereoForNode(osg::Node* node); void setShadowTechnique(SceneUtil::MWShadowTechnique* shadowTechnique); /// Determine which view the cull visitor belongs to Eye getEye(const osgUtil::CullVisitor* cv) const; private: friend class MultiviewStereoStatesetUpdateCallback; void updateMultiviewStateset(osg::StateSet* stateset); void updateStereoFramebuffer(); void setupBruteForceTechnique(); void setupOVRMultiView2Technique(); osg::ref_ptr mViewer; osg::ref_ptr mMainCamera; osg::ref_ptr mUpdateCallback; std::string mError; osg::Matrixd mMasterProjectionMatrix; std::shared_ptr mMultiviewFramebuffer; bool mEyeResolutionOverriden; osg::Vec2i mEyeResolutionOverride; double mNear; double mFar; std::array mView; std::array mViewOffsetMatrix; std::array mProjectionMatrix; std::array mProjectionMatrixReverseZ; std::unique_ptr mFrustumManager; std::shared_ptr mUpdateViewCallback; using Identifier = osgUtil::CullVisitor::Identifier; osg::ref_ptr mIdentifierMain = new Identifier(); osg::ref_ptr mIdentifierLeft = new Identifier(); osg::ref_ptr mIdentifierRight = new Identifier(); }; struct CustomView { Stereo::View mLeft; Stereo::View mRight; }; struct Settings { bool mMultiview; bool mAllowDisplayListsForMultiview; bool mSharedShadowMaps; std::optional mCustomView; std::optional mEyeResolution; }; //! Performs stereo-specific initialization operations. class InitializeStereoOperation final : public osg::GraphicsOperation { public: explicit InitializeStereoOperation(const Settings& settings); void operator()(osg::GraphicsContext* graphicsContext) override; private: bool mMultiview; bool mSharedShadowMaps; std::optional mCustomView; std::optional mEyeResolution; }; } #endif