/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__ |