SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLShadowMap Class Reference

Class for standard and cascaded shadow mapping. More...

#include <SLShadowMap.h>

Public Member Functions

 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. More...
 
 SLShadowMap (SLLight *light, SLCamera *camera, const SLVec2i &texSize=SLVec2i(1024, 1024), const SLint numCascades=4)
 Ctor for standard auto sized shadow mapping with cascades. More...
 
 ~SLShadowMap ()
 
void renderShadows (SLSceneView *sv, SLNode *root)
 
void drawFrustum ()
 SLShadowMap::drawFrustum draws the volume affected by the shadow map. More...
 
void drawRays ()
 
void useCubemap (SLbool useCubemap)
 
void rayCount (const SLVec2i &rayCount)
 
void clipNear (SLfloat clipNear)
 
void clipFar (SLfloat clipFar)
 
void size (const SLVec2f &size)
 
void textureSize (const SLVec2i &textureSize)
 
void numCascades (int numCascades)
 
void cascadesFactor (float factor)
 
SLProjType projection ()
 
SLbool useCubemap () const
 
SLbool useCascaded () const
 
SLMat4flightSpace ()
 
SLGLDepthBufferdepthBuffer ()
 
SLGLVDepthBuffer depthBuffers ()
 
SLVec2i rayCount ()
 
SLfloat lightClipNear ()
 
SLfloat lightClipFar ()
 
SLVec2f size ()
 
SLVec2i textureSize ()
 
int numCascades ()
 
int maxCascades ()
 
float cascadesFactor ()
 
SLCameracamera ()
 

Static Public Attributes

static SLuint drawCalls = 0
 NO. of draw calls for shadow mapping. More...
 

Private Member Functions

void updateLightSpaces ()
 SLShadowMap::updateLightSpaces updates a light view projection matrix. More...
 
void renderDirectionalLightCascaded (SLSceneView *sv, SLNode *root)
 
SLVVec2f getShadowMapCascades (int numCascades, float camClipNear, float camClipFar)
 
void drawNodesIntoDepthBufferRec (SLNode *node, SLSceneView *sv, SLMat4f &lightView)
 
void lightCullingAdaptiveRec (SLNode *node, SLMat4f &lightProj, SLMat4f &lightView, SLPlane *lightFrustumPlanes, SLVNode &visibleNodes)
 
void drawNodesDirectionalCulling (SLVNode visibleNodes, SLSceneView *sv, SLMat4f &lightView)
 

Private Attributes

SLLight_light
 The light which uses this shadow map. More...
 
SLProjType _projection
 Projection to use to create shadow map. More...
 
SLbool _useCubemap
 Flag if cubemap should be used for perspective projections. More...
 
SLbool _useCascaded
 Flag if cascaded shadow maps should be used. More...
 
SLint _numCascades
 Number of cascades for directional light shadow mapping. More...
 
SLint _maxCascades
 Max. number of cascades for for which the shader gets generated. More...
 
SLfloat _cascadesFactor
 Factor that determines the cascades distribution. More...
 
SLMat4f _lightView [6]
 Light view matrices. More...
 
SLMat4f _lightProj [6]
 Light projection matrices. More...
 
SLMat4f _lightSpace [6]
 Light space matrices (= _lightProj * _lightView) More...
 
SLGLVDepthBuffer _depthBuffers
 Vector of framebuffers with texture. More...
 
SLGLVertexArrayExt_frustumVAO
 Visualization of light-space-frustum. More...
 
SLVec2i _rayCount
 Amount of rays drawn by drawRays() More...
 
SLMaterial_material
 Material used to render the shadow map. More...
 
SLfloat _lightClipNear
 Light frustum near clipping plane. More...
 
SLfloat _lightClipFar
 Light frustum far clipping plane. More...
 
SLVec2f _size
 Height and width of the frustum (only for SLLightDirect non cascaded) More...
 
SLVec2f _halfSize
 _size divided by two (only for SLLightDirect non cascaded) More...
 
SLVec2i _textureSize
 Size of the shadow map texture. More...
 
SLCamera_camera
 Camera to witch the light frustums are adapted. More...
 

Detailed Description

Class for standard and cascaded shadow mapping.

