File: mwshadowtechnique.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 (343 lines) | stat: -rw-r--r-- 13,710 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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
// clang-format off
/* This file is based on OpenSceneGraph's include/osgShadow/ViewDependentShadowMap.
 * Where applicable, any changes made are covered by OpenMW's GPL 3 license, not the OSGPL.
 * The original copyright notice is listed below.
 */

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2011 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#ifndef COMPONENTS_SCENEUTIL_MWSHADOWTECHNIQUE_H
#define COMPONENTS_SCENEUTIL_MWSHADOWTECHNIQUE_H 1

#include <array>
#include <mutex>
#include <string>

#include <osg/Camera>
#include <osg/Material>
#include <osg/MatrixTransform>
#include <osg/LightSource>
#include <osg/PolygonOffset>

#include <osgShadow/ShadowTechnique>

#include <components/shader/shadermanager.hpp>

namespace SceneUtil {

    /** ViewDependentShadowMap provides an base implementation of view dependent shadow mapping techniques.*/
    class MWShadowTechnique : public osgShadow::ShadowTechnique
    {
    public:
        MWShadowTechnique();

        MWShadowTechnique(const MWShadowTechnique& vdsm, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);

        META_Object(SceneUtil, MWShadowTechnique)

        /** initialize the ShadowedScene and local cached data structures.*/
        void init() override;

        /** run the update traversal of the ShadowedScene and update any loca chached data structures.*/
        void update(osg::NodeVisitor& nv) override;

        /** run the cull traversal of the ShadowedScene and set up the rendering for this ShadowTechnique.*/
        void cull(osgUtil::CullVisitor& cv) override;

        /** Resize any per context GLObject buffers to specified size. */
        void resizeGLObjectBuffers(unsigned int maxSize) override;

        /** If State is non-zero, this function releases any associated OpenGL objects for
        * the specified graphics context. Otherwise, releases OpenGL objects
        * for all graphics contexts. */
        void releaseGLObjects(osg::State* = 0) const override;

        /** Clean scene graph from any shadow technique specific nodes, state and drawables.*/
        void cleanSceneGraph() override;

        virtual void enableShadows();

        virtual void disableShadows(bool setDummyState = false);

        virtual void enableDebugHUD();

        virtual void disableDebugHUD();

        virtual void setSplitPointUniformLogarithmicRatio(double ratio);

        virtual void setSplitPointDeltaBias(double bias);

        virtual void setPolygonOffset(float factor, float units);

        virtual void setShadowFadeStart(float shadowFadeStart);

        virtual void enableFrontFaceCulling();

        virtual void disableFrontFaceCulling();

        virtual void setupCastingShader(Shader::ShaderManager &shaderManager);

        class ComputeLightSpaceBounds : public osg::NodeVisitor, public osg::CullStack
        {
        public:
            ComputeLightSpaceBounds();

            void apply(osg::Node& node) override final;
            void apply(osg::Group& node) override;

            void apply(osg::Drawable& drawable) override final;
            void apply(osg::Geometry& drawable) override;

            void apply(osg::Billboard&) override;

            void apply(osg::Projection&) override;

            void apply(osg::Transform& transform) override final;
            void apply(osg::MatrixTransform& transform) override;

            void apply(osg::Camera&) override;

            void updateBound(const osg::BoundingBox& bb);

            void update(const osg::Vec3& v);

            void reset() override;

            osg::BoundingBox _bb;
        };

        struct Frustum
        {
            Frustum(osgUtil::CullVisitor* cv, double minZNear, double maxZFar);
            void setCustomClipSpace(const osg::BoundingBoxd& clipCornersOverride);
            void init();

            osg::Matrixd projectionMatrix;
            osg::Matrixd modelViewMatrix;

            bool useCustomClipSpace;
            osg::BoundingBoxd customClipSpace;

            typedef std::vector<osg::Vec3d> Vertices;
            Vertices corners;

            typedef std::vector<unsigned int> Indices;
            typedef std::vector<Indices> Faces;
            Faces faces;

            typedef std::vector<Indices> Edges;
            Edges edges;

            osg::Vec3d eye;
            osg::Vec3d centerNearPlane;
            osg::Vec3d centerFarPlane;
            osg::Vec3d center;
            osg::Vec3d frustumCenterLine;
        };

