1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 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 \*---------------------------------------------------------------------------*/
42 #include "OSGConfig.h"
44 #include "OSGSimpleShadowMapEngine.h"
46 #include "OSGMatrixCamera.h"
48 #include "OSGMatrixUtility.h"
49 #include "OSGRenderAction.h"
51 #include "OSGRenderPartition.h"
52 #include "OSGFrameBufferObject.h"
54 #include "OSGChunkMaterial.h"
56 #include "OSGTextureBuffer.h"
57 #include "OSGTextureObjChunk.h"
58 #include "OSGPolygonChunk.h"
59 #include "OSGTexGenChunk.h"
60 #include "OSGBlendChunk.h"
65 // Documentation for this class is emited in the
66 // OSGSimpleShadowMapEngineBase.cpp file.
67 // To modify it, please change the .fcd file (OSGSimpleShadowMapEngine.fcd) and
68 // regenerate the base file.
71 /*! \class OSG::SimpleShadowMapEngine
74 /*-------------------------------------------------------------------------*/
77 void SimpleShadowMapEngine::changed(ConstFieldMaskArg whichField
,
81 Inherited::changed(whichField
, origin
, details
);
84 /*-------------------------------------------------------------------------*/
87 void SimpleShadowMapEngine::dump( UInt32 uiIndent
,
88 const BitVector bvFlags
) const
90 Inherited::dump(uiIndent
, bvFlags
);
93 /*-------------------------------------------------------------------------*/
96 SimpleShadowMapEngine::SimpleShadowMapEngine(void) :
101 SimpleShadowMapEngine::SimpleShadowMapEngine(
102 const SimpleShadowMapEngine
&source
) :
108 /*-------------------------------------------------------------------------*/
111 SimpleShadowMapEngine::~SimpleShadowMapEngine(void)
116 /*-------------------------------------------------------------------------*/
119 void SimpleShadowMapEngine::initMethod(InitPhase ePhase
)
121 Inherited::initMethod(ePhase
);
123 if(ePhase
== TypeObject::SystemPost
)
128 void SimpleShadowMapEngine::lightRenderEnter(Light
*pLight
,
129 RenderAction
*pAction
)
131 if(pLight
->getOn() == false)
134 StateChunk
*pChunk
= pLight
->getChunk();
136 UInt32 uiSlot
= pChunk
->getClassId();
138 Int32 iLightIndex
= pAction
->allocateLightIndex();
140 // LightChunk *pLightChunk = dynamic_cast<LightChunk *>(pChunk);
142 // Color4f tmpVal(0.0, 0.0, 0.0, 1.0);
144 // pLightChunk->setAmbient(tmpVal);
149 pAction
->addOverride(uiSlot
+ iLightIndex
, pChunk
);
153 SWARNING
<< "maximum light source limit ("
156 << " skipping light sources!"
161 void SimpleShadowMapEngine::setupCamera(Light
*pLight
,
163 RenderAction
*pAction
,
164 EngineDataPtr pEngineData
)
166 if(eType
== Directional
)
168 DirectionalLight
*pDLight
=
169 dynamic_cast<DirectionalLight
*>(pLight
);
171 MatrixCameraUnrecPtr pCam
=
172 dynamic_cast<MatrixCamera
*>(pEngineData
->getCamera());
176 pCam
= MatrixCamera::createLocal();
178 pEngineData
->setCamera(pCam
);
185 Node
*pNode
= pAction
->getActNode();
187 // tmpDir = DirectionalLightPtr::dcast(_lights[i]);
189 diff
= (pNode
->getVolume().getMax() -
190 pNode
->getVolume().getMin());
192 Real32 sceneWidth
= diff
.length() * 0.5f
;
193 // Not final values. May get tweaked in the future
195 Real32 sceneHeight
= diff
.length() * 0.5f
;
197 pNode
->getVolume().getCenter(center
);
199 Vec3f lightdir
= pDLight
->getDirection();
201 if(pLight
->getBeacon() != NULL
)
203 Matrix m
= pLight
->getBeacon()->getToWorld();
205 m
.mult(lightdir
, lightdir
);
208 MatrixLookAt(transMatrix
,
213 transMatrix
.invert();
217 proMatrix
.setIdentity();
219 MatrixOrthogonal( proMatrix
,
220 -sceneWidth
, sceneWidth
, -sceneHeight
,
221 sceneHeight
, -sceneWidth
, sceneWidth
);
224 pCam
->setProjectionMatrix(proMatrix
);
225 pCam
->setModelviewMatrix (transMatrix
);
227 else if(eType
== Point
)
229 PointLight
*pPLight
= dynamic_cast<PointLight
*>(pLight
);
231 MatrixCameraUnrecPtr pCam
=
232 dynamic_cast<MatrixCamera
*>(pEngineData
->getCamera());
236 pCam
= MatrixCamera::createLocal();
238 pEngineData
->setCamera(pCam
);
248 Node
*pNode
= pAction
->getActNode();
251 pNode
->getVolume().getCenter(center
);
253 Pnt3f lightpos
= pPLight
->getPosition();
255 if(pLight
->getBeacon() != NULL
)
257 Matrix m
= pLight
->getBeacon()->getToWorld();
259 m
.mult(lightpos
, lightpos
);
263 MatrixLookAt(transMatrix
,
268 transMatrix
.invert();
271 diff
= (pNode
->getVolume().getMax() -
272 pNode
->getVolume().getMin());
274 dist
= lightpos
- center
;
276 angle
= atan((diff
.length() * 0.5) / dist
.length());
280 proMatrix
.setIdentity();
282 MatrixPerspective( proMatrix
,
285 pAction
->getActivePartition()->getNear(),
286 pAction
->getActivePartition()->getFar ());
289 pCam
->setProjectionMatrix(proMatrix
);
290 pCam
->setModelviewMatrix (transMatrix
);
294 void SimpleShadowMapEngine::setupLightChunk(Light
*pLight
,
296 RenderAction
*pAction
,
297 EngineDataPtr pEngineData
)
299 if(eType
== Directional
)
301 DirectionalLight
*pDLight
=
302 dynamic_cast<DirectionalLight
*>(pLight
);
304 LightChunkUnrecPtr pChunk
= pEngineData
->getLightChunk();
308 pChunk
= LightChunk::createLocal();
310 pEngineData
->setLightChunk(pChunk
);
313 Color4f
tmpVal(0.0, 0.0, 0.0, 1.0);
315 pChunk
->setSpecular(tmpVal
);
317 tmpVal
.setValuesRGBA(0.2f
, 0.2f
, 0.2f
, 1.0f
);
319 pChunk
->setDiffuse (tmpVal
);
321 tmpVal
.setValuesRGBA(0.0, 0.0, 0.0, 1.0);
323 pChunk
->setAmbient (tmpVal
);
325 Vec4f
dir(pDLight
->getDirection());
329 pChunk
->setPosition(dir
);
331 pChunk
->setBeacon(pLight
->getBeacon());
333 else if(eType
== Point
)
335 PointLight
*pPLight
= dynamic_cast<PointLight
*>(pLight
);
337 LightChunkUnrecPtr pChunk
= pEngineData
->getLightChunk();
341 pChunk
= LightChunk::createLocal();
343 pEngineData
->setLightChunk(pChunk
);
346 Color4f
tmpVal(0.0, 0.0, 0.0, 1.0);
348 pChunk
->setSpecular(tmpVal
);
350 tmpVal
.setValuesRGBA(this->getShadowColor()[0],
351 this->getShadowColor()[1],
352 this->getShadowColor()[2],
353 this->getShadowColor()[3]);
355 pChunk
->setDiffuse (tmpVal
);
357 tmpVal
.setValuesRGBA(0.0, 0.0, 0.0, 1.0);
359 pChunk
->setAmbient (tmpVal
);
361 Vec4f
pos(pPLight
->getPosition());
365 pChunk
->setPosition(pos
);
367 pChunk
->setBeacon(pLight
->getBeacon());
372 void SimpleShadowMapEngine::doLightPass(Light
*pLight
,
373 RenderAction
*pAction
,
374 EngineDataPtr pEngineData
)
376 this->pushPartition(pAction
);
378 RenderPartition
*pPart
= pAction
->getActivePartition();
379 Viewarea
*pArea
= pAction
->getViewarea ();
380 Background
*pBack
= pAction
->getBackground ();
382 FrameBufferObject
*pTarget
= pEngineData
->getRenderTarget();
386 FrameBufferObjectUnrecPtr pFBO
= FrameBufferObject::createLocal();
388 pFBO
->setWidth (this->getWidth ());
389 pFBO
->setHeight(this->getHeight());
391 pEngineData
->setRenderTarget(pFBO
);
396 TextureObjChunk
*pTexChunk
= pEngineData
->getTexChunk();
399 TextureBufferUnrecPtr pTexBuffer
= pEngineData
->getTexBuffer();
401 if(pTexBuffer
== NULL
)
403 pTexBuffer
= TextureBuffer::createLocal();
405 pEngineData
->setTexBuffer (pTexBuffer
);
407 pTexBuffer
->setTexture (pTexChunk
);
408 pTarget
->setDepthAttachment(pTexBuffer
);
411 PolygonChunkUnrecPtr pPoly
= pEngineData
->getPolyChunk();
415 pPoly
= PolygonChunk::createLocal();
417 pPoly
->setOffsetBias (this->getOffsetBias ());
418 pPoly
->setOffsetFactor(this->getOffsetFactor());
419 pPoly
->setOffsetFill (true );
421 pEngineData
->setPolyChunk(pPoly
);
424 pPart
->setRenderTarget(pTarget
);
428 Camera
*pCam
= pEngineData
->getCamera();
430 pPart
->setWindow (pAction
->getWindow());
432 pPart
->calcViewportDimension(0.f
, 0.f
, 1.f
, 1.f
,
433 pTarget
->getWidth (),
434 pTarget
->getHeight ());
438 // set the projection
439 pCam
->getProjection (m
,
440 pPart
->getViewportWidth (),
441 pPart
->getViewportHeight());
443 pCam
->getProjectionTranslation(t
,
444 pPart
->getViewportWidth (),
445 pPart
->getViewportHeight());
448 pPart
->setupProjection(m
, t
);
451 pPart
->getViewportWidth (),
452 pPart
->getViewportHeight());
455 pPart
->setupViewing(m
);
457 pPart
->setNear (pCam
->getNear());
458 pPart
->setFar (pCam
->getFar ());
460 pPart
->calcFrustum ();
462 pPart
->setBackground(pBack
);
465 Node
*pActNode
= pAction
->getActNode();
467 pAction
->overrideMaterial(_pLightPassMat
, pActNode
);
469 pAction
->pushState();
471 UInt32 uiPolySlot
= pPoly
->getClassId();
473 pAction
->addOverride (uiPolySlot
, pPoly
);
475 // lightRenderEnter(pLight, pAction);
477 pAction
->useNodeList(false);
479 this->recurseFrom(pAction
, pLight
);
483 pAction
->overrideMaterial(NULL
, pActNode
);
485 this->popPartition(pAction
);
488 void SimpleShadowMapEngine::doAmbientPass(Light
*pLight
,
489 RenderAction
*pAction
,
490 EngineDataPtr pEngineData
)
492 this->pushPartition(pAction
,
493 (RenderPartition::CopyViewing
|
494 RenderPartition::CopyProjection
|
495 RenderPartition::CopyWindow
|
496 RenderPartition::CopyViewportSize
|
497 RenderPartition::CopyFrustum
|
498 RenderPartition::CopyNearFar
));
500 LightChunk
*pChunk
= pEngineData
->getLightChunk();
502 UInt32 uiSlot
= pChunk
->getClassId();
504 Int32 iLightIndex
= pAction
->allocateLightIndex();
506 pAction
->pushState();
510 pAction
->addOverride(uiSlot
+ iLightIndex
, pChunk
);
514 SWARNING
<< "maximum light source limit ("
517 << " skipping light sources!"
521 pAction
->useNodeList(false);
523 this->recurseFrom(pAction
, pLight
);
527 this->popPartition(pAction
);
530 void SimpleShadowMapEngine::doFinalPass(Light
*pLight
,
531 RenderAction
*pAction
,
532 EngineDataPtr pEngineData
)
534 this->pushPartition(pAction
,
535 (RenderPartition::CopyViewing
|
536 RenderPartition::CopyProjection
|
537 RenderPartition::CopyWindow
|
538 RenderPartition::CopyViewportSize
|
539 RenderPartition::CopyFrustum
|
540 RenderPartition::CopyNearFar
));
542 FrameBufferObject
*pTarget
= pEngineData
->getRenderTarget();
546 FrameBufferObjectUnrecPtr pFBO
= FrameBufferObject::createLocal();
548 pFBO
->setWidth (this->getWidth ());
549 pFBO
->setHeight(this->getHeight());
551 pEngineData
->setRenderTarget(pFBO
);
556 BlendChunkUnrecPtr pBlender
= pEngineData
->getBlendChunk();
560 pBlender
= BlendChunk::createLocal();
562 pBlender
->setSrcFactor(GL_ONE
);
563 pBlender
->setDestFactor(GL_ONE
);
564 pBlender
->setAlphaFunc(GL_GEQUAL
);
565 pBlender
->setAlphaValue(0.99f
);
567 pEngineData
->setBlendChunk(pBlender
);
571 Matrix4f projectionMatrix
, viewMatrix
, biasMatrix
;
573 biasMatrix
.setIdentity();
574 biasMatrix
.setScale(0.5);
575 biasMatrix
.setTranslate(0.5,0.5,0.5);
577 MatrixCamera
*pCam
= dynamic_cast<MatrixCamera
*>(
578 pEngineData
->getCamera());
580 pCam
->getProjection(projectionMatrix
,
584 pCam
->getViewing (viewMatrix
,
588 Matrix textureMatrix
= biasMatrix
;
589 textureMatrix
.mult(projectionMatrix
);
590 textureMatrix
.mult(viewMatrix
);
592 textureMatrix
.transpose();
593 Vec4f ps
= textureMatrix
[0];
594 Vec4f pt
= textureMatrix
[1];
595 Vec4f pr
= textureMatrix
[2];
596 Vec4f pq
= textureMatrix
[3];
598 TexGenChunkUnrecPtr pTexGen
= pEngineData
->getTexGenChunk();
602 pTexGen
= TexGenChunk::createLocal();
604 pEngineData
->setTexGenChunk(pTexGen
);
606 pTexGen
->setEyeModelViewMode(TexGenChunk::EyeModelViewCamera
);
608 pTexGen
->setGenFuncS(GL_EYE_LINEAR
);
609 pTexGen
->setGenFuncT(GL_EYE_LINEAR
);
610 pTexGen
->setGenFuncR(GL_EYE_LINEAR
);
611 pTexGen
->setGenFuncQ(GL_EYE_LINEAR
);
614 pTexGen
->setGenFuncSPlane(ps
);
615 pTexGen
->setGenFuncTPlane(pt
);
616 pTexGen
->setGenFuncRPlane(pr
);
617 pTexGen
->setGenFuncQPlane(pq
);
619 TextureObjChunkUnrecPtr pTexChunk
= pEngineData
->getTexChunk();
621 if(pTexChunk
== NULL
)
623 pTexChunk
= TextureObjChunk::createLocal();
625 pEngineData
->setTexChunk(pTexChunk
);
627 ImageUnrecPtr pImage
= Image::createLocal();
629 // creates a image without allocating main memory.
631 pImage
->set(Image::OSG_L_PF
,
632 pTarget
->getWidth (),
633 pTarget
->getHeight(),
639 Image::OSG_UINT8_IMAGEDATA
,
643 pTexChunk
->setImage (pImage
);
644 pTexChunk
->setInternalFormat(GL_DEPTH_COMPONENT32
);
645 pTexChunk
->setExternalFormat(GL_DEPTH_COMPONENT
);
646 pTexChunk
->setMinFilter (GL_LINEAR
);
647 pTexChunk
->setMagFilter (GL_LINEAR
);
648 pTexChunk
->setWrapS (GL_CLAMP_TO_BORDER
);
649 pTexChunk
->setWrapT (GL_CLAMP_TO_BORDER
);
650 // pTexChunk->setEnvMode (GL_MODULATE);
651 pTexChunk
->setTarget (GL_TEXTURE_2D
);
653 pTexChunk
->setCompareMode(GL_COMPARE_R_TO_TEXTURE
);
654 pTexChunk
->setCompareFunc(GL_LEQUAL
);
655 pTexChunk
->setDepthMode (GL_INTENSITY
);
658 pAction
->pushState();
660 UInt32 uiBlendSlot
= pBlender
->getClassId();
661 UInt32 uiTexSlot
= pTexChunk
->getClassId();
662 UInt32 uiTexGenSlot
= pTexGen
->getClassId();
664 if(this->getForceTextureUnit() != -1)
666 uiTexSlot
+= this->getForceTextureUnit();
667 uiTexGenSlot
+= this->getForceTextureUnit();
675 pAction
->addOverride(uiBlendSlot
, pBlender
);
676 pAction
->addOverride(uiTexSlot
, pTexChunk
);
677 pAction
->addOverride(uiTexGenSlot
, pTexGen
);
679 lightRenderEnter(pLight
, pAction
);
681 pAction
->useNodeList(false);
683 this->recurseFrom(pAction
, pLight
);
687 this->popPartition(pAction
);
691 Action::ResultE
SimpleShadowMapEngine::runOnEnter(
694 RenderAction
*pAction
)
696 EngineDataUnrecPtr pEngineData
=
697 pAction
->getData
<SimpleShadowMapEngineData
*>(_iDataSlotId
);
699 if(pEngineData
== NULL
)
701 pEngineData
= EngineData::createLocal();
703 this->setData(pEngineData
, _iDataSlotId
, pAction
);
706 BitVector bvMask
= pAction
->getPassMask() & (bvLightPassMask
|
711 fprintf(stderr, "%p %llu %llu | %llu %llu %llu\n",
724 if(0x0000 != (bvMask
& bvDiffusePassMask
))
726 this->recurseFrom(pAction
, pLight
);
728 setupCamera (pLight
, eType
, pAction
, pEngineData
);
729 doFinalPass (pLight
, pAction
, pEngineData
);
732 if(0x0000 != (bvMask
& bvAmbientPassMask
))
734 this->recurseFrom(pAction
, pLight
);
736 setupLightChunk(pLight
, eType
, pAction
, pEngineData
);
739 if(0x0000 != (bvMask
& bvLightPassMask
))
741 this->recurseFrom(pAction
, pLight
);
743 doLightPass (pLight
, pAction
, pEngineData
);
748 setupCamera (pLight
, eType
, pAction
, pEngineData
);
750 setupLightChunk(pLight
, eType
, pAction
, pEngineData
);
752 pAction
->addPassMask(bvDiffusePassMask
);
753 doFinalPass (pLight
, pAction
, pEngineData
);
754 pAction
->subPassMask(bvDiffusePassMask
);
756 pAction
->addPassMask(bvAmbientPassMask
);
757 doAmbientPass (pLight
, pAction
, pEngineData
);
758 pAction
->subPassMask(bvAmbientPassMask
);
760 pAction
->addPassMask(bvLightPassMask
);
761 doLightPass (pLight
, pAction
, pEngineData
);
762 pAction
->subPassMask(bvLightPassMask
);
768 Action::ResultE
SimpleShadowMapEngine::runOnLeave(
771 RenderAction
*pAction
)
773 return Action::Continue
;