TDME2  1.9.200
ShadowMap.cpp
Go to the documentation of this file.
2 
3 #include <memory>
4 #include <vector>
5 
6 #include <tdme/tdme.h>
12 #include <tdme/engine/Camera.h>
13 #include <tdme/engine/Engine.h>
14 #include <tdme/engine/Entity.h>
18 #include <tdme/engine/Light.h>
19 #include <tdme/engine/LODObject.h>
21 #include <tdme/engine/Object.h>
25 #include <tdme/engine/Partition.h>
26 #include <tdme/math/Math.h>
27 #include <tdme/math/Matrix4x4.h>
28 #include <tdme/math/Vector3.h>
29 
30 using std::make_unique;
31 using std::unique_ptr;
32 using std::vector;
33 
53 using tdme::math::Math;
56 
57 ShadowMap::ShadowMap(ShadowMapping* shadowMapping, int32_t width, int32_t height)
58 {
59  this->shadowMapping = shadowMapping;
60  lightCamera = make_unique<Camera>(shadowMapping->renderer);
61  lightCamera->setCameraMode(Camera::CAMERAMODE_NONE);
62  frameBuffer = make_unique<FrameBuffer>(width, height, FrameBuffer::FRAMEBUFFER_DEPTHBUFFER);
63  if (shadowMapping->renderer->getRendererType() == Renderer::RENDERERTYPE_VULKAN) {
65  0.5f, 0.0f, 0.0f, 0.0f,
66  0.0f, -0.5f, 0.0f, 0.0f,
67  0.0f, 0.0f, 0.5f, 0.0f,
68  0.5f, 0.5f, 0.5f, 1.0f
69  );
70  } else {
72  0.5f, 0.0f, 0.0f, 0.0f,
73  0.0f, 0.5f, 0.0f, 0.0f,
74  0.0f, 0.0f, 0.5f, 0.0f,
75  0.5f, 0.5f, 0.5f, 1.0f
76  );
77  }
79 }
80 
82 }
83 
85 {
86  frameBuffer->initialize();
87 }
88 
89 void ShadowMap::reshape(int32_t width, int32_t height)
90 {
91 }
92 
94 {
95  frameBuffer->dispose();
96 }
97 
99 {
100  frameBuffer->bindDepthBufferTexture(contextIdx);
101 }
102 
104 {
105  return lightCamera.get();
106 }
107 
109 {
110  // use default context
111  auto contextIdx = shadowMapping->renderer->CONTEXTINDEX_DEFAULT;
112 
113  //
114  auto camera = shadowMapping->engine->getCamera();
115 
116  //
117  auto lightDirection = light->getSpotDirection().clone().normalize();
118 
119  // directional lights
120  if (light->isDirectional() == true) {
121  // try to determine light position
122  // left
123  auto left = camera->getModelViewProjectionInvertedMatrix().multiply(
124  Vector4(
125  (2.0f * 0.0f) - 1.0f,
126  1.0f - (2.0f * 0.5f),
127  2.0f * 0.997f - 1.0f,
128  1.0f
129  )
130  );
131  left.scale(1.0f / left.getW());
132 
133  // right
134  auto right = camera->getModelViewProjectionInvertedMatrix().multiply(
135  Vector4(
136  (2.0f * 1.0f) - 1.0f,
137  1.0f - (2.0f * 0.5f),
138  2.0f * 0.997f - 1.0f,
139  1.0f
140  )
141  );
142  right.scale(1.0f / right.getW());
143 
144  // center
145  auto center4 = camera->getModelViewProjectionInvertedMatrix().multiply(
146  Vector4(
147  (2.0f * 0.5f) - 1.0f,
148  1.0f - (2.0f * 1.0f),
149  2.0f * 0.5f - 1.0f,
150  1.0f
151  )
152  );
153  center4.scale(1.0f / center4.getW());
154 
155  // so we get some contraints for the shadow map camera, TODO: improve me
156  Vector3 center(Vector3(center4.getX(), center4.getY(), center4.getZ()));
157  auto width = Vector3(right.getX(), right.getY(), right.getZ()).sub(Vector3(left.getX(), left.getY(), left.getZ())).computeLength() * shadowMapping->engine->getShadowMapLightEyeDistanceScale();
158 
159  // light camera
160  // compute camera from view of light
161  auto lightLookFrom = center.clone().sub(lightDirection.clone().scale(width * 0.5f));
162 
163  // set up light camera from view of light
164  Vector3 lightCameraUpVector;
165  Vector3 lightCameraSideVector;
167  lightCamera->setOrthographicFrustumScale((width / frameBuffer->getWidth()) / 1.25f);
168  lightCamera->setZNear(camera->getZNear());
169  lightCamera->setZFar(250.0f);
170  lightCamera->setLookFrom(lightLookFrom);
171  } else {
172  auto lightPosition = light->getPosition();
173  lightPosition.scale(1.0f / lightPosition.getW());
174  auto lightPosition3 = Vector3(lightPosition.getX(), lightPosition.getY(), lightPosition.getZ());
176  lightCamera->setZNear(camera->getZNear());
177  lightCamera->setZFar(150.0f);
178  lightCamera->setLookFrom(lightPosition3);
179  }
180 
181  //
182  lightCamera->setForwardVector(lightDirection);
183  lightCamera->setSideVector(Vector3(1.0f, 0.0f, 0.0f));
184  // TODO: fix cross product NaN if side vector == forward vector
185  auto lightCameraUpVector = Vector3::computeCrossProduct(lightCamera->getForwardVector(), lightCamera->getSideVector());
186  lightCamera->setUpVector(lightCameraUpVector);
187  auto lightCameraSideVector = Vector3::computeCrossProduct(lightCamera->getForwardVector(), lightCamera->getUpVector());
188  lightCamera->setSideVector(lightCameraSideVector);
189  lightCamera->setUpVector(lightCameraUpVector);
190  lightCamera->update(contextIdx, frameBuffer->getWidth(), frameBuffer->getHeight());
191  lightCamera->getFrustum()->update();
192 
193  // clear visible objects
194  visibleObjects.clear();
195 
196  // determine visible objects and objects that should generate a shadow
197  for (auto entity: shadowMapping->engine->getPartition()->getVisibleEntities(lightCamera->getFrustum())) {
198  switch (entity->getEntityType()) {
200  {
201  auto org = static_cast<ObjectRenderGroup*>(entity);
202  auto orgEntity = org->getEntity();
203  if (orgEntity != nullptr) {
204  if (orgEntity->isContributesShadows() == false) continue;
205  switch(orgEntity->getEntityType()) {
207  {
208  auto object = static_cast<Object*>(orgEntity);
209  visibleObjects.push_back(object);
210  }
211  break;
213  {
214  auto lodObject = static_cast<LODObject*>(orgEntity);
215  if (lodObject->isContributesShadows() == false) continue;
216  auto object = lodObject->getLODObject();
217  if (object != nullptr) {
218  visibleObjects.push_back(object);
219  }
220  }
221  break;
222  default:
223  break;
224  }
225  }
226  }
227  break;
229  {
230  auto object = static_cast<Object*>(entity);
231  if (object->isContributesShadows() == false) continue;
232  visibleObjects.push_back(object);
233  }
234  break;
236  {
237  auto lodObject = static_cast<LODObject*>(entity);
238  if (lodObject->isContributesShadows() == false) continue;
239  auto object = lodObject->getLODObject();
240  if (object != nullptr) visibleObjects.push_back(object);
241  }
242  break;
244  {
245  auto object = static_cast<ImposterObject*>(entity);
246  if (object->isContributesShadows() == false) continue;
247  visibleObjects.push_back(object->getBillboardObject());
248  }
249  break;
251  {
252  auto lodObjectImposter = static_cast<LODObjectImposter*>(entity);
253  if (lodObjectImposter->isContributesShadows() == false) continue;
254  auto object = lodObjectImposter->getLODObject();
255  if (object != nullptr) visibleObjects.push_back(object);
256  }
257  break;
259  {
260  auto opse = static_cast<ObjectParticleSystem*>(entity);
261  if (opse->isContributesShadows() == false) continue;
262  for (auto object: opse->getEnabledObjects()) visibleObjects.push_back(object);
263  }
264  break;
266  {
267  auto psg = static_cast<ParticleSystemGroup*>(entity);
268  for (auto ps: psg->getParticleSystems()) {
269  if (ps->getEntityType() != Entity::ENTITYTYPE_OBJECTPARTICLESYSTEM) continue;
270  auto opse = static_cast<ObjectParticleSystem*>(ps);
271  if (opse->isContributesShadows() == false) continue;
272  for (auto object: opse->getEnabledObjects()) visibleObjects.push_back(object);
273  }
274  }
275  break;
277  {
278  auto eh = static_cast<EntityHierarchy*>(entity);
279  if (eh->isContributesShadows() == false) continue;
280  for (auto entity: eh->getEntities()) {
281  if (entity->getEntityType() != Entity::ENTITYTYPE_OBJECT) continue;
282  auto object = static_cast<Object*>(entity);
283  if (object->isEnabled() == false) continue;
284  visibleObjects.push_back(object);
285  }
286  }
287  break;
288  default:
289  break;
290  }
291  }
292 
293  // bind frame buffer
294  frameBuffer->enableFrameBuffer();
295  // clear depth buffer
297  // generate shadow map texture matrix
299  // only draw opaque face entities as shadows will not be produced from transparent objects
300  for (auto i = 0; i < Entity::RENDERPASS_MAX; i++) {
301  auto renderPass = static_cast<Entity::RenderPass>(Math::pow(2, i));
303  renderPass,
305  false,
306  EntityRenderer::RENDERTYPE_TEXTUREARRAYS_DIFFUSEMASKEDTRANSPARENCY |
307  EntityRenderer::RENDERTYPE_TEXTURES_DIFFUSEMASKEDTRANSPARENCY
308  );
309  }
310 }
311 
313 {
314  // matrices
315  auto modelViewMatrix = shadowMapping->renderer->getModelViewMatrix();
316  auto projectionMatrix = shadowMapping->renderer->getProjectionMatrix();
317  // compute shadow texture matrix
318  depthBiasMVPMatrix.set(modelViewMatrix).multiply(projectionMatrix).multiply(biasMatrix);
319 }
320 
322 {
324 }
@ FRUSTUMMODE_ORTHOGRAPHIC
Definition: Camera.h:27
Engine main class.
Definition: Engine.h:131
Camera * getCamera()
Definition: Engine.h:1071
Partition * getPartition()
Definition: Engine.h:1085
float getShadowMapLightEyeDistanceScale()
Definition: Engine.h:715
Entity hierarchy to be used with engine class.
Engine entity.
Definition: Entity.h:30
static constexpr int RENDERPASS_MAX
Definition: Entity.h:83
@ ENTITYTYPE_OBJECTRENDERGROUP
Definition: Entity.h:96
@ ENTITYTYPE_OBJECTPARTICLESYSTEM
Definition: Entity.h:98
@ ENTITYTYPE_IMPOSTEROBJECT
Definition: Entity.h:91
@ ENTITYTYPE_PARTICLESYSTEMGROUP
Definition: Entity.h:99
@ ENTITYTYPE_LODOBJECTIMPOSTER
Definition: Entity.h:94
@ ENTITYTYPE_ENTITYHIERARCHY
Definition: Entity.h:89
Frame buffer class.
Definition: FrameBuffer.h:22
static constexpr int32_t FRAMEBUFFER_DEPTHBUFFER
Definition: FrameBuffer.h:25
Imposter object to be used with engine class.
LOD object + imposter to be used with engine class.
LOD object to be used with engine class.
Definition: LODObject.h:49
Object * getLODObject()
Definition: LODObject.h:166
Light representation.
Definition: Light.h:33
const Vector3 & getSpotDirection() const
Definition: Light.h:154
bool isDirectional() const
Returns if light is directional light like sun, moon lights.
Definition: Light.h:313
const Vector4 & getPosition() const
Definition: Light.h:139
Object particle system entity to be used with engine class.
Object render group for static objects that might be animated by shaders.
Object to be used with engine class.
Definition: Object.h:60
Particle system group, which combines several particle systems into a group, to be used with engine c...
Axis aligned bounding box used for frustum, this is not directly connectable with physics engine.
Definition: BoundingBox.h:26
Line segment helper functions.
Definition: LineSegment.h:16
virtual void clear(int32_t mask)=0
Clear render buffer with given mask.
void render(Entity::RenderPass renderPass, const vector< Object * > &objects, bool renderTransparentFaces, int32_t renderTypes)
Renders all given objects.
void reshape(int32_t width, int32_t height)
Reshape frame buffer.
Definition: ShadowMap.cpp:89
void updateDepthBiasMVPMatrix(int contextIdx)
Set up shadow texture matrix computed and stored before.
Definition: ShadowMap.cpp:321
void dispose()
Disposes this shadow map.
Definition: ShadowMap.cpp:93
void computeDepthBiasMVPMatrix()
Computes shadow texture matrix and stores it.
Definition: ShadowMap.cpp:312
void createShadowMap(Light *light)
Create shadow map.
Definition: ShadowMap.cpp:108
void bindDepthBufferTexture(int contextIdx)
Binds frame buffer depth texture.
Definition: ShadowMap.cpp:98
void updateDepthBiasMVPMatrix(int contextIdx, Matrix4x4 &depthBiasMVPMatrix)
Update depth bias mvp matrix with given matrix.
Standard math functions.
Definition: Math.h:19
Matrix4x4 class representing matrix4x4 mathematical structure and operations for 3d space.
Definition: Matrix4x4.h:23
Matrix4x4 & identity()
Creates identity matrix.
Definition: Matrix4x4.h:158
Vector3 multiply(const Vector3 &vector3) const
Multiplies this matrix with vector3.
Definition: Matrix4x4.h:225
Matrix4x4 & set(float r0c0, float r0c1, float r0c2, float r0c3, float r1c0, float r1c1, float r1c2, float r1c3, float r2c0, float r2c1, float r2c2, float r2c3, float r3c0, float r3c1, float r3c2, float r3c3)
Sets this matrix by its components.
Definition: Matrix4x4.h:108
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Definition: Vector3.h:20
float computeLength() const
Definition: Vector3.h:274
Vector3 clone() const
Clones this vector3.
Definition: Vector3.h:374
Vector3 & sub(float scalar)
Subtracts a scalar.
Definition: Vector3.h:177
Vector3 & scale(float scalar)
Scales by scalar.
Definition: Vector3.h:201
Vector3 & normalize()
Normalizes this vector3.
Definition: Vector3.h:239
Vector4 class representing vector4 mathematical structure and operations with x, y,...
Definition: Vector4.h:22
Vector4 & scale(float scalar)
Scales this vector4.
Definition: Vector4.h:264
Partition interface.
Definition: Partition.h:18
virtual const vector< Entity * > & getVisibleEntities(Frustum *frustum)=0
Get visible entities.