Coverage Report

Created: 2025-10-10 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/include/OgreShadowCaster.h
Line
Count
Source
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
    (Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
15
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
18
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
THE SOFTWARE.
26
-----------------------------------------------------------------------------
27
*/
28
#ifndef __ShadowCaster_H__
29
#define __ShadowCaster_H__
30
31
#include "OgrePrerequisites.h"
32
#include "OgreRenderable.h"
33
#include "OgreRenderOperation.h"
34
#include "OgreHeaderPrefix.h"
35
36
37
namespace Ogre {
38
39
    /** \addtogroup Core
40
    *  @{
41
    */
42
    /** \addtogroup Scene
43
    *  @{
44
    */
45
    /** Class which represents the renderable aspects of a set of shadow volume faces. 
46
47
        Note that for casters comprised of more than one set of vertex buffers (e.g. SubMeshes each
48
        using their own geometry), it will take more than one ShadowRenderable to render the 
49
        shadow volume. Therefore for shadow caster geometry, it is best to stick to one set of
50
        vertex buffers (not necessarily one buffer, but the positions for the entire geometry 
51
        should come from one buffer if possible)
52
    */
53
    class _OgreExport ShadowRenderable : public Renderable, public ShadowDataAlloc
54
    {
55
    protected:
56
        RenderOperation mRenderOp;
57
        MaterialPtr mMaterial;
58
        ShadowRenderable* mLightCap; /// Used only if isLightCapSeparate == true
59
        MovableObject* mParent;
60
        /// Shared link to position buffer.
61
        HardwareVertexBufferSharedPtr mPositionBuffer;
62
        /// Shared link to w-coord buffer (optional).
63
        HardwareVertexBufferSharedPtr mWBuffer;
64
    public:
65
0
        ShadowRenderable() : mLightCap(0) {}
66
        ShadowRenderable(MovableObject* parent, const HardwareIndexBufferSharedPtr& indexBuffer,
67
                         const VertexData* vertexData, bool createSeparateLightCap,
68
                         bool isLightCap = false);
69
        virtual ~ShadowRenderable();
70
        /** Set the material to be used by the shadow, should be set by the caller 
71
            before adding to a render queue
72
        */
73
0
        void setMaterial(const MaterialPtr& mat) { mMaterial = mat; }
74
0
        const MaterialPtr& getMaterial(void) const override { return mMaterial; }
75
0
        void getRenderOperation(RenderOperation& op) override { op = mRenderOp; }
76
        /// Get the internal render operation for set up.
77
0
        RenderOperation* getRenderOperationForUpdate(void) {return &mRenderOp;}
78
        void getWorldTransforms(Matrix4* xform) const override;
79
0
        Real getSquaredViewDepth(const Camera*) const override { return 0; /* not used */}
80
        const LightList& getLights(void) const override;
81
        /** Does this renderable require a separate light cap?
82
83
            If possible, the light cap (when required) should be contained in the
84
            usual geometry of the shadow renderable. However, if for some reason
85
            the normal depth function (less than) could cause artefacts, then a
86
            separate light cap with a depth function of 'always fail' can be used 
87
            instead. The primary example of this is when there are floating point
88
            inaccuracies caused by calculating the shadow geometry separately from
89
            the real geometry. 
90
        */
91
0
        bool isLightCapSeparate(void) const { return mLightCap != 0; }
92
93
        /// Get the light cap version of this renderable.
94
0
        ShadowRenderable* getLightCapRenderable(void) { return mLightCap; }
95
        /// Should this ShadowRenderable be treated as visible?
96
0
        virtual bool isVisible(void) const { return true; }
97
98
        /** This function informs the shadow renderable that the global index buffer
99
            from the SceneManager has been updated. As all shadow use this buffer their pointer 
100
            must be updated as well.
101
        @param indexBuffer
102
            Pointer to the new index buffer.
103
        */
104
        void rebindIndexBuffer(const HardwareIndexBufferSharedPtr& indexBuffer);
105
106
0
        const HardwareVertexBufferSharedPtr& getPositionBuffer(void) const { return mPositionBuffer; }
107
    };
108
109
    /** A set of flags that can be used to influence ShadowRenderable creation. */
110
    enum ShadowRenderableFlags
111
    {
112
        /// For shadow volume techniques only, generate a light cap on the volume.
113
        SRF_INCLUDE_LIGHT_CAP = 0x00000001,
114
        /// For shadow volume techniques only, generate a dark cap on the volume.
115
        SRF_INCLUDE_DARK_CAP  = 0x00000002,
116
        /// For shadow volume techniques only, indicates volume is extruded to infinity.
117
        SRF_EXTRUDE_TO_INFINITY  = 0x00000004,
118
        /// For shadow volume techniques only, indicates hardware extrusion is not supported.
119
        SRF_EXTRUDE_IN_SOFTWARE  = 0x00000008,
120
    };
121
122
    typedef std::vector<ShadowRenderable*> ShadowRenderableList;
123
124
    /** This class defines the interface that must be implemented by shadow casters.
125
    */
126
    class _OgreExport ShadowCaster
127
    {
128
    public:
129
0
        virtual ~ShadowCaster() { }
130
        /** Returns whether or not this object currently casts a shadow. */
131
        virtual bool getCastShadows(void) const = 0;
132
133
        /** Returns details of the edges which might be used to determine a silhouette. */
134
0
        virtual EdgeData* getEdgeList(void) { return NULL; }
135
        /** Returns whether the object has a valid edge list. */
136
0
        bool hasEdgeList() { return getEdgeList() != NULL; }
137
138
        /** Get the world bounding box of the caster. */
139
        virtual const AxisAlignedBox& getWorldBoundingBox(bool derive = false) const = 0;
140
        /** Gets the world space bounding box of the light cap. */
141
0
        const AxisAlignedBox& getLightCapBounds(void) const { return getWorldBoundingBox(); }
142
        /** Gets the world space bounding box of the dark cap, as extruded using the light provided. */
143
        const AxisAlignedBox& getDarkCapBounds(const Light& light, Real dirLightExtrusionDist) const;
144
145
        typedef Ogre::ShadowRenderableList ShadowRenderableList;
146
        typedef VectorIterator<ShadowRenderableList> ShadowRenderableListIterator;
147
148
        /** Gets an list of the renderables required to render the shadow volume.
149
150
            Shadowable geometry should ideally be designed such that there is only one
151
            ShadowRenderable required to render the the shadow; however this is not a necessary
152
            limitation and it can be exceeded if required.
153
        @param light
154
            The light to generate the shadow from.
155
        @param indexBuffer
156
            The index buffer to build the renderables into, 
157
            the current contents are assumed to be disposable.
158
        @param indexBufferUsedSize
159
            If the rest of buffer is enough than it would be locked with
160
            HBL_NO_OVERWRITE semantic and indexBufferUsedSize would be increased,
161
            otherwise HBL_DISCARD would be used and indexBufferUsedSize would be reset.
162
        @param extrusionDistance
163
            The distance to extrude the shadow volume.
164
        @param flags
165
            Technique-specific flags, see ShadowRenderableFlags.
166
        */
167
        virtual const ShadowRenderableList&
168
        getShadowVolumeRenderableList(const Light* light, const HardwareIndexBufferPtr& indexBuffer,
169
                                      size_t& indexBufferUsedSize, float extrusionDistance,
170
                                      int flags = 0);
171
172
        /** Common implementation of releasing shadow renderables.*/
173
        static void clearShadowRenderableList(ShadowRenderableList& shadowRenderables);
174
175
        /** Utility method for extruding vertices based on a light. 
176
177
            Unfortunately, because D3D cannot handle homogeneous (4D) position
178
            coordinates in the fixed-function pipeline (GL can, but we have to
179
            be cross-API), when we extrude in software we cannot extrude to 
180
            infinity the way we do in the vertex program (by setting w to
181
            0.0f). Therefore we extrude by a fixed distance, which may cause 
182
            some problems with larger scenes. Luckily better hardware (ie
183
            vertex programs) can fix this.
184
        @param vertexBuffer
185
            The vertex buffer containing ONLY xyz position
186
            values, which must be originalVertexCount * 2 * 3 floats long.
187
        @param originalVertexCount
188
            The count of the original number of
189
            vertices, i.e. the number in the mesh, not counting the doubling
190
            which has already been done (by VertexData::prepareForShadowVolume)
191
            to provide the extruded area of the buffer.
192
        @param lightPos
193
            4D light position in object space, when w=0.0f this
194
            represents a directional light.
195
        @param extrudeDist
196
            The distance to extrude.
197
        */
198
        static void extrudeVertices(const HardwareVertexBufferSharedPtr& vertexBuffer, 
199
            size_t originalVertexCount, const Vector4& lightPos, Real extrudeDist);
200
        /** Get the distance to extrude for a point/spot light. */
201
        virtual Real getPointExtrusionDistance(const Light* l) const = 0;
202
    protected:
203
        /** Tells the caster to perform the tasks necessary to update the 
204
            edge data's light listing. Can be overridden if the subclass needs 
205
            to do additional things. 
206
        @param edgeData
207
            The edge information to update.
208
        @param lightPos
209
            4D vector representing the light, a directional light has w=0.0.
210
       */
211
        void updateEdgeListLightFacing(EdgeData* edgeData, const Vector4& lightPos);
212
213
        /** Generates the indexes required to render a shadow volume into the 
214
            index buffer which is passed in, and updates shadow renderables
215
            to use it.
216
        @param edgeData
217
            The edge information to use.
218
        @param indexBuffer
219
            The buffer into which to write data into; current 
220
            contents are assumed to be discardable.
221
        @param indexBufferUsedSize
222
            If the rest of buffer is enough than it would be locked with
223
            HBL_NO_OVERWRITE semantic and indexBufferUsedSize would be increased,
224
            otherwise HBL_DISCARD would be used and indexBufferUsedSize would be reset.
225
        @param light
226
            The light, mainly for type info as silhouette calculations
227
            should already have been done in updateEdgeListLightFacing
228
        @param shadowRenderables
229
            A list of shadow renderables which has 
230
            already been constructed but will need populating with details of
231
            the index ranges to be used.
232
        @param flags
233
            Additional controller flags, see ShadowRenderableFlags.
234
        */
235
        void generateShadowVolume(EdgeData* edgeData,
236
            const HardwareIndexBufferSharedPtr& indexBuffer, size_t& indexBufferUsedSize,
237
            const Light* light, ShadowRenderableList& shadowRenderables, unsigned long flags);
238
        /** Utility method for extruding a bounding box. 
239
        @param box
240
            Original bounding box, will be updated in-place.
241
        @param lightPos
242
            4D light position in object space, when w=0.0f this
243
            represents a directional light.
244
        @param extrudeDist
245
            The distance to extrude.
246
        */
247
        void extrudeBounds(AxisAlignedBox& box, const Vector4& lightPos, Real extrudeDist) const;
248
249
        /// World space AABB of this object's dark cap
250
        mutable AxisAlignedBox mWorldDarkCapBounds;
251
    };
252
    /** @} */
253
    /** @} */
254
} // namespace Ogre
255
#include "OgreHeaderSuffix.h"
256
257
#endif // __ShadowCaster_H__