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     @remarks
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         MaterialPtr mMaterial;
57         RenderOperation mRenderOp;
58         ShadowRenderable* mLightCap; /// Used only if isLightCapSeparate == true
59     public:
ShadowRenderable()60         ShadowRenderable() : mMaterial(), mLightCap(0) {}
~ShadowRenderable()61         virtual ~ShadowRenderable() { delete mLightCap; }
62         /** Set the material to be used by the shadow, should be set by the caller
63             before adding to a render queue
64         */
setMaterial(const MaterialPtr & mat)65         void setMaterial(const MaterialPtr& mat) { mMaterial = mat; }
66         /// @copydoc Renderable::getMaterial
getMaterial(void)67         const MaterialPtr& getMaterial(void) const { return mMaterial; }
68         /// @copydoc Renderable::getRenderOperation
getRenderOperation(RenderOperation & op)69         void getRenderOperation(RenderOperation& op) { op = mRenderOp; }
70         /// Get the internal render operation for set up.
getRenderOperationForUpdate(void)71         RenderOperation* getRenderOperationForUpdate(void) {return &mRenderOp;}
72         /// @copydoc Renderable::getWorldTransforms
73         void getWorldTransforms(Matrix4* xform) const = 0;
74         /// @copydoc Renderable::getSquaredViewDepth
getSquaredViewDepth(const Camera *)75         Real getSquaredViewDepth(const Camera*) const{ return 0; /* not used */}
76         /// @copydoc Renderable::getLights
77         const LightList& getLights(void) const;
78         /** Does this renderable require a separate light cap?
79         @remarks
80             If possible, the light cap (when required) should be contained in the
81             usual geometry of the shadow renderable. However, if for some reason
82             the normal depth function (less than) could cause artefacts, then a
83             separate light cap with a depth function of 'always fail' can be used
84             instead. The primary example of this is when there are floating point
85             inaccuracies caused by calculating the shadow geometry separately from
86             the real geometry.
87         */
isLightCapSeparate(void)88         bool isLightCapSeparate(void) const { return mLightCap != 0; }
89 
90         /// Get the light cap version of this renderable.
getLightCapRenderable(void)91         ShadowRenderable* getLightCapRenderable(void) { return mLightCap; }
92         /// Should this ShadowRenderable be treated as visible?
isVisible(void)93         virtual bool isVisible(void) const { return true; }
94 
95         /** This function informs the shadow renderable that the global index buffer
96             from the SceneManager has been updated. As all shadow use this buffer their pointer
97             must be updated as well.
98         @param indexBuffer
99             Pointer to the new index buffer.
100         */
101         virtual void rebindIndexBuffer(const HardwareIndexBufferSharedPtr& indexBuffer) = 0;
102 
103     };
104 
105     /** A set of flags that can be used to influence ShadowRenderable creation. */
106     enum ShadowRenderableFlags
107     {
108         /// For shadow volume techniques only, generate a light cap on the volume.
109         SRF_INCLUDE_LIGHT_CAP = 0x00000001,
110         /// For shadow volume techniques only, generate a dark cap on the volume.
111         SRF_INCLUDE_DARK_CAP  = 0x00000002,
112         /// For shadow volume techniques only, indicates volume is extruded to infinity.
113         SRF_EXTRUDE_TO_INFINITY  = 0x00000004
114     };
115 
116     /** This class defines the interface that must be implemented by shadow casters.
117     */
118     class _OgreExport ShadowCaster
119     {
120     public:
~ShadowCaster()121         virtual ~ShadowCaster() { }
122         /** Returns whether or not this object currently casts a shadow. */
123         virtual bool getCastShadows(void) const = 0;
124 
125         /** Returns details of the edges which might be used to determine a silhouette. */
126         virtual EdgeData* getEdgeList(void) = 0;
127         /** Returns whether the object has a valid edge list. */
128         virtual bool hasEdgeList(void) = 0;
129 
130         /** Get the world bounding box of the caster. */
131         virtual const AxisAlignedBox& getWorldBoundingBox(bool derive = false) const = 0;
132         /** Gets the world space bounding box of the light cap. */
133         virtual const AxisAlignedBox& getLightCapBounds(void) const = 0;
134         /** Gets the world space bounding box of the dark cap, as extruded using the light provided. */
135         virtual const AxisAlignedBox& getDarkCapBounds(const Light& light, Real dirLightExtrusionDist) const = 0;
136 
137         typedef std::vector<ShadowRenderable*> ShadowRenderableList;
138         typedef VectorIterator<ShadowRenderableList> ShadowRenderableListIterator;
139 
140         /** Gets an iterator over the renderables required to render the shadow volume.
141         @remarks
142             Shadowable geometry should ideally be designed such that there is only one
143             ShadowRenderable required to render the the shadow; however this is not a necessary
144             limitation and it can be exceeded if required.
145         @param shadowTechnique
146             The technique being used to generate the shadow.
147         @param light
148             The light to generate the shadow from.
149         @param indexBuffer
150             The index buffer to build the renderables into,
151             the current contents are assumed to be disposable.
152         @param extrudeVertices
153             If @c true, this means this class should extrude
154             the vertices of the back of the volume in software. If false, it
155             will not be done (a vertex program is assumed).
156         @param extrusionDistance
157             The distance to extrude the shadow volume.
158         @param flags
159             Technique-specific flags, see ShadowRenderableFlags.
160         */
161         virtual ShadowRenderableListIterator getShadowVolumeRenderableIterator(
162             ShadowTechnique shadowTechnique, const Light* light,
163             HardwareIndexBufferSharedPtr* indexBuffer, size_t* indexBufferUsedSize,
164             bool extrudeVertices, Real extrusionDistance, unsigned long flags = 0 ) = 0;
165 
166         /** Common implementation of releasing shadow renderables.*/
167         static void clearShadowRenderableList(ShadowRenderableList& shadowRenderables);
168 
169         /** Utility method for extruding vertices based on a light.
170         @remarks
171             Unfortunately, because D3D cannot handle homogeneous (4D) position
172             coordinates in the fixed-function pipeline (GL can, but we have to
173             be cross-API), when we extrude in software we cannot extrude to
174             infinity the way we do in the vertex program (by setting w to
175             0.0f). Therefore we extrude by a fixed distance, which may cause
176             some problems with larger scenes. Luckily better hardware (ie
177             vertex programs) can fix this.
178         @param vertexBuffer
179             The vertex buffer containing ONLY xyz position
180             values, which must be originalVertexCount * 2 * 3 floats long.
181         @param originalVertexCount
182             The count of the original number of
183             vertices, i.e. the number in the mesh, not counting the doubling
184             which has already been done (by VertexData::prepareForShadowVolume)
185             to provide the extruded area of the buffer.
186         @param lightPos
187             4D light position in object space, when w=0.0f this
188             represents a directional light.
189         @param extrudeDist
190             The distance to extrude.
191         */
192         static void extrudeVertices(const HardwareVertexBufferSharedPtr& vertexBuffer,
193             size_t originalVertexCount, const Vector4& lightPos, Real extrudeDist);
194         /** Get the distance to extrude for a point/spot light. */
195         virtual Real getPointExtrusionDistance(const Light* l) const = 0;
196     protected:
197         /** Tells the caster to perform the tasks necessary to update the
198             edge data's light listing. Can be overridden if the subclass needs
199             to do additional things.
200         @param edgeData
201             The edge information to update.
202         @param lightPos
203             4D vector representing the light, a directional light has w=0.0.
204        */
205         virtual void updateEdgeListLightFacing(EdgeData* edgeData,
206             const Vector4& lightPos);
207 
208         /** Generates the indexes required to render a shadow volume into the
209             index buffer which is passed in, and updates shadow renderables
210             to use it.
211         @param edgeData
212             The edge information to use.
213         @param indexBuffer
214             The buffer into which to write data into; current
215             contents are assumed to be discardable.
216         @param indexBufferUsedSize
217             If the rest of buffer is enough than it would be locked with
218             HBL_NO_OVERWRITE semantic and indexBufferUsedSize would be increased,
219             otherwise HBL_DISCARD would be used and indexBufferUsedSize would be reset.
220         @param light
221             The light, mainly for type info as silhouette calculations
222             should already have been done in updateEdgeListLightFacing
223         @param shadowRenderables
224             A list of shadow renderables which has
225             already been constructed but will need populating with details of
226             the index ranges to be used.
227         @param flags
228             Additional controller flags, see ShadowRenderableFlags.
229         */
230         virtual void generateShadowVolume(EdgeData* edgeData,
231             const HardwareIndexBufferSharedPtr& indexBuffer, size_t& indexBufferUsedSize,
232             const Light* light, ShadowRenderableList& shadowRenderables, unsigned long flags);
233         /** Utility method for extruding a bounding box.
234         @param box
235             Original bounding box, will be updated in-place.
236         @param lightPos
237             4D light position in object space, when w=0.0f this
238             represents a directional light.
239         @param extrudeDist
240             The distance to extrude.
241         */
242         virtual void extrudeBounds(AxisAlignedBox& box, const Vector4& lightPos,
243             Real extrudeDist) const;
244 
245 
246     };
247     /** @} */
248     /** @} */
249 } // namespace Ogre
250 #include "OgreHeaderSuffix.h"
251 
252 #endif // __ShadowCaster_H__
253