1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2009 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
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. *
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. *
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. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
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"
63 #include "OSGSpotLight.h"
64 #include "OSGDirectionalLight.h"
66 #include "OSGFrameBufferObject.h"
67 #include "OSGTextureBuffer.h"
69 #include "OSGChunkMaterial.h"
70 #include "OSGShaderShadowMapEngineData.h"
75 #include <boost/cast.hpp>
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 /***************************************************************************\
88 \***************************************************************************/
90 const Matrix
ShaderShadowMapEngine::_matCubeFaceInv
[6] =
92 Matrix( 1, 0, 0, 0, // + Z
97 Matrix(-1, 0, 0, 0, // - Z
102 Matrix( 1, 0, 0, 0, // + Y
107 Matrix( 1, 0, 0, 0, // - Y
112 Matrix( 0, 0, -1, 0, // + X
117 Matrix( 0, 0, 1, 0, // - X
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(
136 "#extension GL_EXT_gpu_shader4 : require\n"
137 "#extension GL_EXT_gpu_shader4 : enable\n"
139 "uniform samplerCubeShadow SSME_texShadow;\n"
141 "uniform mat4 SSME_matEyeToLight;\n"
142 "uniform mat4 SSME_matLightProj;\n"
144 "vec4 OSG_SSME_FP_calcShadow(in vec4 ecFragPos)\n"
146 " vec4 shadow = vec4(0., 0., 0., 0.);\n"
147 " vec4 lcPos = SSME_matEyeToLight * ecFragPos;\n"
148 " vec4 lcAbsPos = abs(lcPos);\n"
151 " if(lcAbsPos.x > lcAbsPos.y && lcAbsPos.x > lcAbsPos.z)\n"
153 " if(lcPos.x >= 0.)\n"
154 " plcPos = vec4(-1, -1, -1, 1) * lcPos.zyxw;\n"
156 " plcPos = vec4( 1, -1, 1, 1) * lcPos.zyxw;\n"
158 " else if(lcAbsPos.y > lcAbsPos.x && lcAbsPos.y > lcAbsPos.z)\n"
160 " if(lcPos.y >= 0.)\n"
161 " plcPos = vec4( 1, 1, -1, 1) * lcPos.xzyw;\n"
163 " plcPos = vec4( 1, -1, 1, 1) * lcPos.xzyw;\n"
167 " if(lcPos.z >= 0.)\n"
168 " plcPos = vec4( 1, -1, -1, 1) * lcPos;\n"
170 " plcPos = vec4(-1, -1, 1, 1) * lcPos;\n"
173 " plcPos = SSME_matLightProj * plcPos;\n"
174 " plcPos = plcPos / plcPos.w;\n"
175 " plcPos = 0.5 + 0.5 * plcPos;\n"
177 " shadow = shadowCube(SSME_texShadow, vec4(lcPos.xyz, plcPos.z));\n"
182 const std::string
ShaderShadowMapEngine::_dirFPCode(
185 "uniform sampler2DShadow SSME_texShadow;\n"
187 "uniform mat4 SSME_matEyeToLight;\n"
188 "uniform mat4 SSME_matLightProj;\n"
190 "vec4 OSG_SSME_FP_calcShadow(in vec4 ecFragPos)\n"
192 " vec4 lcPos = SSME_matEyeToLight * ecFragPos;\n"
193 " vec4 plcPos = SSME_matLightProj * lcPos;\n"
195 " plcPos = plcPos / plcPos.w;\n"
196 " plcPos = 0.5 + 0.5 * plcPos;\n"
198 " return shadow2D(SSME_texShadow, plcPos.xyz);\n"
201 const std::string
ShaderShadowMapEngine::_spotFPCode(
204 "uniform sampler2DShadow SSME_texShadow;\n"
206 "uniform mat4 SSME_matEyeToLight;\n"
207 "uniform mat4 SSME_matLightProj;\n"
209 "vec4 OSG_SSME_FP_calcShadow(in vec4 ecFragPos)\n"
211 " vec4 lcPos = SSME_matEyeToLight * ecFragPos;\n"
212 " vec4 plcPos = SSME_matLightProj * lcPos;\n"
214 " plcPos = plcPos / plcPos.w;\n"
215 " plcPos = 0.5 + 0.5 * plcPos;\n"
217 " return shadow2D(SSME_texShadow, plcPos.xyz);\n"
220 /***************************************************************************\
222 \***************************************************************************/
224 void ShaderShadowMapEngine::initMethod(InitPhase ePhase
)
226 Inherited::initMethod(ePhase
);
230 /***************************************************************************\
232 \***************************************************************************/
234 /*-------------------------------------------------------------------------*\
236 \*-------------------------------------------------------------------------*/
238 /*----------------------- constructors & destructors ----------------------*/
240 ShaderShadowMapEngine::ShaderShadowMapEngine(void) :
245 ShaderShadowMapEngine::ShaderShadowMapEngine(const ShaderShadowMapEngine
&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
);
266 SSMEngineDataUnrecPtr newData
= SSMEngineData::createLocal();
267 this->setData(newData
, _iDataSlotId
, ract
);
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
);
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
,
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
329 boost::polymorphic_downcast
<PointLight
*>(light
);
331 handlePointLightEnter(pointL
, ract
, data
);
337 DirectionalLight
*dirL
=
338 boost::polymorphic_downcast
<DirectionalLight
*>(light
);
340 handleDirectionalLightEnter(dirL
, ract
, data
);
347 boost::polymorphic_downcast
<SpotLight
*>(light
);
349 handleSpotLightEnter(spotL
, ract
, data
);
355 FWARNING(("ShaderShadowMapEngine::handleEnter: Unknown "
356 "light type [%u]\n", eType
));
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());
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();
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
;
412 shadowFP
->updateUniformVariable("SSME_matEyeToLight", matEyeToLight
);
413 shadowFP
->updateUniformVariable("SSME_matLightProj", matLightProj
);
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
,
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 );
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
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)
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]),
537 Pnt3f
lightMax(osgMin(camVerts
[9][0], sceneVerts
[9][0]),
538 osgMin(camVerts
[9][1], sceneVerts
[9][1]),
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
;
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();
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
;
582 shadowFP
->updateUniformVariable("SSME_matEyeToLight", matEyeToLight
);
583 shadowFP
->updateUniformVariable("SSME_matLightProj", matLightProj
);
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
,
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 );
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
);
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();
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();
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
;
686 shadowFP
->updateUniformVariable("SSME_matEyeToLight", matEyeToLight
);
687 shadowFP
->updateUniformVariable("SSME_matLightProj", matLightProj
);
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
,
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 );
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());
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
);
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
);
784 matLightPos
.setTranslate(spotL
->getPosition());
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
;
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
);
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
);
834 else if(osgAbs(kL
) > TypeTraits
<Real32
>::getDefaultEps())
836 Real32 r
= (1.f
/ lightThreshold
- kC
) / kL
;
845 void ShaderShadowMapEngine::updateShadowTexChunk(SSMEngineData
*data
)
847 TextureObjChunk
*bufTex
= data
->getShadowTexChunk();
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();
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)
919 ImageUnrecPtr newBufImg
= Image::createLocal();
920 newBufImg
->set(Image::OSG_L_PF
,
928 Image::OSG_UINT8_IMAGEDATA
,
932 bufTex
->setImage (newBufImg
);
933 data
->setShadowTexImage(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)
955 ImageUnrecPtr newBufImg
= Image::createLocal();
956 newBufImg
->set(Image::OSG_L_PF
,
964 Image::OSG_UINT8_IMAGEDATA
,
968 bufTex
->setImage (newBufImg
);
969 data
->setShadowTexImage(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(
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
);
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
);
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());