fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / NodeCores / Groups / Light / Shadow / Engines / OSGShaderShadowMapEngine.cpp
blob689db94d5167b7d23fe46913760e3cfe26ba3315
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2009 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
40 // Includes
41 //---------------------------------------------------------------------------
43 #include <cstdlib>
44 #include <cstdio>
46 #include "OSGConfig.h"
48 #include "OSGShaderShadowMapEngine.h"
50 #include "OSGMatrixUtility.h"
51 #include "OSGSolidBackground.h"
52 #include "OSGColorMaskChunk.h"
53 #include "OSGMaterialChunk.h"
54 #include "OSGPolygonChunk.h"
55 #include "OSGRenderAction.h"
56 #include "OSGShaderProgram.h"
58 #include "OSGBlendChunk.h"
59 #include "OSGDepthChunk.h"
60 #include "OSGTextureObjChunk.h"
61 #include "OSGImage.h"
63 #include "OSGSpotLight.h"
64 #include "OSGDirectionalLight.h"
66 #include "OSGFrameBufferObject.h"
67 #include "OSGTextureBuffer.h"
69 #include "OSGChunkMaterial.h"
70 #include "OSGShaderShadowMapEngineData.h"
73 #include "OSGGL.h"
75 #include <boost/cast.hpp>
77 #include <strstream>
79 OSG_BEGIN_NAMESPACE
81 // Documentation for this class is emitted in the
82 // OSGShaderShadowMapEngineBase.cpp file.
83 // To modify it, please change the .fcd file (OSGShaderShadowMapEngine.fcd) and
84 // regenerate the base file.
86 /***************************************************************************\
87 * Class variables *
88 \***************************************************************************/
90 const Matrix ShaderShadowMapEngine::_matCubeFaceInv[6] =
92 Matrix( 1, 0, 0, 0, // + Z
93 0, -1, 0, 0,
94 0, 0, -1, 0,
95 0, 0, 0, 1),
97 Matrix(-1, 0, 0, 0, // - Z
98 0, -1, 0, 0,
99 0, 0, 1, 0,
100 0, 0, 0, 1),
102 Matrix( 1, 0, 0, 0, // + Y
103 0, 0, 1, 0,
104 0, -1, 0, 0,
105 0, 0, 0, 1),
107 Matrix( 1, 0, 0, 0, // - Y
108 0, 0, -1, 0,
109 0, 1, 0, 0,
110 0, 0, 0, 1),
112 Matrix( 0, 0, -1, 0, // + X
113 0, -1, 0, 0,
114 -1, 0, 0, 0,
115 0, 0, 0, 1),
117 Matrix( 0, 0, 1, 0, // - X
118 0, -1, 0, 0,
119 1, 0, 0, 0,
120 0, 0, 0, 1),
123 const GLenum ShaderShadowMapEngine::_cubeFaceTargets[6] =
125 GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
126 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
127 GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
128 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
129 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
130 GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
133 const std::string ShaderShadowMapEngine::_pointFPCode(
134 "#version 120\n"
135 "\n"
136 "#extension GL_EXT_gpu_shader4 : require\n"
137 "#extension GL_EXT_gpu_shader4 : enable\n"
138 "\n"
139 "uniform samplerCubeShadow SSME_texShadow;\n"
140 "\n"
141 "uniform mat4 SSME_matEyeToLight;\n"
142 "uniform mat4 SSME_matLightProj;\n"
143 "\n"
144 "vec4 OSG_SSME_FP_calcShadow(in vec4 ecFragPos)\n"
145 "{\n"
146 " vec4 shadow = vec4(0., 0., 0., 0.);\n"
147 " vec4 lcPos = SSME_matEyeToLight * ecFragPos;\n"
148 " vec4 lcAbsPos = abs(lcPos);\n"
149 " vec4 plcPos;\n"
150 "\n"
151 " if(lcAbsPos.x > lcAbsPos.y && lcAbsPos.x > lcAbsPos.z)\n"
152 " {\n"
153 " if(lcPos.x >= 0.)\n"
154 " plcPos = vec4(-1, -1, -1, 1) * lcPos.zyxw;\n"
155 " else\n"
156 " plcPos = vec4( 1, -1, 1, 1) * lcPos.zyxw;\n"
157 " }\n"
158 " else if(lcAbsPos.y > lcAbsPos.x && lcAbsPos.y > lcAbsPos.z)\n"
159 " {\n"
160 " if(lcPos.y >= 0.)\n"
161 " plcPos = vec4( 1, 1, -1, 1) * lcPos.xzyw;\n"
162 " else\n"
163 " plcPos = vec4( 1, -1, 1, 1) * lcPos.xzyw;\n"
164 " }\n"
165 " else\n"
166 " {\n"
167 " if(lcPos.z >= 0.)\n"
168 " plcPos = vec4( 1, -1, -1, 1) * lcPos;\n"
169 " else\n"
170 " plcPos = vec4(-1, -1, 1, 1) * lcPos;\n"
171 " }\n"
172 "\n"
173 " plcPos = SSME_matLightProj * plcPos;\n"
174 " plcPos = plcPos / plcPos.w;\n"
175 " plcPos = 0.5 + 0.5 * plcPos;\n"
176 "\n"
177 " shadow = shadowCube(SSME_texShadow, vec4(lcPos.xyz, plcPos.z));\n"
178 "\n"
179 " return shadow;\n"
180 "}\n");
182 const std::string ShaderShadowMapEngine::_dirFPCode(
183 "#version 120\n"
184 "\n"
185 "uniform sampler2DShadow SSME_texShadow;\n"
186 "\n"
187 "uniform mat4 SSME_matEyeToLight;\n"
188 "uniform mat4 SSME_matLightProj;\n"
189 "\n"
190 "vec4 OSG_SSME_FP_calcShadow(in vec4 ecFragPos)\n"
191 "{\n"
192 " vec4 lcPos = SSME_matEyeToLight * ecFragPos;\n"
193 " vec4 plcPos = SSME_matLightProj * lcPos;\n"
194 "\n"
195 " plcPos = plcPos / plcPos.w;\n"
196 " plcPos = 0.5 + 0.5 * plcPos;\n"
197 "\n"
198 " return shadow2D(SSME_texShadow, plcPos.xyz);\n"
199 "}\n");
201 const std::string ShaderShadowMapEngine::_spotFPCode(
202 "#version 120\n"
203 "\n"
204 "uniform sampler2DShadow SSME_texShadow;\n"
205 "\n"
206 "uniform mat4 SSME_matEyeToLight;\n"
207 "uniform mat4 SSME_matLightProj;\n"
208 "\n"
209 "vec4 OSG_SSME_FP_calcShadow(in vec4 ecFragPos)\n"
210 "{\n"
211 " vec4 lcPos = SSME_matEyeToLight * ecFragPos;\n"
212 " vec4 plcPos = SSME_matLightProj * lcPos;\n"
213 "\n"
214 " plcPos = plcPos / plcPos.w;\n"
215 " plcPos = 0.5 + 0.5 * plcPos;\n"
216 "\n"
217 " return shadow2D(SSME_texShadow, plcPos.xyz);\n"
218 "}\n");
220 /***************************************************************************\
221 * Class methods *
222 \***************************************************************************/
224 void ShaderShadowMapEngine::initMethod(InitPhase ePhase)
226 Inherited::initMethod(ePhase);
230 /***************************************************************************\
231 * Instance methods *
232 \***************************************************************************/
234 /*-------------------------------------------------------------------------*\
235 - private -
236 \*-------------------------------------------------------------------------*/
238 /*----------------------- constructors & destructors ----------------------*/
240 ShaderShadowMapEngine::ShaderShadowMapEngine(void) :
241 Inherited()
245 ShaderShadowMapEngine::ShaderShadowMapEngine(const ShaderShadowMapEngine &source) :
246 Inherited(source)
250 ShaderShadowMapEngine::~ShaderShadowMapEngine(void)
254 /*----------------------------- class specific ----------------------------*/
256 Action::ResultE ShaderShadowMapEngine::runOnEnter(
257 Light *light, LightTypeE eType, RenderAction *ract)
259 typedef ShaderShadowMapEngineDataUnrecPtr SSMEngineDataUnrecPtr;
261 BitVector bvMask = ract->getPassMask ( );
262 SSMEngineData *data = ract->getData<SSMEngineData *>(_iDataSlotId);
264 if(data == NULL)
266 SSMEngineDataUnrecPtr newData = SSMEngineData::createLocal();
267 this->setData(newData, _iDataSlotId, ract);
269 data = newData;
272 if(0x0000 != bvMask)
274 // already generating a shadow map for another light source
275 if(0x0000 != (bvMask & bvLightPassMask))
277 this->recurseFrom(ract, light);
279 handleEnter(light, eType, ract, data);
282 else
284 // first light source to generate a shadow map
285 ract->addPassMask(bvLightPassMask);
286 handleEnter(light, eType, ract, data);
287 ract->subPassMask(bvLightPassMask);
290 // continue rendering normally
291 return Action::Continue;
294 Action::ResultE ShaderShadowMapEngine::runOnLeave(
295 Light *light, LightTypeE eType, RenderAction *ract)
297 return Action::Continue;
300 void ShaderShadowMapEngine::changed(ConstFieldMaskArg whichField,
301 UInt32 origin,
302 BitVector details)
304 Inherited::changed(whichField, origin, details);
307 void ShaderShadowMapEngine::dump( UInt32 ,
308 const BitVector ) const
310 SLOG << "Dump ShaderShadowMapEngine NI" << std::endl;
313 void ShaderShadowMapEngine::handleEnter(
314 Light *light, LightTypeE eType, RenderAction *ract, SSMEngineData *data)
316 updateShadowTexChunk (data);
317 updateLightPassMaterial(data);
318 updateBackground (data);
320 UInt32 parentTravMask = ract->getTravMask();
321 ract->setTravMask(_sfShadowTravMask.getValue());
323 // call specific handler for light type
324 switch(eType)
326 case Point:
328 PointLight *pointL =
329 boost::polymorphic_downcast<PointLight *>(light);
331 handlePointLightEnter(pointL, ract, data);
333 break;
335 case Directional:
337 DirectionalLight *dirL =
338 boost::polymorphic_downcast<DirectionalLight *>(light);
340 handleDirectionalLightEnter(dirL, ract, data);
342 break;
344 case Spot:
346 SpotLight *spotL =
347 boost::polymorphic_downcast<SpotLight *>(light);
349 handleSpotLightEnter(spotL, ract, data);
351 break;
353 default:
355 FWARNING(("ShaderShadowMapEngine::handleEnter: Unknown "
356 "light type [%u]\n", eType));
358 break;
361 ract->setTravMask(parentTravMask);
364 void ShaderShadowMapEngine::handlePointLightEnter(
365 PointLight *pointL, RenderAction *ract, SSMEngineData *data)
367 RenderPartition *parentPart = ract->getActivePartition();
369 Matrix matEyeToWorld(parentPart->getCameraToWorld());
370 Matrix matLightProj;
372 Real32 lightNear;
373 Real32 lightFar;
375 calcPointLightRange(pointL, 0.001f,
376 parentPart->getNear(), parentPart->getFar(),
377 lightNear, lightFar );
379 MatrixPerspective(matLightProj, Pi / 4.f, 1.f,
380 lightNear, lightFar );
382 Matrix matWorldToLight;
383 Matrix matEyeToLight;
385 calcPointLightMatrices(matWorldToLight, matEyeToLight,
386 pointL, matEyeToWorld );
388 updatePointLightShadowTexImage (data);
389 updatePointLightShadowTexBuffers(data);
390 updatePointLightRenderTargets (data);
392 Int32 shadowTexUnit = (this->getForceTextureUnit() > 0) ?
393 this->getForceTextureUnit() : 7;
395 ShaderProgram *shadowFP = this->getShadowFragmentProgram();
397 if(shadowFP == NULL)
399 ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal();
400 newShadowFP->setShaderType(GL_FRAGMENT_SHADER);
401 newShadowFP->setProgram (_pointFPCode );
403 newShadowFP->addUniformVariable("SSME_matEyeToLight", matEyeToLight);
404 newShadowFP->addUniformVariable("SSME_matLightProj", matLightProj );
405 newShadowFP->addUniformVariable("SSME_texShadow", shadowTexUnit);
407 this->setShadowFragmentProgram(newShadowFP);
408 shadowFP = newShadowFP;
410 else
412 shadowFP->updateUniformVariable("SSME_matEyeToLight", matEyeToLight);
413 shadowFP->updateUniformVariable("SSME_matLightProj", matLightProj );
416 commitChanges();
418 // schedule rendering of cube faces
419 for(UInt16 i = 0; i < 6; ++i)
421 Matrix matWorldToLightFace(matWorldToLight);
422 matWorldToLightFace.multLeft(_matCubeFaceInv[i]);
424 this->pushPartition(ract);
426 RenderPartition *part = ract->getActivePartition( );
427 Window *win = ract->getWindow ( );
428 FrameBufferObject *target = data->getRenderTargets (i);
429 Background *back = data->getBackground ( );
431 part->setRenderTarget(target);
432 part->setWindow (win );
434 part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
435 target->getWidth (),
436 target->getHeight() );
438 part->setupProjection(matLightProj, Matrix::identity());
439 part->setupViewing (matWorldToLightFace );
441 part->setNear (parentPart->getNear());
442 part->setFar (parentPart->getFar ());
444 part->calcFrustum ( );
446 part->setBackground (back );
448 // force material for shadow map generation
449 part->overrideMaterial(data->getLightPassMaterials(0),
450 ract->getActNode ( ) );
452 this->recurseFrom(ract, pointL);
453 ract->useNodeList(false );
455 // undo override
456 part->overrideMaterial(NULL,
457 ract->getActNode ( ) );
459 this->popPartition(ract);
463 void ShaderShadowMapEngine::handleDirectionalLightEnter(
464 DirectionalLight *dirL, RenderAction *ract, SSMEngineData *data)
466 RenderPartition *parentPart = ract ->getActivePartition();
467 FrustumVolume camFrust = parentPart->getFrustum ();
469 Matrix matEyeToWorld (parentPart->getCameraToWorld());
470 Matrix matWorldToLight;
471 Matrix matEyeToLight;
473 calcDirectionalLightMatrices(matWorldToLight, matEyeToLight,
474 dirL, matEyeToWorld );
476 // place light camera outside the scene bounding box:
477 // - project camera frustum and scene bounding box into a
478 // coordinate system where the directional light shines
479 // along the -z axis.
480 // - compute 2 AABBs that contain the projected frustum and
481 // scene BB
482 // - width and height of the ortho projection are determined from
483 // the frustum AABB, while near and far are determined by the
484 // scene AABB (offscreen objects cast shadows into the view volume)
485 Pnt3f camVerts [10];
486 Pnt3f sceneVerts[10];
487 const Matrix &matSceneToWorld = ract->topMatrix ();
488 BoxVolume sceneBB = ract->getActNode()->getVolume();
490 camFrust.getCorners(camVerts [0], camVerts [1],
491 camVerts [2], camVerts [3],
492 camVerts [4], camVerts [5],
493 camVerts [6], camVerts [7] );
494 sceneBB .getCorners(sceneVerts[0], sceneVerts[1],
495 sceneVerts[2], sceneVerts[3],
496 sceneVerts[4], sceneVerts[5],
497 sceneVerts[6], sceneVerts[7] );
499 camVerts [8].setValues(TypeTraits<Real32>::getMax(),
500 TypeTraits<Real32>::getMax(),
501 TypeTraits<Real32>::getMax() );
502 camVerts [9].setValues(TypeTraits<Real32>::getMin(),
503 TypeTraits<Real32>::getMin(),
504 TypeTraits<Real32>::getMin() );
505 sceneVerts[8].setValues(TypeTraits<Real32>::getMax(),
506 TypeTraits<Real32>::getMax(),
507 TypeTraits<Real32>::getMax() );
508 sceneVerts[9].setValues(TypeTraits<Real32>::getMin(),
509 TypeTraits<Real32>::getMin(),
510 TypeTraits<Real32>::getMin() );
512 for(UInt32 i = 0; i < 8; ++i)
514 matWorldToLight.mult(camVerts [i], camVerts [i]);
516 matSceneToWorld.mult(sceneVerts[i], sceneVerts[i]);
517 matWorldToLight.mult(sceneVerts[i], sceneVerts[i]);
519 camVerts [8][0] = osgMin(camVerts [8][0], camVerts [i][0]);
520 camVerts [9][0] = osgMax(camVerts [9][0], camVerts [i][0]);
521 camVerts [8][1] = osgMin(camVerts [8][1], camVerts [i][1]);
522 camVerts [9][1] = osgMax(camVerts [9][1], camVerts [i][1]);
524 sceneVerts[8][0] = osgMin(sceneVerts[8][0], sceneVerts[i][0]);
525 sceneVerts[9][0] = osgMax(sceneVerts[9][0], sceneVerts[i][0]);
526 sceneVerts[8][1] = osgMin(sceneVerts[8][1], sceneVerts[i][1]);
527 sceneVerts[9][1] = osgMax(sceneVerts[9][1], sceneVerts[i][1]);
528 sceneVerts[8][2] = osgMin(sceneVerts[8][2], sceneVerts[i][2]);
529 sceneVerts[9][2] = osgMax(sceneVerts[9][2], sceneVerts[i][2]);
532 // these points are the corners of the ortho shadow view volume
533 Pnt3f lightMin(osgMax(camVerts[8][0], sceneVerts[8][0]),
534 osgMax(camVerts[8][1], sceneVerts[8][1]),
535 -sceneVerts[9][2]);
537 Pnt3f lightMax(osgMin(camVerts[9][0], sceneVerts[9][0]),
538 osgMin(camVerts[9][1], sceneVerts[9][1]),
539 -sceneVerts[8][2]);
541 // enlarge by 2% in x, y, z direction
542 lightMin[0] -= (lightMax[0] - lightMin[0]) * 0.01f;
543 lightMin[1] -= (lightMax[1] - lightMin[1]) * 0.01f;
544 lightMin[2] -= (lightMax[2] - lightMin[2]) * 0.01f;
546 lightMax[0] += (lightMax[0] - lightMin[0]) * 0.01f;
547 lightMax[1] += (lightMax[1] - lightMin[1]) * 0.01f;
548 lightMax[2] += (lightMax[2] - lightMin[2]) * 0.01f;
550 Matrix matLightProj;
551 Matrix matLightProjTrans;
553 MatrixOrthogonal(matLightProj,
554 lightMin[0], lightMax[0],
555 lightMin[1], lightMax[1],
556 lightMin[2], lightMax[2] );
558 updateShadowTexImage (data);
559 updateShadowTexBuffers(data);
560 updateRenderTargets (data);
562 Int32 shadowTexUnit = (this->getForceTextureUnit() > 0) ?
563 this->getForceTextureUnit() : 7;
565 ShaderProgram *shadowFP = this->getShadowFragmentProgram();
567 if(shadowFP == NULL)
569 ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal();
570 newShadowFP->setShaderType(GL_FRAGMENT_SHADER);
571 newShadowFP->setProgram (_dirFPCode );
573 newShadowFP->addUniformVariable("SSME_matEyeToLight", matEyeToLight);
574 newShadowFP->addUniformVariable("SSME_matLightProj", matLightProj );
575 newShadowFP->addUniformVariable("SSME_texShadow", shadowTexUnit);
577 this->setShadowFragmentProgram(newShadowFP);
578 shadowFP = newShadowFP;
580 else
582 shadowFP->updateUniformVariable("SSME_matEyeToLight", matEyeToLight);
583 shadowFP->updateUniformVariable("SSME_matLightProj", matLightProj );
586 commitChanges();
588 this->pushPartition(ract);
590 RenderPartition *part = ract->getActivePartition( );
591 Window *win = ract->getWindow ( );
592 FrameBufferObject *target = data->getRenderTargets (0);
593 Background *back = data->getBackground ( );
595 part->setRenderTarget(target);
596 part->setWindow (win );
598 part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
599 target->getWidth (),
600 target->getHeight() );
602 part->setupProjection(matLightProj, matLightProjTrans);
603 part->setupViewing (matWorldToLight );
605 part->setNear (parentPart->getNear());
606 part->setFar (parentPart->getFar ());
608 part->calcFrustum ( );
610 part->setBackground (back );
612 // force material for shadow map generation
613 part->overrideMaterial(data->getLightPassMaterials(0),
614 ract->getActNode ( ) );
616 this->recurseFrom(ract, dirL);
617 ract->useNodeList(false );
619 // undo override
620 part->overrideMaterial(NULL,
621 ract->getActNode ( ) );
623 this->popPartition(ract);
626 void ShaderShadowMapEngine::handleSpotLightEnter(
627 SpotLight *spotL, RenderAction *ract, SSMEngineData *data)
629 RenderPartition *parentPart = ract->getActivePartition();
630 // Real cosSpotCutOff = osgCos(spotL->getSpotCutOff());
632 Matrix matEyeToWorld (parentPart->getCameraToWorld());
633 Matrix matWorldToLight;
634 Matrix matEyeToLight;
636 calcSpotLightMatrices(matWorldToLight, matEyeToLight,
637 spotL, matEyeToWorld );
639 Real32 lightNear;
640 Real32 lightFar;
642 calcPointLightRange(spotL, 0.001f,
643 parentPart->getNear(), parentPart->getFar(),
644 lightNear, lightFar );
646 if(getShadowNear() != 0.f)
648 lightNear = getShadowNear();
651 if(getShadowFar() != 0.f)
653 lightFar = getShadowFar();
656 Matrix matLightProj;
657 Matrix matLightProjTrans;
659 MatrixPerspective(matLightProj,
660 spotL->getSpotCutOff(), 1.f,
661 lightNear, lightFar );
663 updateShadowTexImage (data);
664 updateShadowTexBuffers(data);
665 updateRenderTargets (data);
667 Int32 shadowTexUnit = (this->getForceTextureUnit() > 0) ?
668 this->getForceTextureUnit() : 7;
669 ShaderProgram *shadowFP = this->getShadowFragmentProgram();
671 if(shadowFP == NULL)
673 ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal();
674 newShadowFP->setShaderType(GL_FRAGMENT_SHADER);
675 newShadowFP->setProgram (_spotFPCode );
677 newShadowFP->addUniformVariable("SSME_matEyeToLight", matEyeToLight);
678 newShadowFP->addUniformVariable("SSME_matLightProj", matLightProj );
679 newShadowFP->addUniformVariable("SSME_texShadow", shadowTexUnit);
681 this->setShadowFragmentProgram(newShadowFP);
682 shadowFP = newShadowFP;
684 else
686 shadowFP->updateUniformVariable("SSME_matEyeToLight", matEyeToLight);
687 shadowFP->updateUniformVariable("SSME_matLightProj", matLightProj );
690 commitChanges();
692 this->pushPartition(ract);
694 RenderPartition *part = ract->getActivePartition( );
695 Window *win = ract->getWindow ( );
696 FrameBufferObject *target = data->getRenderTargets (0);
697 Background *back = data->getBackground ( );
699 part->setRenderTarget(target);
700 part->setWindow (win );
702 part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
703 target->getWidth (),
704 target->getHeight() );
706 part->setupProjection(matLightProj, matLightProjTrans);
707 part->setupViewing (matWorldToLight );
709 part->setNear (parentPart->getNear());
710 part->setFar (parentPart->getFar ());
712 part->calcFrustum ( );
714 part->setBackground (back );
716 // force material for shadow map generation
717 part->overrideMaterial(data->getLightPassMaterials(0),
718 ract->getActNode ( ) );
720 this->recurseFrom(ract, spotL);
721 ract->useNodeList(false );
723 // undo override
724 part->overrideMaterial(NULL,
725 ract->getActNode ( ) );
727 this->popPartition(ract);
730 /*! Calculates \a matWorldToLight and \a matEyeToLight for a directional light
731 \a dirL and inverse viewing matrix \a matEyeToWorld.
733 void ShaderShadowMapEngine::calcDirectionalLightMatrices(
734 Matrix &matWorldToLight,
735 Matrix &matEyeToLight,
736 const DirectionalLight *dirL,
737 const Matrix &matEyeToWorld)
739 if(dirL->getBeacon() != NULL)
740 dirL->getBeacon()->getToWorld(matWorldToLight);
742 Quaternion rotLightDir (Vec3f(0.f, 0.f, 1.f), dirL->getDirection());
743 Matrix matLightDir;
744 matLightDir.setRotate(rotLightDir);
746 matWorldToLight.mult (matLightDir);
747 matWorldToLight.invert( );
749 matEyeToLight = matWorldToLight;
750 matEyeToLight.mult(matEyeToWorld);
753 void ShaderShadowMapEngine::calcPointLightMatrices(
754 Matrix &matWorldToLight,
755 Matrix &matEyeToLight,
756 const PointLight *pointL,
757 const Matrix &matEyeToWorld)
759 if(pointL->getBeacon() != NULL)
760 pointL->getBeacon()->getToWorld(matWorldToLight);
762 Matrix matLightPos;
763 matLightPos .setTranslate(pointL->getPosition());
764 matWorldToLight.mult (matLightPos );
765 matWorldToLight.invert ( );
767 matEyeToLight = matWorldToLight;
768 matEyeToLight.mult(matEyeToWorld);
771 /*! Calculates \a matWorldToLight and \a matEyeToLight for a spot light
772 \a spotL and inverse viewing matrix \a matEyeToWorld.
774 void ShaderShadowMapEngine::calcSpotLightMatrices(
775 Matrix &matWorldToLight,
776 Matrix &matEyeToLight,
777 const SpotLight *spotL,
778 const Matrix &matEyeToWorld)
780 if(spotL->getBeacon() != NULL)
781 spotL->getBeacon()->getToWorld(matWorldToLight);
783 Matrix matLightPos;
784 matLightPos.setTranslate(spotL->getPosition());
786 Matrix matLightDir;
787 Quaternion rotLightDir(Vec3f(0.f, 0.f, 1.f), -spotL->getDirection());
788 matLightDir.setRotate(rotLightDir);
790 matWorldToLight.mult (matLightPos);
791 matWorldToLight.mult (matLightDir);
792 matWorldToLight.invert( );
794 matEyeToLight = matWorldToLight;
795 matEyeToLight.mult(matEyeToWorld);
798 void ShaderShadowMapEngine::calcPointLightRange(
799 const PointLight *pointL, Real32 lightThreshold,
800 Real32 defaultNear, Real32 defaultFar,
801 Real32 &outNear, Real32 &outFar )
803 outNear = defaultNear;
804 outFar = defaultFar;
806 Real32 kQ = pointL->getQuadraticAttenuation();
807 Real32 kL = pointL->getLinearAttenuation ();
808 Real32 kC = pointL->getConstantAttenuation ();
810 if(osgAbs(kQ) > TypeTraits<Real32>::getDefaultEps())
812 Real32 det = kL * kL - 4.f * kQ * (kC - 1.f / lightThreshold);
814 if(det >= 0)
816 det = osgSqrt(det);
817 Real32 r1 = - kL + det / (2.f * kQ);
818 Real32 r2 = - kL - det / (2.f * kQ);
820 if(r1 > 0.f && r2 > 0.f)
822 outFar = osgMin(r1, r2);
824 else if(r1 > 0.f)
826 outFar = r1;
828 else if(r2 > 0.f)
830 outFar = r2;
834 else if(osgAbs(kL) > TypeTraits<Real32>::getDefaultEps())
836 Real32 r = (1.f / lightThreshold - kC) / kL;
838 if(r > 0.f)
840 outFar = r;
845 void ShaderShadowMapEngine::updateShadowTexChunk(SSMEngineData *data)
847 TextureObjChunk *bufTex = data->getShadowTexChunk();
849 if(bufTex == NULL)
851 TextureObjChunkUnrecPtr newBufTex = TextureObjChunk::createLocal();
852 newBufTex->setMinFilter (GL_LINEAR );
853 newBufTex->setMagFilter (GL_LINEAR );
854 newBufTex->setWrapS (GL_CLAMP_TO_EDGE );
855 newBufTex->setWrapT (GL_CLAMP_TO_EDGE );
856 newBufTex->setWrapR (GL_CLAMP_TO_EDGE );
857 newBufTex->setScale (false );
858 newBufTex->setInternalFormat(GL_DEPTH_COMPONENT24 );
859 newBufTex->setExternalFormat(GL_DEPTH_COMPONENT );
860 newBufTex->setCompareMode (GL_COMPARE_R_TO_TEXTURE);
861 newBufTex->setCompareFunc (GL_LESS );
862 newBufTex->setDepthMode (GL_LUMINANCE );
864 data->setShadowTexChunk(newBufTex);
865 this->setShadowTexChunk(newBufTex);
869 void ShaderShadowMapEngine::updateLightPassMaterial(SSMEngineData *data)
871 if(data->getMFLightPassMaterials()->empty() == true)
873 MaterialChunkUnrecPtr newMatChunk = MaterialChunk::createLocal();
874 newMatChunk->setLit (false );
875 newMatChunk->setColorMaterial(GL_NONE);
877 ColorMaskChunkUnrecPtr newCMaskChunk = ColorMaskChunk::create();
878 newCMaskChunk->setMaskR(false);
879 newCMaskChunk->setMaskG(false);
880 newCMaskChunk->setMaskB(false);
881 newCMaskChunk->setMaskA(false);
883 PolygonChunkUnrecPtr newPolyChunk = PolygonChunk::createLocal();
884 newPolyChunk->setOffsetFill (true );
885 newPolyChunk->setOffsetFactor(this->getOffsetFactor());
886 newPolyChunk->setOffsetBias (this->getOffsetBias ());
888 ChunkMaterialUnrecPtr newLightPassMat = ChunkMaterial::createLocal();
889 newLightPassMat->addChunk(newMatChunk );
890 newLightPassMat->addChunk(newCMaskChunk);
891 newLightPassMat->addChunk(newPolyChunk );
893 data->editMFLightPassMaterials()->push_back(newLightPassMat);
897 void ShaderShadowMapEngine::updateBackground(SSMEngineData *data)
899 Background *back = data->getBackground();
901 if(back == NULL)
903 SolidBackgroundUnrecPtr newBack = SolidBackground::createLocal();
904 newBack->setClearColor(false);
906 data->setBackground(newBack);
910 void ShaderShadowMapEngine::updatePointLightShadowTexImage(SSMEngineData *data)
912 Image *bufImg = data->getShadowTexImage();
913 TextureObjChunk *bufTex = data->getShadowTexChunk();
915 FASSERT((bufTex != NULL), false)
917 if(bufImg == NULL)
919 ImageUnrecPtr newBufImg = Image::createLocal();
920 newBufImg->set(Image::OSG_L_PF,
921 this->getWidth (),
922 this->getHeight(),
927 NULL,
928 Image::OSG_UINT8_IMAGEDATA,
929 false,
932 bufTex->setImage (newBufImg);
933 data ->setShadowTexImage(newBufImg);
935 bufImg = newBufImg;
938 if((bufImg->getWidth () != this->getWidth ()) ||
939 (bufImg->getHeight() != this->getHeight()) )
941 bufImg->setWidth (this->getWidth ());
942 bufImg->setHeight(this->getHeight());
946 void ShaderShadowMapEngine::updateShadowTexImage(SSMEngineData *data)
948 Image *bufImg = data->getShadowTexImage();
949 TextureObjChunk *bufTex = data->getShadowTexChunk();
951 FASSERT((bufTex != NULL), false)
953 if(bufImg == NULL)
955 ImageUnrecPtr newBufImg = Image::createLocal();
956 newBufImg->set(Image::OSG_L_PF,
957 this->getWidth (),
958 this->getHeight(),
963 NULL,
964 Image::OSG_UINT8_IMAGEDATA,
965 false,
968 bufTex->setImage (newBufImg);
969 data ->setShadowTexImage(newBufImg);
971 bufImg = newBufImg;
974 if((bufImg->getWidth () != this->getWidth ()) ||
975 (bufImg->getHeight() != this->getHeight()) )
977 bufImg->setWidth (this->getWidth ());
978 bufImg->setHeight(this->getHeight());
982 void ShaderShadowMapEngine::updatePointLightShadowTexBuffers(
983 SSMEngineData *data)
985 TextureObjChunk *bufTex = data->getShadowTexChunk();
987 if(data->getMFShadowTexBuffers()->empty() == true)
989 for(UInt16 i = 0; i < 6; ++i)
991 TextureBufferUnrecPtr newBuf = TextureBuffer::createLocal();
992 newBuf->setTexture (bufTex );
993 newBuf->setTexTarget(_cubeFaceTargets[i]);
995 data->editMFShadowTexBuffers()->push_back(newBuf);
1000 void ShaderShadowMapEngine::updateShadowTexBuffers(SSMEngineData *data)
1002 TextureObjChunk *bufTex = data->getShadowTexChunk();
1004 if(data->getMFShadowTexBuffers()->empty() == true)
1006 TextureBufferUnrecPtr newBuf = TextureBuffer::createLocal();
1007 newBuf->setTexture (bufTex );
1008 newBuf->setTexTarget(GL_TEXTURE_2D);
1010 data->editMFShadowTexBuffers()->push_back(newBuf);
1014 void ShaderShadowMapEngine::updatePointLightRenderTargets(SSMEngineData *data)
1016 if(data->getMFRenderTargets()->empty() == true)
1018 for(UInt16 i = 0; i < 6; ++i)
1020 FrameBufferObjectUnrecPtr newTarget =
1021 FrameBufferObject::createLocal();
1022 newTarget->setWidth (this->getWidth ( ));
1023 newTarget->setHeight (this->getHeight ( ));
1024 newTarget->setDepthAttachment(data->getShadowTexBuffers(i));
1026 data->editMFRenderTargets()->push_back(newTarget);
1029 else
1031 for(UInt16 i = 0; i < 6; ++i)
1033 FrameBufferObject *target = data->getRenderTargets(i);
1035 if((target->getWidth () != this->getWidth ()) ||
1036 (target->getHeight() != this->getHeight()) )
1038 target->setWidth (this->getWidth ());
1039 target->setHeight(this->getHeight());
1045 void ShaderShadowMapEngine::updateRenderTargets(SSMEngineData *data)
1047 if(data->getMFRenderTargets()->empty() == true)
1049 FrameBufferObjectUnrecPtr newTarget =
1050 FrameBufferObject::createLocal();
1051 newTarget->setWidth (this->getWidth ( ));
1052 newTarget->setHeight (this->getHeight ( ));
1053 newTarget->setDepthAttachment(data->getShadowTexBuffers(0));
1055 data->editMFRenderTargets()->push_back(newTarget);
1057 else
1059 FrameBufferObject *target = data->getRenderTargets(0);
1061 if((target->getWidth () != this->getWidth ()) ||
1062 (target->getHeight() != this->getHeight()) )
1064 target->setWidth (this->getWidth ());
1065 target->setHeight(this->getHeight());
1070 OSG_END_NAMESPACE