Shadow mapping is a technique to render shadows. The scene gets rendered from the point of view of the lights which cast shadows. The resulting depth-map of that render-pass can be used to determine which fragments are affected by which lights. The standard fixed size shadow maps can be used with all light types. The auto sized shadow maps get automatically sized to a specified camera. At the moment only directional light get supported with multiple cascaded shadow maps.

Definition at line 38 of file SLShadowMap.h.

Constructor & Destructor Documentation

◆ SLShadowMap() [1/2]

SLShadowMap::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.

Ctor for standard fixed size shadow map for any type of light

Parameters
lightPointer to the light for which the shadow is created
lightClipNearThe light frustums near clipping distance
lightClipFarThe light frustums near clipping distance
sizeIgnored for rectangular lights
texSizeShadow texture map size

Definition at line 38 of file SLShadowMap.cpp.

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 }
#define PROFILE_FUNCTION()
Definition: Instrumentor.h:41
#define SL_EXIT_MSG(message)
Definition: SL.h:240
@ P_monoPerspective
standard mono pinhole perspective projection
Definition: SLEnums.h:135
@ P_monoOrthographic
standard mono orthographic projection
Definition: SLEnums.h:137
std::vector< SLGLDepthBuffer * > SLGLVDepthBuffer
SLVec2< SLint > SLVec2i
Definition: SLVec2.h:140
SLLightDirect class for a directional light source.
Definition: SLLightDirect.h:40
Light node class for a rectangular light source.
Definition: SLLightRect.h:39
SLLightSpot class for a spot light source.
Definition: SLLightSpot.h:36
SLGLVDepthBuffer _depthBuffers
Vector of framebuffers with texture.
Definition: SLShadowMap.h:123
SLProjType _projection
Projection to use to create shadow map.
Definition: SLShadowMap.h:114
SLbool _useCascaded
Flag if cascaded shadow maps should be used.
Definition: SLShadowMap.h:116
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
SLMaterial * _material
Material used to render the shadow map.
Definition: SLShadowMap.h:126
SLGLVertexArrayExt * _frustumVAO
Visualization of light-space-frustum.
Definition: SLShadowMap.h:124
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
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
SLLight * _light
The light which uses this shadow map.
Definition: SLShadowMap.h:113
SLfloat _lightClipFar
Light frustum far clipping plane.
Definition: SLShadowMap.h:128
SLVec2f size()
Definition: SLShadowMap.h:85
SLbool _useCubemap
Flag if cubemap should be used for perspective projections.
Definition: SLShadowMap.h:115

◆ SLShadowMap() [2/2]

SLShadowMap::SLShadowMap ( SLLight light,
SLCamera camera,
const SLVec2i texSize = SLVec2i(1024, 1024),
const SLint  numCascades = 4 
)

Ctor for standard auto sized shadow mapping with cascades.

Ctor for auto sized cascaded shadow mapping

Parameters
lightPointer to the light for which the shadow is created
cameraPointer to the camera for witch the shadow map gets sized
texSizeShadow texture map size (equal for all cascades)
numCascadesNO. of cascades for cascaded shadow mapping

Definition at line 81 of file SLShadowMap.cpp.

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 }
SLVec2< SLfloat > SLVec2f
Definition: SLVec2.h:141
int numCascades()
Definition: SLShadowMap.h:87
SLint _maxCascades
Max. number of cascades for for which the shader gets generated.
Definition: SLShadowMap.h:118
SLfloat _cascadesFactor
Factor that determines the cascades distribution.
Definition: SLShadowMap.h:119
SLCamera * camera()
Definition: SLShadowMap.h:90

◆ ~SLShadowMap()

SLShadowMap::~SLShadowMap ( )

Definition at line 116 of file SLShadowMap.cpp.

117 {
118  _depthBuffers.erase(_depthBuffers.begin(), _depthBuffers.end());
119  delete _frustumVAO;
120  delete _material;
121 }

Member Function Documentation

◆ camera()

SLCamera* SLShadowMap::camera ( )
inline

Definition at line 90 of file SLShadowMap.h.

90 { return _camera; }

◆ cascadesFactor() [1/2]

float SLShadowMap::cascadesFactor ( )
inline

Definition at line 89 of file SLShadowMap.h.

89 { return _cascadesFactor; }

◆ cascadesFactor() [2/2]

void SLShadowMap::cascadesFactor ( float  factor)
inline

