File: depth.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 (195 lines) | stat: -rw-r--r-- 6,214 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
#ifndef OPENMW_COMPONENTS_SCENEUTIL_DEPTH_H
#define OPENMW_COMPONENTS_SCENEUTIL_DEPTH_H

#include <osg/Depth>

#include "util.hpp"

#ifndef GL_DEPTH32F_STENCIL8_NV
#define GL_DEPTH32F_STENCIL8_NV 0x8DAC
#endif

#ifndef GL_DEPTH32F_STENCIL8
#define GL_DEPTH32F_STENCIL8 0x8CAD
#endif

#ifndef GL_FLOAT_32_UNSIGNED_INT_24_8_REV
#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
#endif

#ifndef GL_DEPTH24_STENCIL8
#define GL_DEPTH24_STENCIL8 0x88F0
#endif

#ifndef GL_DEPTH_STENCIL_EXT
#define GL_DEPTH_STENCIL_EXT 0x84F9
#endif

#ifndef GL_UNSIGNED_INT_24_8_EXT
#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
#endif

namespace SceneUtil
{
    // Sets camera clear depth to 0 if reversed depth buffer is in use, 1 otherwise.
    void setCameraClearDepth(osg::Camera* camera);

    // Returns a perspective projection matrix for use with a reversed z-buffer
    // and an infinite far plane. This is derived by mapping the default z-range
    // of [0,1] to [1,0], then taking the limit as far plane approaches infinity.
    osg::Matrix getReversedZProjectionMatrixAsPerspectiveInf(double fov, double aspect, double near);

    // Returns a perspective projection matrix for use with a reversed z-buffer.
    osg::Matrix getReversedZProjectionMatrixAsPerspective(double fov, double aspect, double near, double far);

    // Returns an orthographic projection matrix for use with a reversed z-buffer.
    osg::Matrix getReversedZProjectionMatrixAsOrtho(
        double left, double right, double bottom, double top, double near, double far);

    // Returns true if the GL format is a depth format
    bool isDepthFormat(GLenum format);

    // Returns true if the GL format is a depth+stencil format
    bool isDepthStencilFormat(GLenum format);

    // Returns the corresponding source format and type for the given internal format
    void getDepthFormatSourceFormatAndType(GLenum internalFormat, GLenum& sourceFormat, GLenum& sourceType);

    // Converts depth-stencil formats to their corresponding depth formats.
    GLenum getDepthFormatOfDepthStencilFormat(GLenum internalFormat);

    // Brief wrapper around an osg::Depth that applies the reversed depth function when a reversed depth buffer is in
    // use
    class AutoDepth : public osg::Depth
    {
    public:
        AutoDepth(
            // NB: OSG uses LESS test function by default, Morrowind uses LEQUAL
            osg::Depth::Function func = osg::Depth::LEQUAL, double zNear = 0.0, double zFar = 1.0,
            bool writeMask = true)
        {
            setFunction(func);
            setZNear(zNear);
            setZFar(zFar);
            setWriteMask(writeMask);
        }

        AutoDepth(const osg::Depth& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY)
            : osg::Depth(copy, copyop)
        {
        }

        osg::Object* cloneType() const override { return new AutoDepth; }
        osg::Object* clone(const osg::CopyOp& copyop) const override { return new AutoDepth(*this, copyop); }

        void apply(osg::State& state) const override
        {
            glDepthFunc(static_cast<GLenum>(AutoDepth::isReversed() ? getReversedDepthFunction() : getFunction()));
            glDepthMask(static_cast<GLboolean>(getWriteMask()));
#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE) || defined(OSG_GLES3_AVAILABLE)
            glDepthRangef(getZNear(), getZFar());
#else
            glDepthRange(getZNear(), getZFar());
#endif
        }

        static void setReversed(bool reverseZ)
        {
            static bool init = false;

            if (!init)
            {
                AutoDepth::sReversed = reverseZ;
                init = true;
            }
        }

        static bool isReversed()
        {
            return AutoDepth::sReversed;
        }

        static void setDepthFormat(GLenum format);

        static GLenum depthInternalFormat()
        {
            return AutoDepth::sDepthInternalFormat;
        }

        static GLenum depthSourceFormat()
        {
            return AutoDepth::sDepthSourceFormat;
        }

        static GLenum depthSourceType()
        {
            return AutoDepth::sDepthSourceType;
        }

    private:
        static inline bool sReversed = false;
        static inline GLenum sDepthSourceFormat = GL_DEPTH_COMPONENT;
        static inline GLenum sDepthInternalFormat = GL_DEPTH_COMPONENT24;
        static inline GLenum sDepthSourceType = GL_UNSIGNED_INT;

        osg::Depth::Function getReversedDepthFunction() const
        {
            const osg::Depth::Function func = getFunction();

            switch (func)
            {
                case osg::Depth::LESS:
                    return osg::Depth::GREATER;
                case osg::Depth::LEQUAL:
                    return osg::Depth::GEQUAL;
                case osg::Depth::GREATER:
                    return osg::Depth::LESS;
                case osg::Depth::GEQUAL:
                    return osg::Depth::LEQUAL;
                default:
                    return func;
            }
        }
    };

    // Replaces all nodes osg::Depth state attributes with SceneUtil::AutoDepth.
    class ReplaceDepthVisitor : public osg::NodeVisitor
    {
    public:
        ReplaceDepthVisitor()
            : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
        {
        }

        void apply(osg::Node& node) override
        {
            osg::StateSet* stateSet = node.getStateSet();

            if (stateSet)
            {
                if (osg::Depth* depth = static_cast<osg::Depth*>(stateSet->getAttribute(osg::StateAttribute::DEPTH)))
                    stateSet->setAttribute(new SceneUtil::AutoDepth(*depth));
            };

            traverse(node);
        }
    };

    class SelectDepthFormatOperation : public osg::GraphicsOperation
    {
    public:
        SelectDepthFormatOperation()
            : GraphicsOperation("SelectDepthFormatOperation", false)
        {
        }

        void operator()(osg::GraphicsContext* graphicsContext) override;

        void setSupportedFormats(const std::vector<GLenum>& supportedFormats) { mSupportedFormats = supportedFormats; }

    private:
        std::vector<GLenum> mSupportedFormats;
    };
}

#endif