        /** Custom frustum callback allowing the application to request shadow maps covering a
        * different furstum than the camera normally would cover, by customizing the corners of the clip space. */
        struct CustomFrustumCallback : osg::Referenced
        {
            /** The callback operator.
            * Output the custum frustum to the boundingBox variable.
            * If sharedFrustumHint is set to a valid cull visitor, the shadow maps of that cull visitor will be re-used instead of recomputing new shadow maps 
            * Note that the customClipSpace bounding box will be uninitialized when this operator is called. If it is not initalized, or a valid shared frustum hint set,
            * the resulting shadow map may be invalid. */
            virtual void operator()(osgUtil::CullVisitor& cv, osg::BoundingBoxd& customClipSpace, osgUtil::CullVisitor*& sharedFrustumHint) = 0;
        };
        typedef std::vector< osg::ref_ptr<osg::Uniform> > Uniforms;

        // forward declare
        class ViewDependentData;

        struct LightData : public osg::Referenced
        {
            LightData(ViewDependentData* vdd);

            virtual void setLightData(osg::RefMatrix* lm, const osg::Light* l, const osg::Matrixd& modelViewMatrix);

            ViewDependentData*                  _viewDependentData;

            osg::ref_ptr<osg::RefMatrix>        lightMatrix;
            osg::ref_ptr<const osg::Light>      light;

            osg::Vec4d                          lightPos;
            osg::Vec3d                          lightPos3;
            osg::Vec3d                          lightDir;
            bool                                directionalLight;

            typedef std::vector<unsigned int> ActiveTextureUnits;
            ActiveTextureUnits                   textureUnits;
        };

        typedef std::list< osg::ref_ptr<LightData> > LightDataList;

        struct ShadowData : public osg::Referenced
        {
            ShadowData(ViewDependentData* vdd);

            virtual void releaseGLObjects(osg::State* = 0) const;

            ViewDependentData*                  _viewDependentData;

            unsigned int                        _textureUnit;
            unsigned int                        _sm_i;
            osg::ref_ptr<osg::Texture2D>        _texture;
            osg::ref_ptr<osg::Camera>           _camera;
        };

        typedef std::list< osg::ref_ptr<ShadowData> > ShadowDataList;


        class ViewDependentData : public osg::Referenced
        {
        public:
            ViewDependentData(MWShadowTechnique* vdsm);

            const MWShadowTechnique* getViewDependentShadowMap() const { return _viewDependentShadowMap; }

            LightDataList& getLightDataList() { return _lightDataList; }

            ShadowDataList& getShadowDataList() { return _shadowDataList; }

            osg::StateSet* getStateSet(unsigned int traversalNumber) { return _stateset[traversalNumber % 2].get(); }

            virtual void releaseGLObjects(osg::State* = 0) const;

            unsigned int numValidShadows(void) const { return _numValidShadows; }

            void setNumValidShadows(unsigned int numValidShadows) { _numValidShadows = numValidShadows; }

        protected:
            friend class MWShadowTechnique;
            virtual ~ViewDependentData() {}

            MWShadowTechnique*          _viewDependentShadowMap;

            std::array<osg::ref_ptr<osg::StateSet>, 2> _stateset;

            LightDataList               _lightDataList;
            ShadowDataList              _shadowDataList;
            std::array<Uniforms, 2>     _uniforms;

            unsigned int _numValidShadows;
        };

        virtual ViewDependentData* createViewDependentData(osgUtil::CullVisitor* cv);

        ViewDependentData* getViewDependentData(osgUtil::CullVisitor* cv);

        void copyShadowMap(osgUtil::CullVisitor& cv, ViewDependentData* lhs, ViewDependentData* rhs);

        void setCustomFrustumCallback(CustomFrustumCallback* cfc);

        void copyShadowStateSettings(osgUtil::CullVisitor& cv, ViewDependentData* vdd);

        virtual void createShaders();

        virtual bool selectActiveLights(osgUtil::CullVisitor* cv, ViewDependentData* vdd) const;

        virtual osg::Polytope computeLightViewFrustumPolytope(Frustum& frustum, LightData& positionedLight);

        virtual bool computeShadowCameraSettings(Frustum& frustum, LightData& positionedLight, osg::Matrixd& projectionMatrix, osg::Matrixd& viewMatrix);

        virtual bool cropShadowCameraToMainFrustum(Frustum& frustum, osg::Camera* camera, double viewNear, double viewFar, std::vector<osg::Plane>& planeList);