Definition at line 73 of file SLShadowMap.h.

73 { _cascadesFactor = factor; }

◆ clipFar()

void SLShadowMap::clipFar ( SLfloat  clipFar)
inline

Definition at line 65 of file SLShadowMap.h.

void clipFar(SLfloat clipFar)
Definition: SLShadowMap.h:65

◆ clipNear()

void SLShadowMap::clipNear ( SLfloat  clipNear)
inline

Definition at line 64 of file SLShadowMap.h.

void clipNear(SLfloat clipNear)
Definition: SLShadowMap.h:64

◆ depthBuffer()

SLGLDepthBuffer* SLShadowMap::depthBuffer ( )
inline

Definition at line 80 of file SLShadowMap.h.

80 { return _depthBuffers.at(0); }

◆ depthBuffers()

SLGLVDepthBuffer SLShadowMap::depthBuffers ( )
inline

Definition at line 81 of file SLShadowMap.h.

81 { return _depthBuffers; }

◆ drawFrustum()

void SLShadowMap::drawFrustum ( )

SLShadowMap::drawFrustum draws the volume affected by the shadow map.

Definition at line 124 of file SLShadowMap.cpp.

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 }
unsigned int SLuint
Definition: SL.h:171
int SLint
Definition: SL.h:170
@ PT_lines
Definition: SLGLEnums.h:32
SLScene * s
Definition: SLScene.h:31
vector< SLVec3f > SLVVec3f
Definition: SLVec3.h:325
Singleton class holding all OpenGL states.
Definition: SLGLState.h:71
SLMat4f modelMatrix
Init all states.
Definition: SLGLState.h:89
static SLGLState * instance()
Public static instance getter for singleton pattern.
Definition: SLGLState.h:74
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.
SLMat4< T > inverted() const
Computes the inverse of a 4x4 non-singular matrix.
Definition: SLMat4.h:1371
void translate(T tx, T ty, T tz=0)
Definition: SLMat4.h:601
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
SLMat4f _lightView[6]
Light view matrices.
Definition: SLShadowMap.h:120
SLMat4f _lightProj[6]
Light projection matrices.
Definition: SLShadowMap.h:121
SLMat4f _lightSpace[6]
Light space matrices (= _lightProj * _lightView)
Definition: SLShadowMap.h:122
static SLVec4 GREEN
Definition: SLVec4.h:217

◆ drawNodesDirectionalCulling()

void SLShadowMap::drawNodesDirectionalCulling ( SLVNode  visibleNodes,
SLSceneView sv,
SLMat4f lightView 
)
private

SLShadowMap::drawNodesDirectionalCulling draw all nodes in the vector visibleNodes.

Parameters
visibleNodesVector of visible nodes
svPointer to the sceneview
lightViewThe light view matrix

Definition at line 397 of file SLShadowMap.cpp.

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 }
SLMat4f viewMatrix
matrix for the active cameras view transform
Definition: SLGLState.h:91
SLNode represents a node in a hierarchical scene graph.
Definition: SLNode.h:147
SceneView class represents a dynamic real time 3D view onto the scene.
Definition: SLSceneView.h:69
static SLuint drawCalls
NO. of draw calls for shadow mapping.
Definition: SLShadowMap.h:92

◆ drawNodesIntoDepthBufferRec()

void SLShadowMap::drawNodesIntoDepthBufferRec ( SLNode node,
SLSceneView sv,
SLMat4f lightView 
)
private

Recursive node drawing function for standard shadow map drawing.

Parameters
nodeThe node do draw
svPointer to the sceneview
lightViewThe light view matrix

Definition at line 422 of file SLShadowMap.cpp.

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 }
#define SL_DB_HIDDEN
Flags an object as hidden.
Definition: SLDrawBits.h:20
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
SLVNode & children()
Definition: SLNode.h:305
SLbool drawBit(SLuint bit)
Definition: SLNode.h:300
const SLMat4f & updateAndGetWM() const
Definition: SLNode.cpp:703
SLMesh * mesh()
Definition: SLNode.h:304
void castsShadows(SLbool castsShadows)
Definition: SLNode.h:282
void drawNodesIntoDepthBufferRec(SLNode *node, SLSceneView *sv, SLMat4f &lightView)

◆ drawRays()

