File: stereomanager.hpp

package info (click to toggle)
openmw 0.49.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 33,992 kB
  • sloc: cpp: 372,479; xml: 2,149; sh: 1,403; python: 797; makefile: 26
file content (197 lines) | stat: -rw-r--r-- 6,599 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#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