SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLShadowMap.cpp
Go to the documentation of this file.
1 /**
2  * \file SLShadowMap.cpp
3  * \date May 2020
4  * \remarks Please use clangformat to format the code. See more code style on
5  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
6  * \authors Michael Schertenleib, Marcus Hudritsch
7  * \copyright http://opensource.org/licenses/GPL-3.0
8 */
9 
10 #include <algorithm>
11 
12 #include <SLGLDepthBuffer.h>
13 #include <SLGLProgramManager.h>
14 #include <SLGLState.h>
15 #include <SLGLVertexArrayExt.h>
16 #include <SLLight.h>
17 #include <SLMaterial.h>
18 #include <SLShadowMap.h>
19 #include <Profiler.h>
20 #include <SLSceneView.h>
21 #include <SLCamera.h>
22 #include <SLFrustum.h>
23 #include <SLNodeLOD.h>
24 #include <SLLightSpot.h>
25 #include <SLLightRect.h>
26 #include <SLLightDirect.h>
27 
28 //-----------------------------------------------------------------------------
29 SLuint SLShadowMap::drawCalls = 0; //!< NO. of draw calls for shadow mapping
30 //-----------------------------------------------------------------------------
31 /*! Ctor for standard fixed size shadow map for any type of light
32  * \param light Pointer to the light for which the shadow is created
33  * \param lightClipNear The light frustums near clipping distance
34  * \param lightClipFar The light frustums near clipping distance
35  * \param size Ignored for rectangular lights
36  * \param texSize Shadow texture map size
37  */
39  float lightClipNear,
40  float lightClipFar,
41  const SLVec2f& size,
42  const SLVec2i& texSize)
43 {
44  assert(light && "SLShadowMap::SLShadowMap: No light passed");
45  assert(lightClipFar > lightClipNear &&
46  "SLShadowMap::SLShadowMap: Invalid clip distances passed");
47 
49 
50  if (typeid(*light) == typeid(SLLightDirect))
52  else if (typeid(*light) == typeid(SLLightSpot))
54  else if (typeid(*light) == typeid(SLLightRect))
56  else
57  SL_EXIT_MSG("SLShadowMap::SLShadowMap: Unknown light type");
58 
59  _light = light;
60  _useCubemap = false;
61  _useCascaded = false;
63  _frustumVAO = nullptr;
64  _rayCount = SLVec2i(0, 0);
65  _material = nullptr;
68  _size = size;
69  _halfSize = _size / 2;
70  _textureSize = texSize;
71  _camera = nullptr;
72  _numCascades = 0;
73 }
74 //-----------------------------------------------------------------------------
75 /*! Ctor for auto sized cascaded shadow mapping
76  * \param light Pointer to the light for which the shadow is created
77  * \param camera Pointer to the camera for witch the shadow map gets sized
78  * \param texSize Shadow texture map size (equal for all cascades)
79  * \param numCascades NO. of cascades for cascaded shadow mapping
80  */
82  SLCamera* camera,
83  const SLVec2i& texSize,
84  int numCascades)
85 {
86  assert(light && "SLShadowMap::SLShadowMap: No light passed");
87  assert(camera && "SLShadowMap::SLShadowMap: No camera passed");
88  assert(numCascades >= 0 && numCascades <= 5 &&
89  "SLShadowMap::SLShadowMap: Invalid NO.of cascades (0-5)");
90 
92 
93  if (typeid(*light) == typeid(SLLightDirect))
95  else
96  SL_EXIT_MSG("Auto sized shadow maps only exist for directional lights yet.");
97 
98  _light = light;
99  _useCubemap = false;
100  _useCascaded = true;
102  _frustumVAO = nullptr;
103  _rayCount = SLVec2i(0, 0);
104  _material = nullptr;
105  _camera = camera;
108  _textureSize = texSize;
109  _size = SLVec2f(0, 0); // will be ignored and automatically calculated
110  _halfSize = SLVec2f(0, 0); // will be ignored and automatically calculated
111  _lightClipNear = 0.1f; // will be ignored and automatically calculated
112  _lightClipFar = 20.f; // will be ignored and automatically calculated
113  _cascadesFactor = 30.f;
114 }
115 //-----------------------------------------------------------------------------
117 {
118  _depthBuffers.erase(_depthBuffers.begin(), _depthBuffers.end());
119  delete _frustumVAO;
120  delete _material;
121 }
122 //-----------------------------------------------------------------------------
123 //! SLShadowMap::drawFrustum draws the volume affected by the shadow map
125 {
126  // clang-format off
127  static SLVVec3f P = {
128  {-1, 1, -1}, { 1, 1, -1}, // lower rect
129  {-1, 1, -1}, {-1, 1, 1},
130  { 1, 1, 1}, {-1, 1, 1},
131  { 1, 1, 1}, { 1, 1, -1},
132 
133  {-1, -1, -1}, { 1, -1, -1}, // upper rect
134  {-1, -1, -1}, {-1, -1, 1},
135  { 1, -1, 1}, {-1, -1, 1},
136  { 1, -1, 1}, { 1, -1, -1},
137 
138  {-1, -1, -1}, {-1, 1, -1}, // vertical lines
139  { 1, -1, -1}, { 1, 1, -1},
140  {-1, -1, 1}, {-1, 1, 1},
141  { 1, -1, 1}, { 1, 1, 1},
142  };
143  // clang-format on
144 
145  if (_frustumVAO == nullptr)
146  {
149  }
150 
151  SLGLState* stateGL = SLGLState::instance();
152 
153  if (_useCascaded)
154  {
155  for (SLint i = 0; i < _numCascades; ++i)
156  {
157  // Inverse matrix in a way to avoid precision error
158  SLMat4f s, t;
159  s.scale(1.0f / _lightProj[i].m(0), 1.0f / _lightProj[i].m(5), 1.0f / _lightProj[i].m(10));
160  t.translate((-_lightProj[i].m(12)), (-_lightProj[i].m(13)), (-_lightProj[i].m(14)));
161 
162  stateGL->modelMatrix = _lightView[i].inverted() * s * t;
165  1.0f,
166  0,
167  (SLuint)P.size());
168  }
169  }
170  else
171  {
172  for (SLint i = 0; i < (_useCubemap ? 6 : 1); ++i)
173  {
174  stateGL->modelMatrix = _lightSpace[i].inverted();
177  1.0f,
178  0,
179  (SLuint)P.size());
180  }
181  }
182 }
183 
184 //-----------------------------------------------------------------------------
185 /*! SLShadowMap::drawRays draws sample rays of the light for visualization
186  * purpose only. Gets turned on when the light node is selected.
187  */
189 {
190 #ifndef SL_GLES // Reading the depth-buffer with GLES is non-trivial
191 
192  if (_useCubemap) return; // Not implemented for cubemaps
193  SLint w = _rayCount.x;
194  SLint h = _rayCount.y;
195  if (w == 0 || h == 0) return;
196 
197  SLGLState* stateGL = SLGLState::instance();
198  SLVVec3f P;
199 
200  _depthBuffers[0]->bind();
201 
202  SLfloat pixelWidth = (SLfloat)_textureSize.x / w;
203  SLfloat pixelHeight = (SLfloat)_textureSize.y / h;
204  SLfloat* depths = _depthBuffers[0]->readPixels();
205 
206  for (SLint x = 0; x < w; ++x)
207  {
208  for (SLint y = 0; y < h; ++y)
209  {
210  SLint pixelX = (SLint)(pixelWidth * (x + 0.5f));
211  SLint pixelY = (SLint)(pixelHeight * (y + 0.5f));
212  SLfloat viewSpaceX = Utils::lerp((x + 0.5f) / w, -1.0f, 1.0f);
213  SLfloat viewSpaceY = Utils::lerp((y + 0.5f) / h, -1.0f, 1.0f);
214  SLfloat depth = depths[pixelY * _depthBuffers[0]->dimensions().x + pixelX] * 2 - 1;
215  if (depth == 1.0f)
216  continue;
217  P.push_back(SLVec3f(viewSpaceX, viewSpaceY, -1.0f));
218  P.push_back(SLVec3f(viewSpaceX, viewSpaceY, depth));
219  }
220  }
221 
222  delete depths;
223  _depthBuffers[0]->unbind();
224  if (P.empty()) return;
225 
226  SLGLVertexArrayExt vao;
227  vao.generateVertexPos(&P);
228 
229  stateGL->modelMatrix = _lightSpace[0].inverted();
232  1.0f,
233  0,
234  (SLuint)P.size());
235 
236 #endif
237 }
238 //-----------------------------------------------------------------------------
239 //! SLShadowMap::updateLightSpaces updates a light view projection matrix
241 {
242  // Calculate FOV
243  SLfloat fov;
244 
246  {
247  fov = _light->spotCutOffDEG() * 2;
248 
249  // Automatically use cubemap when perspective projection makes no sense
250  if (fov >= 180.0f)
251  _useCubemap = true;
252 
253  if (_useCubemap)
254  fov = 90.0f;
255  }
256 
257  // Set view matrix
258  SLVec3f positionWS = _light->positionWS().vec3();
259 
260  if (_useCubemap)
261  {
262  _lightView[0].lookAt(positionWS, positionWS + SLVec3f::AXISX, -SLVec3f::AXISY);
263  _lightView[1].lookAt(positionWS, positionWS - SLVec3f::AXISX, -SLVec3f::AXISY);
264  _lightView[2].lookAt(positionWS, positionWS + SLVec3f::AXISY, SLVec3f::AXISZ);
265  _lightView[3].lookAt(positionWS, positionWS - SLVec3f::AXISY, -SLVec3f::AXISZ);
266  _lightView[4].lookAt(positionWS, positionWS + SLVec3f::AXISZ, -SLVec3f::AXISY);
267  _lightView[5].lookAt(positionWS, positionWS - SLVec3f::AXISZ, -SLVec3f::AXISY);
268  }
269  else
270  {
271  SLNode* node = dynamic_cast<SLNode*>(_light);
272  _lightView[0].lookAt(positionWS, positionWS + node->forwardWS(), node->upWS());
273  }
274 
275  // Set projection matrix
276  switch (_projection)
277  {
278  case P_monoOrthographic:
280  _halfSize.x,
281  -_halfSize.y,
282  _halfSize.y,
284  _lightClipFar);
285  break;
286 
287  case P_monoPerspective:
289  break;
290 
291  default:
292  SL_EXIT_MSG("Unsupported light projection");
293  }
294 
295  // Set the model-view-projection matrix
296  for (SLint i = 0; i < (_useCubemap ? 6 : 1); ++i)
297  _lightSpace[i] = _lightProj[0] * _lightView[i];
298 }
299 //-----------------------------------------------------------------------------
300 /*! Returns the visible nodes inside the light frustum
301  * Check if the passed node is inside the light frustum and add if so to the
302  * visibleNodes vector. The goal is to exit this function as fast as possible
303  * if the node is not visible from the light hence gets not lighted.
304  * \param node Node to cull or add to to visibleNodes vector
305  * \param lightProj The cascades light projection matrix that gets adapted
306  * \param lightView The cascades light view matrix
307  * \param lightFrustumPlanes The six light frustum planes
308  * \param visibleNodes Vector to push the lighted nodes
309  */
311  SLMat4f& lightProj,
312  SLMat4f& lightView,
313  SLPlane* lightFrustumPlanes,
314  SLVNode& visibleNodes)
315 {
316  assert(node &&
317  "SLShadowMap::lightCullingAdaptiveRec: No node passed.");
318  assert(node &&
319  "SLShadowMap::lightCullingAdaptiveRec: No lightFrustumPlanes passed.");
320 
321  // Exclude LOD level nodes
322  if (typeid(*node->parent()) == typeid(SLNodeLOD))
323  {
324  int levelForSM = node->levelForSM();
325  if (levelForSM == 0 && node->drawBit(SL_DB_HIDDEN))
326  return;
327  else // levelForSM > 0
328  {
329  if (node->parent()->children().size() < levelForSM)
330  {
331  SL_EXIT_MSG("SLShadowMap::lightCullingAdaptiveRec: levelForSM > num. LOD Nodes.");
332  }
333  SLNode* nodeForSM = node->parent()->children()[levelForSM - 1];
334  if (nodeForSM != node)
335  return;
336  }
337  }
338  else
339  {
340  if (node->drawBit(SL_DB_HIDDEN))
341  return;
342  }
343 
344  if (!node->castsShadows())
345  return;
346 
347  // We don't need to increase far plane distance
348  float distance = lightFrustumPlanes[5].distToPoint(node->aabb()->centerWS());
349  if (distance < -node->aabb()->radiusWS())
350  return;
351 
352  // Check the 4 side planes of the frustum
353  for (int i = 0; i < 4; i++)
354  {
355  distance = lightFrustumPlanes[i].distToPoint(node->aabb()->centerWS());
356  if (distance < -node->aabb()->radiusWS())
357  return;
358  }
359 
360  // If object is behind the light's near plane, move the near plane back
361  if (node->mesh()) // Don't add empty group nodes
362  {
363  distance = lightFrustumPlanes[4].distToPoint(node->aabb()->centerWS());
364  if (distance < node->aabb()->radiusWS())
365  {
366  float a = lightProj.m(10);
367  float b = lightProj.m(14);
368  float n = (b + 1.f) / a;
369  float f = (b - 1.f) / a;
370  n = n + (distance - node->aabb()->radiusWS());
371  lightProj.m(10, -2.f / (f - n));
372  lightProj.m(14, -(f + n) / (f - n));
373  SLFrustum::viewToFrustumPlanes(lightFrustumPlanes,
374  lightProj,
375  lightView);
376  }
377 
378  // If the node survived until now it can cast a shadow in this cascade
379  visibleNodes.push_back(node);
380  }
381 
382  // Now recursively cull the children nodes
383  for (SLNode* child : node->children())
385  lightProj,
386  lightView,
387  lightFrustumPlanes,
388  visibleNodes);
389 }
390 //-----------------------------------------------------------------------------
391 /*! SLShadowMap::drawNodesDirectionalCulling draw all nodes in the vector
392  * visibleNodes.
393  * \param visibleNodes Vector of visible nodes
394  * \param sv Pointer to the sceneview
395  * \param lightView The light view matrix
396  */
398  SLSceneView* sv,
399  SLMat4f& lightView)
400 {
401  SLGLState* stateGL = SLGLState::instance();
402 
403  for (SLNode* node : visibleNodes)
404  {
405  if (node->castsShadows() &&
406  node->mesh() &&
407  node->mesh()->primitive() >= GL_TRIANGLES)
408  {
409  stateGL->viewMatrix = lightView;
410  stateGL->modelMatrix = node->updateAndGetWM();
411  node->mesh()->drawIntoDepthBuffer(sv, node, _material);
413  }
414  }
415 }
416 //-----------------------------------------------------------------------------
417 /*! Recursive node drawing function for standard shadow map drawing.
418  * \param node The node do draw
419  * \param sv Pointer to the sceneview
420  * \param lightView The light view matrix
421  */
423  SLSceneView* sv,
424  SLMat4f& lightView)
425 {
426  assert(node && "SLShadowMap::drawNodesIntoDepthBufferRec: No node passed.");
427 
428  if (node->drawBit(SL_DB_HIDDEN))
429  return;
430  SLGLState* stateGL = SLGLState::instance();
431  stateGL->viewMatrix = lightView;
432  stateGL->modelMatrix = node->updateAndGetWM();
433 
434  if (node->castsShadows() &&
435  node->mesh() &&
436  node->mesh()->primitive() >= GL_TRIANGLES)
437  {
438  node->mesh()->drawIntoDepthBuffer(sv, node, _material);
440  }
441 
442  for (SLNode* child : node->children())
443  drawNodesIntoDepthBufferRec(child, sv, lightView);
444 }
445 //-----------------------------------------------------------------------------
446 /*! SLShadowMap::render Toplevel entry function for shadow map rendering.
447  * \param sv Pointer of the sceneview
448  * \param root Pointer to the root node of the scene
449  */
451 {
452  assert(root && "SLShadowMap::render: No root node passed.");
453 
455 
456  if (_projection == P_monoOrthographic && _camera != nullptr)
457  {
459  return;
460  }
461 
462  // Create Material
463  if (_material == nullptr)
464  _material = new SLMaterial(
465  nullptr,
466  "shadowMapMaterial",
467  nullptr,
468  nullptr,
469  nullptr,
470  nullptr,
472 
473  // Create depth buffer
474  static SLfloat borderColor[] = {1.0, 1.0, 1.0, 1.0};
475 
477 
478  if (this->_useCubemap)
479  this->_textureSize.y = this->_textureSize.x;
480 
481 #ifdef SL_GLES
482  SLint wrapMode = GL_CLAMP_TO_EDGE;
483 #else
484  SLint wrapMode = GL_CLAMP_TO_BORDER;
485 #endif
486 
487  if (_depthBuffers.size() != 0 &&
488  (_depthBuffers[0]->dimensions() != _textureSize ||
489  (_depthBuffers[0]->target() == GL_TEXTURE_CUBE_MAP) != _useCubemap))
490  {
491  _depthBuffers.erase(_depthBuffers.begin(), _depthBuffers.end());
492  }
493 
494  if (_depthBuffers.size() == 0)
495  {
497  GL_NEAREST,
498  GL_NEAREST,
499  wrapMode,
500  borderColor,
501  this->_useCubemap
502  ? GL_TEXTURE_CUBE_MAP
503  : GL_TEXTURE_2D));
504  }
505 
506  _depthBuffers[0]->bind();
507 
508  for (SLint i = 0; i < (_useCubemap ? 6 : 1); ++i)
509  {
510  if (_useCubemap)
511  _depthBuffers[0]->bindFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i);
512 
513  // Set OpenGL states
514  SLGLState* stateGL = SLGLState::instance();
515  stateGL->viewport(0, 0, _textureSize.x, _textureSize.y);
516  stateGL->viewMatrix = _lightView[i];
517  stateGL->projectionMatrix = _lightProj[0];
518  stateGL->clearColor(SLCol4f::BLACK);
519  stateGL->clearColorDepthBuffer();
520 
521  /////////////////////////////////////////////////////
523  /////////////////////////////////////////////////////
524  }
525 
526  _depthBuffers[0]->unbind();
527 }
528 //-----------------------------------------------------------------------------
529 /*! Returns a vector of near and far clip distances for all shadow cascades
530  * along the cameras view direction.
531  * \param numCascades NO. of cascades
532  * \param camClipNear The cameras near clipping distance
533  * \param camClipFar The cameras far clipping distance
534  * \return A SLVVec2f vector with the near and far clip distances
535  */
537  float camClipNear,
538  float camClipFar)
539 {
540  SLVVec2f cascades;
541 
542  float ni, fi = camClipNear;
543 
544  for (int i = 0; i < numCascades; i++)
545  {
546  ni = fi;
547  fi = _cascadesFactor *
548  camClipNear *
549  pow((camClipFar / (_cascadesFactor * camClipNear)),
550  (float)(i + 1) / (float)numCascades);
551 
552  cascades.push_back(SLVec2f(ni, fi));
553  }
554  return cascades;
555 }
556 //-----------------------------------------------------------------------------
557 /*! Renders the nodes into cascaded shadow maps for directional lights
558  * \param sv Pointer of the sceneview
559  * \param root Pointer to the root node of the scene
560  */
562  SLNode* root)
563 {
564  assert(root && "LShadowMap::renderDirectionalLightCascaded: no root node");
565 
566  // Create depth buffer
567  static SLfloat borderColor[] = {1.0, 1.0, 1.0, 1.0};
568 
569  // Create material
570  if (_material == nullptr)
571  _material = new SLMaterial(
572  nullptr,
573  "shadowMapMaterial",
574  nullptr,
575  nullptr,
576  nullptr,
577  nullptr,
579 
580  // Erase depth buffer textures if the number or size changed
581  if (_depthBuffers.size() != 0 &&
582  (_depthBuffers[0]->dimensions() != _textureSize ||
583  _depthBuffers[0]->target() != GL_TEXTURE_2D ||
584  _depthBuffers.size() != _numCascades))
585  {
586  _depthBuffers.erase(_depthBuffers.begin(), _depthBuffers.end());
587  }
588 
589  // Get the vector of cascades with near and far distances
591  _camera->clipNear(),
592  _camera->clipFar());
593 
594  SLMat4f camWM = _camera->updateAndGetWM(); // camera space in world space
595  SLNode* lightNode = dynamic_cast<SLNode*>(_light);
596 
597 #ifdef SL_GLES
598  SLint wrapMode = GL_CLAMP_TO_EDGE;
599 #else
600  SLint wrapMode = GL_CLAMP_TO_BORDER;
601 #endif
602 
603  // Create the depth buffer if they don't exist
604  if (_depthBuffers.size() == 0)
605  {
606  for (int i = 0; i < cascades.size(); i++)
608  GL_NEAREST,
609  GL_NEAREST,
610  wrapMode,
611  borderColor,
612  GL_TEXTURE_2D));
613  }
614 
615  // for all subdivision of frustum
616  for (int i = 0; i < cascades.size(); i++)
617  {
618  // The cascades near and far distance on the view direction in WS
619  float cn = cascades[i].x;
620  float cf = cascades[i].y;
621 
622  // The cascades middle point on the view direction in WS
623  SLVec3f cm = camWM.translation() - camWM.axisZ().normalized() * (cn + cf) * 0.5f;
624 
625  // Build the view matrix with lookAt method
626  SLMat4f lightViewMat; // world space to light space
627  lightViewMat.lookAt(cm, cm + lightNode->forwardWS(), lightNode->upWS());
628 
629  // Get the 8 camera frustum points in view space
630  SLVec3f camFrustumPoints[8];
631  SLFrustum::getPointsInViewSpace(camFrustumPoints,
632  _camera->fovV(),
633  sv->scrWdivH(),
634  cn,
635  cf);
636 
637  // Build min & max point of the cascades light frustum around the view frustum
638  float minx = FLT_MAX, maxx = FLT_MIN;
639  float miny = FLT_MAX, maxy = FLT_MIN;
640  float minz = FLT_MAX, maxz = FLT_MIN;
641  for (int j = 0; j < 8; j++)
642  {
643  SLVec3f fp = lightViewMat * camWM * camFrustumPoints[j];
644  if (fp.x < minx) minx = fp.x;
645  if (fp.y < miny) miny = fp.y;
646  if (fp.x > maxx) maxx = fp.x;
647  if (fp.y > maxy) maxy = fp.y;
648  if (fp.z < minz) minz = fp.z;
649  if (fp.z > maxz) maxz = fp.z;
650  }
651  float sx = 2.f / (maxx - minx);
652  float sy = 2.f / (maxy - miny);
653  float sz = -2.f / (maxz - minz);
654  SLVec3f t = SLVec3f(-0.5f * (maxx + minx),
655  -0.5f * (maxy + miny),
656  -0.5f * (maxz + minz));
657 
658  // Build orthographic light projection matrix
659  SLMat4f lightProjMat;
660  lightProjMat.scale(sx, sy, sz);
661  lightProjMat.translate(t);
662 
663  // Do light culling recursively with light frustum adaptation
664  SLPlane lightFrustumPlanes[6];
665  SLVNode visibleNodes;
666  SLFrustum::viewToFrustumPlanes(lightFrustumPlanes,
667  lightProjMat,
668  lightViewMat);
669  for (SLNode* child : root->children())
670  {
672  lightProjMat,
673  lightViewMat,
674  lightFrustumPlanes,
675  visibleNodes);
676  }
677 
678  _lightView[i] = lightViewMat;
679  _lightProj[i] = lightProjMat;
680  _lightSpace[i] = lightProjMat * lightViewMat;
681 
682  _depthBuffers[i]->bind();
683 
684  // Set OpenGL states for depth buffer rendering
685  SLGLState* stateGL = SLGLState::instance();
686  stateGL->viewport(0, 0, _textureSize.x, _textureSize.y);
687  stateGL->clearColor(SLCol4f::BLACK);
688  stateGL->clearColorDepthBuffer();
689  stateGL->projectionMatrix = lightProjMat;
690  stateGL->viewMatrix = lightViewMat;
691 
692  ////////////////////////////////////////////////////////////
693  drawNodesDirectionalCulling(visibleNodes, sv, lightViewMat);
694  ////////////////////////////////////////////////////////////
695 
696  _depthBuffers[i]->unbind();
697  }
698 }
699 //-----------------------------------------------------------------------------
#define PROFILE_FUNCTION()
Definition: Instrumentor.h:41
float SLfloat
Definition: SL.h:173
unsigned int SLuint
Definition: SL.h:171
#define SL_EXIT_MSG(message)
Definition: SL.h:240
int SLint
Definition: SL.h:170
#define SL_DB_HIDDEN
Flags an object as hidden.
Definition: SLDrawBits.h:20
@ P_monoPerspective
standard mono pinhole perspective projection
Definition: SLEnums.h:135
@ P_monoOrthographic
standard mono orthographic projection
Definition: SLEnums.h:137
Uses an OpenGL framebuffer object as a depth-buffer.
std::vector< SLGLDepthBuffer * > SLGLVDepthBuffer
@ PT_lines
Definition: SLGLEnums.h:32
@ SP_depth
Singleton class for global render state.
Extension class with functions for quick line & point drawing.
deque< SLNode * > SLVNode
SLVNode typedef for a vector of SLNodes.
Definition: SLNode.h:26
SLScene * s
Definition: SLScene.h:31
vector< SLVec2f > SLVVec2f
Definition: SLVec2.h:143
SLVec2< SLint > SLVec2i
Definition: SLVec2.h:140
SLVec2< SLfloat > SLVec2f
Definition: SLVec2.h:141
vector< SLVec3f > SLVVec3f
Definition: SLVec3.h:325
SLVec3< SLfloat > SLVec3f
Definition: SLVec3.h:318
SLVec3f centerWS()
Definition: SLAABBox.h:50
SLfloat radiusWS()
Definition: SLAABBox.h:51
Active or visible camera node class.
Definition: SLCamera.h:54
SLfloat fovV() const
Vertical field of view.
Definition: SLCamera.h:135
void clipFar(const SLfloat cFar)
Definition: SLCamera.h:109
void clipNear(const SLfloat cNear)
Definition: SLCamera.h:108
static void viewToFrustumPlanes(SLPlane *planes, const SLMat4f &projectionMat, const SLMat4f &viewMat)
Definition: SLFrustum.cpp:24
static void getPointsInViewSpace(SLVec3f *points, float fovV, float ratio, float clipNear, float clipFar)
Returns frustum points in view space.
Definition: SLFrustum.cpp:73
static SLGLProgramGeneric * get(SLStdShaderProg id)
Get program reference for given id.
Singleton class holding all OpenGL states.
Definition: SLGLState.h:71
void clearColor(const SLCol4f &c)
Definition: SLGLState.cpp:157
SLMat4f modelMatrix
Init all states.
Definition: SLGLState.h:89
void viewport(SLint x, SLint y, SLsizei width, SLsizei height)
Definition: SLGLState.cpp:378
static SLGLState * instance()
Public static instance getter for singleton pattern.
Definition: SLGLState.h:74
SLMat4f viewMatrix
matrix for the active cameras view transform
Definition: SLGLState.h:91
SLMat4f projectionMatrix
matrix for projection transform
Definition: SLGLState.h:90
void clearColorDepthBuffer()
Definition: SLGLState.h:123
SLGLVertexArray adds Helper Functions for quick Line & Point Drawing.
void generateVertexPos(SLVVec2f *p)
Adds or updates & generates a position vertex attribute for colored line or point drawing.
void drawArrayAsColored(SLGLPrimitiveType primitiveType, SLCol4f color, SLfloat lineOrPointSize=1.0f, SLuint indexFirstVertex=0, SLuint countVertices=0)
Draws the array as the specified primitive with the color.
SLLightDirect class for a directional light source.
Definition: SLLightDirect.h:40
Abstract Light class for OpenGL light sources.
Definition: SLLight.h:61
virtual SLVec4f positionWS() const =0
void spotCutOffDEG(SLfloat cutOffAngleDEG)
Definition: SLLight.cpp:92
Light node class for a rectangular light source.
Definition: SLLightRect.h:39
SLLightSpot class for a spot light source.
Definition: SLLightSpot.h:36
void scale(T sxyz)
Definition: SLMat4.h:667
SLVec3< T > translation() const
Definition: SLMat4.h:184
void lookAt(T EyeX, T EyeY, T EyeZ, T AtX=0, T AtY=0, T AtZ=0, T UpX=0, T UpY=0, T UpZ=0)
Defines the a view matrix as the corresponding gluLookAt function.
Definition: SLMat4.h:708
void ortho(T l, T r, T b, T t, T n, T f)
Defines a orthographic projection matrix with a field of view angle.
Definition: SLMat4.h:911
void m(int i, T val)
Definition: SLMat4.h:93
SLMat4< T > inverted() const
Computes the inverse of a 4x4 non-singular matrix.
Definition: SLMat4.h:1371
SLVec3< T > axisZ() const
Definition: SLMat4.h:187
void perspective(T fov, T aspect, T n, T f)
Defines a perspective projection matrix with a field of view angle.
Definition: SLMat4.h:874
void translate(T tx, T ty, T tz=0)
Definition: SLMat4.h:601
Defines a standard CG material with textures and a shader program.
Definition: SLMaterial.h:56
SLGLPrimitiveType primitive() const
Definition: SLMesh.h:179
void drawIntoDepthBuffer(SLSceneView *sv, SLNode *node, SLMaterial *depthMat)
Simplified drawing method for shadow map creation.
Definition: SLMesh.cpp:330
SLNode represents a node in a hierarchical scene graph.
Definition: SLNode.h:147
SLAABBox * aabb()
Definition: SLNode.h:301
SLVec3f upWS() const
Definition: SLNode.h:561
SLVNode & children()
Definition: SLNode.h:305
SLbool drawBit(SLuint bit)
Definition: SLNode.h:300
void parent(SLNode *p)
Definition: SLNode.cpp:600
const SLMat4f & updateAndGetWM() const
Definition: SLNode.cpp:703
SLMesh * mesh()
Definition: SLNode.h:304
void castsShadows(SLbool castsShadows)
Definition: SLNode.h:282
void levelForSM(SLubyte lfsm)
Definition: SLNode.h:288
SLVec3f forwardWS() const
Definition: SLNode.h:541
Level of detail (LOD) group node based on screen space coverage.
Definition: SLNodeLOD.h:28
Defines a plane in 3D space with the equation ax + by + cy + d = 0.
Definition: SLPlane.h:25
SLfloat distToPoint(const SLVec3f &p)
Returns distance between a point P and the plane.
Definition: SLPlane.h:51
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
SceneView class represents a dynamic real time 3D view onto the scene.
Definition: SLSceneView.h:69
SLfloat scrWdivH() const
Definition: SLSceneView.h:174
SLGLVDepthBuffer _depthBuffers
Vector of framebuffers with texture.
Definition: SLShadowMap.h:123
SLShadowMap(SLLight *light, const SLfloat lightClipNear=0.1f, const SLfloat lightClipFar=20.0f, const SLVec2f &size=SLVec2f(8, 8), const SLVec2i &texSize=SLVec2i(1024, 1024))
Ctor for standard fixed sized shadow mapping without cascades.
Definition: SLShadowMap.cpp:38
SLProjType _projection
Projection to use to create shadow map.
Definition: SLShadowMap.h:114
int numCascades()
Definition: SLShadowMap.h:87
SLbool _useCascaded
Flag if cascaded shadow maps should be used.
Definition: SLShadowMap.h:116
void renderDirectionalLightCascaded(SLSceneView *sv, SLNode *root)
SLMat4f _lightView[6]
Light view matrices.
Definition: SLShadowMap.h:120
SLint _numCascades
Number of cascades for directional light shadow mapping.
Definition: SLShadowMap.h:117
SLVec2i _rayCount
Amount of rays drawn by drawRays()
Definition: SLShadowMap.h:125
SLCamera * _camera
Camera to witch the light frustums are adapted.
Definition: SLShadowMap.h:132
void drawNodesIntoDepthBufferRec(SLNode *node, SLSceneView *sv, SLMat4f &lightView)
SLMaterial * _material
Material used to render the shadow map.
Definition: SLShadowMap.h:126
void updateLightSpaces()
SLShadowMap::updateLightSpaces updates a light view projection matrix.
SLint _maxCascades
Max. number of cascades for for which the shader gets generated.
Definition: SLShadowMap.h:118
static SLuint drawCalls
NO. of draw calls for shadow mapping.
Definition: SLShadowMap.h:92
SLMat4f _lightProj[6]
Light projection matrices.
Definition: SLShadowMap.h:121
SLGLVertexArrayExt * _frustumVAO
Visualization of light-space-frustum.
Definition: SLShadowMap.h:124
void drawFrustum()
SLShadowMap::drawFrustum draws the volume affected by the shadow map.
SLfloat _lightClipNear
Light frustum near clipping plane.
Definition: SLShadowMap.h:127
SLVec2f _halfSize
_size divided by two (only for SLLightDirect non cascaded)
Definition: SLShadowMap.h:130
SLVec2i _textureSize
Size of the shadow map texture.
Definition: SLShadowMap.h:131
SLMat4f _lightSpace[6]
Light space matrices (= _lightProj * _lightView)
Definition: SLShadowMap.h:122
SLfloat _cascadesFactor
Factor that determines the cascades distribution.
Definition: SLShadowMap.h:119
SLfloat lightClipNear()
Definition: SLShadowMap.h:83
SLfloat lightClipFar()
Definition: SLShadowMap.h:84
SLVec2f _size
Height and width of the frustum (only for SLLightDirect non cascaded)
Definition: SLShadowMap.h:129
void lightCullingAdaptiveRec(SLNode *node, SLMat4f &lightProj, SLMat4f &lightView, SLPlane *lightFrustumPlanes, SLVNode &visibleNodes)
void renderShadows(SLSceneView *sv, SLNode *root)
SLLight * _light
The light which uses this shadow map.
Definition: SLShadowMap.h:113
void drawRays()
SLfloat _lightClipFar
Light frustum far clipping plane.
Definition: SLShadowMap.h:128
SLVVec2f getShadowMapCascades(int numCascades, float camClipNear, float camClipFar)
void drawNodesDirectionalCulling(SLVNode visibleNodes, SLSceneView *sv, SLMat4f &lightView)
SLVec2f size()
Definition: SLShadowMap.h:85
SLCamera * camera()
Definition: SLShadowMap.h:90
SLbool _useCubemap
Flag if cubemap should be used for perspective projections.
Definition: SLShadowMap.h:115
T y
Definition: SLVec2.h:30
T x
Definition: SLVec2.h:30
T y
Definition: SLVec3.h:43
SLVec3 normalized() const
Definition: SLVec3.h:127
static SLVec3 AXISY
Definition: SLVec3.h:298
T x
Definition: SLVec3.h:43
static SLVec3 AXISX
Definition: SLVec3.h:297
T z
Definition: SLVec3.h:43
static SLVec3 AXISZ
Definition: SLVec3.h:299
static SLVec4 BLACK
Definition: SLVec4.h:213
static SLVec4 GREEN
Definition: SLVec4.h:217
SLVec3< T > vec3() const
Definition: SLVec4.h:111
static SLVec4 YELLOW
Definition: SLVec4.h:219
T lerp(T x, T a, T b)
Definition: Utils.h:255