void SLShadowMap::drawRays ( )

SLShadowMap::drawRays draws sample rays of the light for visualization purpose only. Gets turned on when the light node is selected.

Definition at line 188 of file SLShadowMap.cpp.

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 }
float SLfloat
Definition: SL.h:173
SLVec3< SLfloat > SLVec3f
Definition: SLVec3.h:318
T y
Definition: SLVec2.h:30
T x
Definition: SLVec2.h:30
static SLVec4 YELLOW
Definition: SLVec4.h:219
T lerp(T x, T a, T b)
Definition: Utils.h:255

◆ getShadowMapCascades()

SLVVec2f SLShadowMap::getShadowMapCascades ( int  numCascades,
float  camClipNear,
float  camClipFar 
)
private

Returns a vector of near and far clip distances for all shadow cascades along the cameras view direction.

Parameters
numCascadesNO. of cascades
camClipNearThe cameras near clipping distance
camClipFarThe cameras far clipping distance
Returns
A SLVVec2f vector with the near and far clip distances

Definition at line 536 of file SLShadowMap.cpp.

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 }
vector< SLVec2f > SLVVec2f
Definition: SLVec2.h:143

◆ lightClipFar()

SLfloat SLShadowMap::lightClipFar ( )
inline

Definition at line 84 of file SLShadowMap.h.

84 { return _lightClipFar; }

◆ lightClipNear()

SLfloat SLShadowMap::lightClipNear ( )
inline

Definition at line 83 of file SLShadowMap.h.

83 { return _lightClipNear; }

◆ lightCullingAdaptiveRec()

void SLShadowMap::lightCullingAdaptiveRec ( SLNode node,
SLMat4f lightProj,
SLMat4f lightView,
SLPlane lightFrustumPlanes,
SLVNode visibleNodes 
)
private

Returns the visible nodes inside the light frustum Check if the passed node is inside the light frustum and add if so to the visibleNodes vector. The goal is to exit this function as fast as possible if the node is not visible from the light hence gets not lighted.

Parameters
nodeNode to cull or add to to visibleNodes vector
lightProjThe cascades light projection matrix that gets adapted
lightViewThe cascades light view matrix
lightFrustumPlanesThe six light frustum planes
visibleNodesVector to push the lighted nodes

Definition at line 310 of file SLShadowMap.cpp.

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 }
SLVec3f centerWS()
Definition: SLAABBox.h:50
SLfloat radiusWS()
Definition: SLAABBox.h:51
static void viewToFrustumPlanes(SLPlane *planes, const SLMat4f &projectionMat, const SLMat4f &viewMat)
Definition: SLFrustum.cpp:24
void m(int i, T val)
Definition: SLMat4.h:93
SLAABBox * aabb()
Definition: SLNode.h:301
void parent(SLNode *p)
Definition: SLNode.cpp:600
void levelForSM(SLubyte lfsm)
Definition: SLNode.h:288
Level of detail (LOD) group node based on screen space coverage.
Definition: SLNodeLOD.h:28
SLfloat distToPoint(const SLVec3f &p)
Returns distance between a point P and the plane.
Definition: SLPlane.h:51
void lightCullingAdaptiveRec(SLNode *node, SLMat4f &lightProj, SLMat4f &lightView, SLPlane *lightFrustumPlanes, SLVNode &visibleNodes)

◆ lightSpace()

SLMat4f* SLShadowMap::lightSpace ( )
inline

Definition at line 79 of file SLShadowMap.h.

79 { return _lightSpace; }

◆ maxCascades()

int SLShadowMap::maxCascades ( )
inline

Definition at line 88 of file SLShadowMap.h.

88 { return _maxCascades; }

◆ numCascades() [1/2]

int SLShadowMap::numCascades ( )
inline

Definition at line 87 of file SLShadowMap.h.

87 { return _numCascades; }

◆ numCascades() [2/2]

void SLShadowMap::numCascades ( int  numCascades)
inline

Definition at line 72 of file SLShadowMap.h.

◆ projection()

SLProjType SLShadowMap::projection ( )
inline

Definition at line 76 of file SLShadowMap.h.

76 { return _projection; }

◆ rayCount() [1/2]

SLVec2i SLShadowMap::rayCount ( )
inline

Definition at line 82 of file SLShadowMap.h.