        virtual bool adjustPerspectiveShadowMapCameraSettings(osgUtil::RenderStage* renderStage, Frustum& frustum, LightData& positionedLight, osg::Camera* camera, double viewNear, double viewFar);
        
        virtual void assignShadowStateSettings(osgUtil::CullVisitor& cv, osg::Camera* camera, unsigned int sm_i, Uniforms& uniforms);
        
        virtual void assignValidRegionSettings(osgUtil::CullVisitor& cv, osg::Camera* camera, unsigned int sm_i, Uniforms& uniforms);

        virtual void cullShadowReceivingScene(osgUtil::CullVisitor* cv) const;

        virtual void cullShadowCastingScene(osgUtil::CullVisitor* cv, osg::Camera* camera) const;

        virtual osg::StateSet* prepareStateSetForRenderingShadow(ViewDependentData& vdd, unsigned int traversalNumber) const;

        void setWorldMask(unsigned int worldMask) { _worldMask = worldMask; }

        osg::ref_ptr<osg::StateSet> getOrCreateShadowsBinStateSet();

    protected:
        virtual ~MWShadowTechnique();

        osg::ref_ptr<ComputeLightSpaceBounds>   _clsb;

        typedef std::map< osgUtil::CullVisitor*, osg::ref_ptr<ViewDependentData> >  ViewDependentDataMap;
        mutable std::mutex                      _viewDependentDataMapMutex;
        ViewDependentDataMap                    _viewDependentDataMap;
        osg::ref_ptr<CustomFrustumCallback>     _customFrustumCallback;
        osg::BoundingBoxd                       _customClipSpace;

        osg::ref_ptr<osg::StateSet>             _shadowRecievingPlaceholderStateSet;

        osg::ref_ptr<osg::StateSet>             _shadowCastingStateSet;
        osg::ref_ptr<osg::PolygonOffset>        _polygonOffset;
        osg::ref_ptr<osg::Texture2D>            _fallbackBaseTexture;
        osg::ref_ptr<osg::Texture2D>            _fallbackShadowMapTexture;

        std::array<Uniforms, 2>                 _uniforms;
        osg::ref_ptr<osg::Program>              _program;

        bool                                    _enableShadows;
        bool                                    mSetDummyStateWhenDisabled;

        double                                  _splitPointUniformLogRatio = 0.5;
        double                                  _splitPointDeltaBias = 0.0;

        float                                   _polygonOffsetFactor = 1.1;
        float                                   _polygonOffsetUnits = 4.0;

        bool                                    _useFrontFaceCulling = true;

        float                                   _shadowFadeStart = 0.0;

        unsigned int                            _worldMask = ~0u;

        class DebugHUD final : public osg::Referenced
        {
        public:
            DebugHUD(int numberOfShadowMapsPerLight);

            void draw(osg::ref_ptr<osg::Texture2D> texture, unsigned int shadowMapNumber, const osg::Matrixd &matrix, osgUtil::CullVisitor& cv);

            void releaseGLObjects(osg::State* state = 0) const;

            void setFrustumVertices(osg::ref_ptr<osg::Vec3Array> vertices, unsigned int traversalNumber);
        protected:
            void addAnotherShadowMap();

            static const int sDebugTextureUnit = 0;

            std::vector<osg::ref_ptr<osg::Camera>> mDebugCameras;
            osg::ref_ptr<osg::Program> mDebugProgram;
            std::vector<osg::ref_ptr<osg::Node>> mDebugGeometry;
            std::vector<osg::ref_ptr<osg::Group>> mFrustumTransforms;
            std::array<std::vector<osg::ref_ptr<osg::Uniform>>, 2> mFrustumUniforms;
            std::array<osg::ref_ptr<osg::Geometry>, 2> mFrustumGeometries;
        };

        osg::ref_ptr<DebugHUD>                  _debugHud;
        std::array<osg::ref_ptr<osg::Program>, GL_ALWAYS - GL_NEVER + 1> _castingPrograms;
        const std::string _shadowsBinName = "ShadowsBin_" + std::to_string(reinterpret_cast<std::uint64_t>(this));
        osg::ref_ptr<osgUtil::RenderBin> _shadowsBin;
        osg::ref_ptr<osg::StateSet> _shadowsBinStateSet;
    };

}

#endif
// clang-format on