mirror of https://github.com/OpenMW/openmw.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
6.4 KiB
C++
198 lines
6.4 KiB
C++
#ifndef STEREO_MANAGER_H
|
|
#define STEREO_MANAGER_H
|
|
|
|
#include <osg/Camera>
|
|
#include <osg/Matrix>
|
|
#include <osg/StateSet>
|
|
#include <osg/Vec3>
|
|
#include <osgUtil/CullVisitor>
|
|
|
|
#include <array>
|
|
#include <memory>
|
|
|
|
#include <components/shader/shadermanager.hpp>
|
|
|
|
#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<UpdateViewCallback> cb);
|
|
|
|
//! Set the cull callback on the appropriate camera object
|
|
void setCullCallback(osg::ref_ptr<osg::NodeCallback> cb);
|
|
|
|
osg::Matrixd computeEyeProjection(int view, bool reverseZ) const;
|
|
osg::Matrixd computeEyeViewOffset(int view) const;
|
|
|
|
const std::shared_ptr<MultiviewFramebuffer>& 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<osgViewer::Viewer> mViewer;
|
|
osg::ref_ptr<osg::Camera> mMainCamera;
|
|
osg::ref_ptr<osg::Callback> mUpdateCallback;
|
|
std::string mError;
|
|
osg::Matrixd mMasterProjectionMatrix;
|
|
std::shared_ptr<MultiviewFramebuffer> mMultiviewFramebuffer;
|
|
bool mEyeResolutionOverriden;
|
|
osg::Vec2i mEyeResolutionOverride;
|
|
double mNear;
|
|
double mFar;
|
|
|
|
std::array<View, 2> mView;
|
|
std::array<osg::Matrixd, 2> mViewOffsetMatrix;
|
|
std::array<osg::Matrixd, 2> mProjectionMatrix;
|
|
std::array<osg::Matrixd, 2> mProjectionMatrixReverseZ;
|
|
|
|
std::unique_ptr<StereoFrustumManager> mFrustumManager;
|
|
std::shared_ptr<UpdateViewCallback> mUpdateViewCallback;
|
|
|
|
using Identifier = osgUtil::CullVisitor::Identifier;
|
|
osg::ref_ptr<Identifier> mIdentifierMain = new Identifier();
|
|
osg::ref_ptr<Identifier> mIdentifierLeft = new Identifier();
|
|
osg::ref_ptr<Identifier> mIdentifierRight = new Identifier();
|
|
};
|
|
|
|
struct CustomView
|
|
{
|
|
Stereo::View mLeft;
|
|
Stereo::View mRight;
|
|
};
|
|
|
|
struct Settings
|
|
{
|
|
bool mMultiview;
|
|
bool mAllowDisplayListsForMultiview;
|
|
bool mSharedShadowMaps;
|
|
std::optional<CustomView> mCustomView;
|
|
std::optional<osg::Vec2i> 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<CustomView> mCustomView;
|
|
std::optional<osg::Vec2i> mEyeResolution;
|
|
};
|
|
}
|
|
|
|
#endif
|