82 { return _rayCount; }

◆ rayCount() [2/2]

void SLShadowMap::rayCount ( const SLVec2i rayCount)
inline

Definition at line 63 of file SLShadowMap.h.

SLVec2i rayCount()
Definition: SLShadowMap.h:82
void set(const T X, const T Y)
Definition: SLVec2.h:40

◆ renderDirectionalLightCascaded()

void SLShadowMap::renderDirectionalLightCascaded ( SLSceneView sv,
SLNode root 
)
private

Renders the nodes into cascaded shadow maps for directional lights

Parameters
svPointer of the sceneview
rootPointer to the root node of the scene

Definition at line 561 of file SLShadowMap.cpp.

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 }
@ SP_depth
deque< SLNode * > SLVNode
SLVNode typedef for a vector of SLNodes.
Definition: SLNode.h:26
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 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.
void clearColor(const SLCol4f &c)
Definition: SLGLState.cpp:157
void viewport(SLint x, SLint y, SLsizei width, SLsizei height)
Definition: SLGLState.cpp:378
SLMat4f projectionMatrix
matrix for projection transform
Definition: SLGLState.h:90
void clearColorDepthBuffer()
Definition: SLGLState.h:123
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
SLVec3< T > axisZ() const
Definition: SLMat4.h:187
Defines a standard CG material with textures and a shader program.
Definition: SLMaterial.h:56
SLVec3f upWS() const
Definition: SLNode.h:561
SLVec3f forwardWS() const
Definition: SLNode.h:541
Defines a plane in 3D space with the equation ax + by + cy + d = 0.
Definition: SLPlane.h:25
SLfloat scrWdivH() const
Definition: SLSceneView.h:174
SLVVec2f getShadowMapCascades(int numCascades, float camClipNear, float camClipFar)
void drawNodesDirectionalCulling(SLVNode visibleNodes, SLSceneView *sv, SLMat4f &lightView)
T y
Definition: SLVec3.h:43
SLVec3 normalized() const
Definition: SLVec3.h:127
T x
Definition: SLVec3.h:43
T z
Definition: SLVec3.h:43
static SLVec4 BLACK
Definition: SLVec4.h:213

◆ renderShadows()

void SLShadowMap::renderShadows ( SLSceneView sv,
SLNode root 
)

SLShadowMap::render Toplevel entry function for shadow map rendering.

Parameters
svPointer of the sceneview
rootPointer to the root node of the scene

Definition at line 450 of file SLShadowMap.cpp.

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 }
void renderDirectionalLightCascaded(SLSceneView *sv, SLNode *root)
void updateLightSpaces()
SLShadowMap::updateLightSpaces updates a light view projection matrix.

◆ size() [1/2]

SLVec2f SLShadowMap::size ( )
inline

Definition at line 85 of file SLShadowMap.h.

85 { return _size; }

◆ size() [2/2]

void SLShadowMap::size ( const SLVec2f size)
inline

Definition at line 66 of file SLShadowMap.h.

67  {
68  _size.set(size);
69  _halfSize.set(size / 2);
70  }

◆ textureSize() [1/2]

SLVec2i SLShadowMap::textureSize ( )
inline

Definition at line 86 of file SLShadowMap.h.

86 { return _textureSize; }

◆ textureSize() [2/2]

void SLShadowMap::textureSize ( const SLVec2i textureSize)
inline

Definition at line 71 of file SLShadowMap.h.

SLVec2i textureSize()
Definition: SLShadowMap.h:86

◆ updateLightSpaces()

void SLShadowMap::updateLightSpaces ( )
private

SLShadowMap::updateLightSpaces updates a light view projection matrix.

Definition at line 240 of file SLShadowMap.cpp.

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 }
virtual SLVec4f positionWS() const =0
void spotCutOffDEG(SLfloat cutOffAngleDEG)
Definition: SLLight.cpp:92
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 perspective(T fov, T aspect, T n, T f)
Defines a perspective projection matrix with a field of view angle.
Definition: SLMat4.h:874
static SLVec3 AXISY
Definition: SLVec3.h:298
static SLVec3 AXISX
Definition: SLVec3.h:297
static SLVec3 AXISZ
Definition: SLVec3.h:299
SLVec3< T > vec3() const
Definition: SLVec4.h:111

