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