#ifndef STEREO_MULTIVIEW_H #define STEREO_MULTIVIEW_H #include #include #include #include #include #include namespace osg { class FrameBufferObject; class Texture; class Texture2D; class Texture2DArray; } namespace osgUtil { class RenderStage; } namespace Stereo { class UpdateRenderStagesCallback; //! Check if TextureView is supported. Results are undefined if called before configureExtensions(). bool getTextureViewSupported(); //! Check if Multiview should be used. Results are undefined if called before configureExtensions(). bool getMultiview(); //! Use the provided context to check what extensions are supported and configure use of multiview based on //! extensions and settings. void configureExtensions(unsigned int contextID, bool enableMultiview); //! Sets the appropriate vertex buffer hint on OSG's display settings if needed void setVertexBufferHint(bool enableMultiview, bool allowDisplayListsForMultiview); //! Creates a Texture2D as a texture view into a Texture2DArray osg::ref_ptr createTextureView_Texture2DFromTexture2DArray( osg::Texture2DArray* textureArray, int layer); //! Class that manages the specifics of GL_OVR_Multiview aware framebuffers, separating the layers into separate //! framebuffers, and disabling class MultiviewFramebuffer { public: MultiviewFramebuffer(int width, int height, int samples); ~MultiviewFramebuffer(); void attachColorComponent(GLint sourceFormat, GLint sourceType, GLint internalFormat); void attachDepthComponent(GLint sourceFormat, GLint sourceType, GLint internalFormat); osg::FrameBufferObject* multiviewFbo(); osg::FrameBufferObject* layerFbo(int i); osg::FrameBufferObject* layerMsaaFbo(int i); osg::Texture2DArray* multiviewColorBuffer(); osg::Texture2DArray* multiviewDepthBuffer(); osg::Texture2D* layerColorBuffer(int i); osg::Texture2D* layerDepthBuffer(int i); void attachTo(osg::Camera* camera); void detachFrom(osg::Camera* camera); int width() const { return mWidth; } int height() const { return mHeight; } int samples() const { return mSamples; } private: osg::Texture2D* createTexture(GLint sourceFormat, GLint sourceType, GLint internalFormat); osg::Texture2DArray* createTextureArray(GLint sourceFormat, GLint sourceType, GLint internalFormat); int mWidth; int mHeight; int mSamples; bool mMultiview; osg::ref_ptr mCullCallback; osg::ref_ptr mMultiviewFbo; std::array, 2> mLayerFbo; std::array, 2> mLayerMsaaFbo; osg::ref_ptr mMultiviewColorTexture; osg::ref_ptr mMultiviewDepthTexture; std::array, 2> mColorTexture; std::array, 2> mDepthTexture; }; //! Sets up a draw callback on the render stage that performs the MSAA resolve operation void setMultiviewMSAAResolveCallback(osgUtil::RenderStage* renderStage); //! Sets up or updates multiview matrices for the given stateset void setMultiviewMatrices( osg::StateSet* stateset, const std::array& projection, bool createInverseMatrices = false); //! Sets the width/height of a texture by first down-casting it to the appropriate type. Sets depth to 2 always for //! Texture2DArray and Texture2DMultisampleArray. void setMultiviewCompatibleTextureSize(osg::Texture* tex, int w, int h); //! Creates a texture (Texture2D, Texture2DMultisample, Texture2DArray, or Texture2DMultisampleArray) based on //! multiview settings and sample count. osg::ref_ptr createMultiviewCompatibleTexture(int width, int height, int samples); //! Returns a framebuffer attachment from the texture, returning a multiview attachment if the texture is one of //! Texture2DArray or Texture2DMultisampleArray osg::FrameBufferAttachment createMultiviewCompatibleAttachment(osg::Texture* tex); //! If OSG has multiview, returns the magic number used to tell OSG to create a multiview attachment. Otherwise //! returns 0. unsigned int osgFaceControlledByMultiviewShader(); //! Implements resolving a multisamples multiview framebuffer. Does not automatically reflect changes to the fbo //! attachments, must call dirty() when the fbo attachments change. class MultiviewFramebufferResolve { public: MultiviewFramebufferResolve( osg::FrameBufferObject* msaaFbo, osg::FrameBufferObject* resolveFbo, GLbitfield blitMask); void resolveImplementation(osg::State& state); void dirty() { mDirtyLayers = true; } const osg::FrameBufferObject* resolveFbo() const { return mResolveFbo; } const osg::FrameBufferObject* msaaFbo() const { return mMsaaFbo; } void setResolveFbo(osg::FrameBufferObject* resolveFbo); void setMsaaFbo(osg::FrameBufferObject* msaaFbo); private: void setupLayers(); osg::ref_ptr mResolveFbo; std::array, 2> mResolveLayers{}; osg::ref_ptr mMsaaFbo; std::array, 2> mMsaaLayers{}; GLbitfield mBlitMask; bool mDirtyLayers = true; int mWidth = -1; int mHeight = -1; }; //! Wrapper for osg::CullSettings::InitialFrustumCallback, to avoid exposing osg multiview interfaces outside of //! multiview.cpp struct InitialFrustumCallback { InitialFrustumCallback(osg::Camera* camera); virtual ~InitialFrustumCallback(); virtual void setInitialFrustum( osg::CullStack& cullStack, osg::BoundingBoxd& bb, bool& nearCulling, bool& farCulling) const = 0; osg::observer_ptr mCamera; }; } #endif