◆ useCascaded()

SLbool SLShadowMap::useCascaded ( ) const
inline

Definition at line 78 of file SLShadowMap.h.

78 { return _useCascaded; }

◆ useCubemap() [1/2]

SLbool SLShadowMap::useCubemap ( ) const
inline

Definition at line 77 of file SLShadowMap.h.

77 { return _useCubemap; }

◆ useCubemap() [2/2]

void SLShadowMap::useCubemap ( SLbool  useCubemap)
inline

Definition at line 62 of file SLShadowMap.h.

SLbool useCubemap() const
Definition: SLShadowMap.h:77

Member Data Documentation

◆ _camera

SLCamera* SLShadowMap::_camera
private

Camera to witch the light frustums are adapted.

Definition at line 132 of file SLShadowMap.h.

◆ _cascadesFactor

SLfloat SLShadowMap::_cascadesFactor
private

Factor that determines the cascades distribution.

Definition at line 119 of file SLShadowMap.h.

◆ _depthBuffers

SLGLVDepthBuffer SLShadowMap::_depthBuffers
private

Vector of framebuffers with texture.

Definition at line 123 of file SLShadowMap.h.

◆ _frustumVAO

SLGLVertexArrayExt* SLShadowMap::_frustumVAO
private

Visualization of light-space-frustum.

Definition at line 124 of file SLShadowMap.h.

◆ _halfSize

SLVec2f SLShadowMap::_halfSize
private

_size divided by two (only for SLLightDirect non cascaded)

Definition at line 130 of file SLShadowMap.h.

◆ _light

SLLight* SLShadowMap::_light
private

The light which uses this shadow map.

Definition at line 113 of file SLShadowMap.h.

◆ _lightClipFar

SLfloat SLShadowMap::_lightClipFar
private

Light frustum far clipping plane.

Definition at line 128 of file SLShadowMap.h.

◆ _lightClipNear

SLfloat SLShadowMap::_lightClipNear
private

Light frustum near clipping plane.

Definition at line 127 of file SLShadowMap.h.

◆ _lightProj

SLMat4f SLShadowMap::_lightProj[6]
private

Light projection matrices.

Definition at line 121 of file SLShadowMap.h.

◆ _lightSpace

SLMat4f SLShadowMap::_lightSpace[6]
private

Light space matrices (= _lightProj * _lightView)

Definition at line 122 of file SLShadowMap.h.

◆ _lightView

SLMat4f SLShadowMap::_lightView[6]
private

Light view matrices.

Definition at line 120 of file SLShadowMap.h.

◆ _material

SLMaterial* SLShadowMap::_material
private

Material used to render the shadow map.

Definition at line 126 of file SLShadowMap.h.

◆ _maxCascades

SLint SLShadowMap::_maxCascades
private

Max. number of cascades for for which the shader gets generated.

Definition at line 118 of file SLShadowMap.h.

◆ _numCascades

SLint SLShadowMap::_numCascades
private

Number of cascades for directional light shadow mapping.

Definition at line 117 of file SLShadowMap.h.

◆ _projection

SLProjType SLShadowMap::_projection
private

Projection to use to create shadow map.

Definition at line 114 of file SLShadowMap.h.

◆ _rayCount

SLVec2i SLShadowMap::_rayCount
private

Amount of rays drawn by drawRays()

Definition at line 125 of file SLShadowMap.h.

◆ _size

SLVec2f SLShadowMap::_size
private

Height and width of the frustum (only for SLLightDirect non cascaded)

Definition at line 129 of file SLShadowMap.h.

◆ _textureSize

SLVec2i SLShadowMap::_textureSize
private

Size of the shadow map texture.

Definition at line 131 of file SLShadowMap.h.

◆ _useCascaded

SLbool SLShadowMap::_useCascaded
private

Flag if cascaded shadow maps should be used.

Definition at line 116 of file SLShadowMap.h.

◆ _useCubemap

SLbool SLShadowMap::_useCubemap
private

Flag if cubemap should be used for perspective projections.

Definition at line 115 of file SLShadowMap.h.

◆ drawCalls

SLuint SLShadowMap::drawCalls = 0
static

NO. of draw calls for shadow mapping.

Definition at line 92 of file SLShadowMap.h.


The documentation for this class was generated from the following files: