00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <cstdlib>
00040 #include <cstdio>
00041
00042 #include "OSGConfig.h"
00043
00044 #include "OSGSimpleShadowMapEngine.h"
00045
00046 #include "OSGMatrixCamera.h"
00047
00048 #include "OSGMatrixUtility.h"
00049 #include "OSGRenderAction.h"
00050
00051 #include "OSGRenderPartition.h"
00052 #include "OSGFrameBufferObject.h"
00053 #include "OSGGroup.h"
00054 #include "OSGChunkMaterial.h"
00055
00056 #include "OSGTextureBuffer.h"
00057 #include "OSGTextureObjChunk.h"
00058 #include "OSGPolygonChunk.h"
00059 #include "OSGTexGenChunk.h"
00060 #include "OSGBlendChunk.h"
00061
00062 OSG_USING_NAMESPACE
00063
00064
00065
00066
00067
00068
00069
00073
00074
00075
00076 void SimpleShadowMapEngine::changed(ConstFieldMaskArg whichField,
00077 UInt32 origin,
00078 BitVector details)
00079 {
00080 Inherited::changed(whichField, origin, details);
00081 }
00082
00083
00084
00085
00086 void SimpleShadowMapEngine::dump( UInt32 uiIndent,
00087 const BitVector bvFlags) const
00088 {
00089 Inherited::dump(uiIndent, bvFlags);
00090 }
00091
00092
00093
00094
00095 SimpleShadowMapEngine::SimpleShadowMapEngine(void) :
00096 Inherited( )
00097 {
00098 }
00099
00100 SimpleShadowMapEngine::SimpleShadowMapEngine(
00101 const SimpleShadowMapEngine &source) :
00102
00103 Inherited(source)
00104 {
00105 }
00106
00107
00108
00109
00110 SimpleShadowMapEngine::~SimpleShadowMapEngine(void)
00111 {
00112 }
00113
00114
00115
00116
00117
00118 void SimpleShadowMapEngine::initMethod(InitPhase ePhase)
00119 {
00120 Inherited::initMethod(ePhase);
00121
00122 if(ePhase == TypeObject::SystemPost)
00123 {
00124 }
00125 }
00126
00127 void SimpleShadowMapEngine::lightRenderEnter(Light *pLight,
00128 RenderAction *pAction)
00129 {
00130 if(pLight->getOn() == false)
00131 return;
00132
00133 StateChunk *pChunk = pLight->getChunk();
00134
00135 UInt32 uiSlot = pChunk->getClassId();
00136
00137 Int32 iLightIndex = pAction->allocateLightIndex();
00138
00139
00140
00141
00142
00143
00144
00145
00146 if(iLightIndex >= 0)
00147 {
00148 pAction->addOverride(uiSlot + iLightIndex, pChunk);
00149 }
00150 else
00151 {
00152 SWARNING << "maximum light source limit ("
00153 << -iLightIndex
00154 << ") is reached"
00155 << " skipping light sources!"
00156 << std::endl;
00157 }
00158 }
00159
00160 void SimpleShadowMapEngine::setupCamera(Light *pLight,
00161 LightTypeE eType,
00162 RenderAction *pAction,
00163 EngineDataPtr pEngineData)
00164 {
00165 if(eType == Directional)
00166 {
00167 DirectionalLight *pDLight =
00168 dynamic_cast<DirectionalLight *>(pLight);
00169
00170 MatrixCameraUnrecPtr pCam =
00171 dynamic_cast<MatrixCamera *>(pEngineData->getCamera());
00172
00173 if(pCam == NULL)
00174 {
00175 pCam = MatrixCamera::createLocal();
00176
00177 pEngineData->setCamera(pCam);
00178 }
00179
00180
00181 Vec3f diff;
00182 Pnt3f center;
00183 Matrix transMatrix;
00184 Node *pNode = pAction->getActNode();
00185
00186
00187
00188 diff = (pNode->getVolume().getMax() -
00189 pNode->getVolume().getMin());
00190
00191 Real32 sceneWidth = diff.length() * 0.5f;
00192
00193
00194 Real32 sceneHeight = diff.length() * 0.5f;
00195
00196 pNode->getVolume().getCenter(center);
00197
00198 Vec3f lightdir = pDLight->getDirection();
00199
00200 if(pLight->getBeacon() != NULL)
00201 {
00202 Matrix m = pLight->getBeacon()->getToWorld();
00203
00204 m.mult(lightdir, lightdir);
00205 }
00206
00207 MatrixLookAt(transMatrix,
00208 center + lightdir,
00209 center,
00210 Vec3f(0,1,0));
00211
00212 transMatrix.invert();
00213
00214 Matrix proMatrix;
00215
00216 proMatrix.setIdentity();
00217
00218 MatrixOrthogonal( proMatrix,
00219 -sceneWidth, sceneWidth, -sceneHeight,
00220 sceneHeight, -sceneWidth, sceneWidth);
00221
00222
00223 pCam->setProjectionMatrix(proMatrix );
00224 pCam->setModelviewMatrix (transMatrix);
00225 }
00226 else if(eType == Point)
00227 {
00228 PointLight *pPLight = dynamic_cast<PointLight *>(pLight);
00229
00230 MatrixCameraUnrecPtr pCam =
00231 dynamic_cast<MatrixCamera *>(pEngineData->getCamera());
00232
00233 if(pCam == NULL)
00234 {
00235 pCam = MatrixCamera::createLocal();
00236
00237 pEngineData->setCamera(pCam);
00238 }
00239
00240 Real32 angle;
00241 Vec3f dist;
00242 Pnt3f center;
00243 Vec3f diff;
00244
00245 Matrix transMatrix;
00246
00247 Node *pNode = pAction->getActNode();
00248
00249
00250 pNode->getVolume().getCenter(center);
00251
00252 Pnt3f lightpos = pPLight->getPosition();
00253
00254 if(pLight->getBeacon() != NULL)
00255 {
00256 Matrix m = pLight->getBeacon()->getToWorld();
00257
00258 m.mult(lightpos, lightpos);
00259 }
00260
00261
00262 MatrixLookAt(transMatrix,
00263 lightpos,
00264 center,
00265 Vec3f(0,1,0));
00266
00267 transMatrix.invert();
00268
00269
00270 diff = (pNode->getVolume().getMax() -
00271 pNode->getVolume().getMin());
00272
00273 dist = lightpos - center;
00274
00275 angle = atan((diff.length() * 0.5) / dist.length());
00276
00277 Matrix proMatrix;
00278
00279 proMatrix.setIdentity();
00280
00281 MatrixPerspective( proMatrix,
00282 2.f * angle,
00283 1,
00284 pAction->getActivePartition()->getNear(),
00285 pAction->getActivePartition()->getFar ());
00286
00287
00288 pCam->setProjectionMatrix(proMatrix );
00289 pCam->setModelviewMatrix (transMatrix);
00290 }
00291 }
00292
00293 void SimpleShadowMapEngine::setupLightChunk(Light *pLight,
00294 LightTypeE eType,
00295 RenderAction *pAction,
00296 EngineDataPtr pEngineData)
00297 {
00298 if(eType == Directional)
00299 {
00300 DirectionalLight *pDLight =
00301 dynamic_cast<DirectionalLight *>(pLight);
00302
00303 LightChunkUnrecPtr pChunk = pEngineData->getLightChunk();
00304
00305 if(pChunk == NULL)
00306 {
00307 pChunk = LightChunk::createLocal();
00308
00309 pEngineData->setLightChunk(pChunk);
00310 }
00311
00312 Color4f tmpVal(0.0, 0.0, 0.0, 1.0);
00313
00314 pChunk->setSpecular(tmpVal);
00315
00316 tmpVal.setValuesRGBA(0.2f, 0.2f, 0.2f, 1.0f);
00317
00318 pChunk->setDiffuse (tmpVal);
00319
00320 tmpVal.setValuesRGBA(0.0, 0.0, 0.0, 1.0);
00321
00322 pChunk->setAmbient (tmpVal);
00323
00324 Vec4f dir(pDLight->getDirection());
00325
00326 dir[3] = 0;
00327
00328 pChunk->setPosition(dir);
00329
00330 pChunk->setBeacon(pLight->getBeacon());
00331 }
00332 else if(eType == Point)
00333 {
00334 PointLight *pPLight = dynamic_cast<PointLight *>(pLight);
00335
00336 LightChunkUnrecPtr pChunk = pEngineData->getLightChunk();
00337
00338 if(pChunk == NULL)
00339 {
00340 pChunk = LightChunk::createLocal();
00341
00342 pEngineData->setLightChunk(pChunk);
00343 }
00344
00345 Color4f tmpVal(0.0, 0.0, 0.0, 1.0);
00346
00347 pChunk->setSpecular(tmpVal);
00348
00349 tmpVal.setValuesRGBA(this->getShadowColor()[0],
00350 this->getShadowColor()[1],
00351 this->getShadowColor()[2],
00352 this->getShadowColor()[3]);
00353
00354 pChunk->setDiffuse (tmpVal);
00355
00356 tmpVal.setValuesRGBA(0.0, 0.0, 0.0, 1.0);
00357
00358 pChunk->setAmbient (tmpVal);
00359
00360 Vec4f pos(pPLight->getPosition());
00361
00362 pos[3] = 1;
00363
00364 pChunk->setPosition(pos);
00365
00366 pChunk->setBeacon(pLight->getBeacon());
00367 }
00368 }
00369
00370
00371 void SimpleShadowMapEngine::doLightPass(Light *pLight,
00372 RenderAction *pAction,
00373 EngineDataPtr pEngineData)
00374 {
00375 pAction->pushPartition();
00376
00377 RenderPartition *pPart = pAction ->getActivePartition();
00378 Viewport *pPort = pAction ->getViewport ();
00379 Background *pBack = pAction ->getBackground ();
00380
00381 FrameBufferObject *pTarget = pEngineData->getRenderTarget();
00382
00383 if(pTarget == NULL)
00384 {
00385 FrameBufferObjectUnrecPtr pFBO = FrameBufferObject::createLocal();
00386
00387 pFBO->setWidth (this->getWidth ());
00388 pFBO->setHeight(this->getHeight());
00389
00390 pEngineData->setRenderTarget(pFBO);
00391
00392 pTarget = pFBO;
00393 }
00394
00395 TextureObjChunk *pTexChunk = pEngineData->getTexChunk();
00396
00397
00398 TextureBufferUnrecPtr pTexBuffer = pEngineData->getTexBuffer();
00399
00400 if(pTexBuffer == NULL)
00401 {
00402 pTexBuffer = TextureBuffer::createLocal();
00403
00404 pEngineData->setTexBuffer (pTexBuffer);
00405
00406 pTexBuffer->setTexture (pTexChunk );
00407 pTarget ->setDepthAttachment(pTexBuffer);
00408 }
00409
00410 PolygonChunkUnrecPtr pPoly = pEngineData->getPolyChunk();
00411
00412 if(pPoly == NULL)
00413 {
00414 pPoly = PolygonChunk::createLocal();
00415
00416 pPoly->setOffsetBias (this->getOffsetBias ());
00417 pPoly->setOffsetFactor(this->getOffsetFactor());
00418 pPoly->setOffsetFill (true );
00419
00420 pEngineData->setPolyChunk(pPoly);
00421 }
00422
00423 pPart->setRenderTarget(pTarget);
00424
00425 if(pPort != NULL)
00426 {
00427 Camera *pCam = pEngineData->getCamera();
00428
00429
00430 pPart->setWindow (pAction->getWindow());
00431
00432 pPart->calcViewportDimension(pPort->getLeft (),
00433 pPort->getBottom(),
00434 pPort->getRight (),
00435 pPort->getTop (),
00436
00437 pTarget->getWidth (),
00438 pTarget->getHeight ());
00439
00440 Matrix m, t;
00441
00442
00443 pCam->getProjection (m,
00444 pPart->getViewportWidth (),
00445 pPart->getViewportHeight());
00446
00447 pCam->getProjectionTranslation(t,
00448 pPart->getViewportWidth (),
00449 pPart->getViewportHeight());
00450
00451
00452 pPart->setupProjection(m, t);
00453
00454 pCam->getViewing(m,
00455 pPart->getViewportWidth (),
00456 pPart->getViewportHeight());
00457
00458
00459 pPart->setupViewing(m);
00460
00461 pPart->setNear (pCam->getNear());
00462 pPart->setFar (pCam->getFar ());
00463
00464 pPart->calcFrustum ();
00465
00466 pPart->setBackground(pBack);
00467 }
00468
00469 Node *pActNode = pAction->getActNode();
00470
00471 pAction->overrideMaterial(_pLightPassMat, pActNode);
00472
00473 pAction->pushState();
00474
00475 UInt32 uiPolySlot = pPoly->getClassId();
00476
00477 pAction->addOverride (uiPolySlot, pPoly);
00478
00479
00480
00481 pAction->useNodeList(false);
00482
00483 this->recurseFrom(pAction, pLight);
00484
00485 pAction->popState();
00486
00487 pAction->overrideMaterial(NULL, pActNode);
00488
00489 pAction->popPartition();
00490 }
00491
00492 void SimpleShadowMapEngine::doAmbientPass(Light *pLight,
00493 RenderAction *pAction,
00494 EngineDataPtr pEngineData)
00495 {
00496 pAction->pushPartition((RenderPartition::CopyViewing |
00497 RenderPartition::CopyProjection |
00498 RenderPartition::CopyWindow |
00499 RenderPartition::CopyViewportSize |
00500 RenderPartition::CopyFrustum |
00501 RenderPartition::CopyNearFar ));
00502
00503 LightChunk *pChunk = pEngineData->getLightChunk();
00504
00505 UInt32 uiSlot = pChunk->getClassId();
00506
00507 Int32 iLightIndex = pAction->allocateLightIndex();
00508
00509 pAction->pushState();
00510
00511 if(iLightIndex >= 0)
00512 {
00513 pAction->addOverride(uiSlot + iLightIndex, pChunk);
00514 }
00515 else
00516 {
00517 SWARNING << "maximum light source limit ("
00518 << -iLightIndex
00519 << ") is reached"
00520 << " skipping light sources!"
00521 << std::endl;
00522 }
00523
00524 pAction->useNodeList(false);
00525
00526 this->recurseFrom(pAction, pLight);
00527
00528 pAction->popState();
00529
00530 pAction->popPartition ();
00531 }
00532
00533 void SimpleShadowMapEngine::doFinalPass(Light *pLight,
00534 RenderAction *pAction,
00535 EngineDataPtr pEngineData)
00536 {
00537 pAction->pushPartition((RenderPartition::CopyViewing |
00538 RenderPartition::CopyProjection |
00539 RenderPartition::CopyWindow |
00540 RenderPartition::CopyViewportSize |
00541 RenderPartition::CopyFrustum |
00542 RenderPartition::CopyNearFar ));
00543
00544 FrameBufferObject *pTarget = pEngineData->getRenderTarget();
00545
00546 if(pTarget == NULL)
00547 {
00548 FrameBufferObjectUnrecPtr pFBO = FrameBufferObject::createLocal();
00549
00550 pFBO->setWidth (this->getWidth ());
00551 pFBO->setHeight(this->getHeight());
00552
00553 pEngineData->setRenderTarget(pFBO);
00554
00555 pTarget = pFBO;
00556 }
00557
00558 BlendChunkUnrecPtr pBlender = pEngineData->getBlendChunk();
00559
00560 if(pBlender == NULL)
00561 {
00562 pBlender = BlendChunk::createLocal();
00563
00564 pBlender->setSrcFactor(GL_ONE);
00565 pBlender->setDestFactor(GL_ONE);
00566 pBlender->setAlphaFunc(GL_GEQUAL);
00567 pBlender->setAlphaValue(0.99f);
00568
00569 pEngineData->setBlendChunk(pBlender);
00570 }
00571
00572
00573 Matrix4f projectionMatrix, viewMatrix, biasMatrix;
00574
00575 biasMatrix.setIdentity();
00576 biasMatrix.setScale(0.5);
00577 biasMatrix.setTranslate(0.5,0.5,0.5);
00578
00579 MatrixCamera *pCam = dynamic_cast<MatrixCamera *>(
00580 pEngineData->getCamera());
00581
00582 pCam->getProjection(projectionMatrix,
00583 this->getWidth (),
00584 this->getHeight());
00585
00586 pCam->getViewing (viewMatrix,
00587 this->getWidth (),
00588 this->getHeight());
00589
00590 Matrix textureMatrix = biasMatrix;
00591 textureMatrix.mult(projectionMatrix);
00592 textureMatrix.mult(viewMatrix);
00593
00594 textureMatrix.transpose();
00595 Vec4f ps = textureMatrix[0];
00596 Vec4f pt = textureMatrix[1];
00597 Vec4f pr = textureMatrix[2];
00598 Vec4f pq = textureMatrix[3];
00599
00600 TexGenChunkUnrecPtr pTexGen = pEngineData->getTexGenChunk();
00601
00602 if(pTexGen == NULL)
00603 {
00604 pTexGen = TexGenChunk::createLocal();
00605
00606 pEngineData->setTexGenChunk(pTexGen);
00607
00608 pTexGen->setEyeModelViewMode(TexGenChunk::EyeModelViewCamera);
00609
00610 pTexGen->setGenFuncS(GL_EYE_LINEAR);
00611 pTexGen->setGenFuncT(GL_EYE_LINEAR);
00612 pTexGen->setGenFuncR(GL_EYE_LINEAR);
00613 pTexGen->setGenFuncQ(GL_EYE_LINEAR);
00614 }
00615
00616 pTexGen->setGenFuncSPlane(ps);
00617 pTexGen->setGenFuncTPlane(pt);
00618 pTexGen->setGenFuncRPlane(pr);
00619 pTexGen->setGenFuncQPlane(pq);
00620
00621 TextureObjChunkUnrecPtr pTexChunk = pEngineData->getTexChunk();
00622
00623 if(pTexChunk == NULL)
00624 {
00625 pTexChunk = TextureObjChunk::createLocal();
00626
00627 pEngineData->setTexChunk(pTexChunk);
00628
00629 ImageUnrecPtr pImage = Image::createLocal();
00630
00631
00632
00633 pImage->set(Image::OSG_L_PF,
00634 pTarget->getWidth (),
00635 pTarget->getHeight(),
00636 1,
00637 1,
00638 1,
00639 0,
00640 NULL,
00641 Image::OSG_UINT8_IMAGEDATA,
00642 false);
00643
00644
00645 pTexChunk->setImage (pImage);
00646 pTexChunk->setInternalFormat(GL_DEPTH_COMPONENT32);
00647 pTexChunk->setExternalFormat(GL_DEPTH_COMPONENT);
00648 pTexChunk->setMinFilter (GL_LINEAR);
00649 pTexChunk->setMagFilter (GL_LINEAR);
00650 pTexChunk->setWrapS (GL_CLAMP_TO_BORDER);
00651 pTexChunk->setWrapT (GL_CLAMP_TO_BORDER);
00652
00653 pTexChunk->setTarget (GL_TEXTURE_2D);
00654
00655 pTexChunk->setCompareMode(GL_COMPARE_R_TO_TEXTURE);
00656 pTexChunk->setCompareFunc(GL_LEQUAL);
00657 pTexChunk->setDepthMode (GL_INTENSITY);
00658 }
00659
00660 pAction->pushState();
00661
00662 UInt32 uiBlendSlot = pBlender ->getClassId();
00663 UInt32 uiTexSlot = pTexChunk->getClassId();
00664 UInt32 uiTexGenSlot = pTexGen ->getClassId();
00665
00666 if(this->getForceTextureUnit() != -1)
00667 {
00668 uiTexSlot += this->getForceTextureUnit();
00669 uiTexGenSlot += this->getForceTextureUnit();
00670 }
00671 else
00672 {
00673 uiTexSlot += 3;
00674 uiTexGenSlot += 3;
00675 }
00676
00677 pAction->addOverride(uiBlendSlot, pBlender );
00678 pAction->addOverride(uiTexSlot, pTexChunk);
00679 pAction->addOverride(uiTexGenSlot, pTexGen );
00680
00681 lightRenderEnter(pLight, pAction);
00682
00683 pAction->useNodeList(false);
00684
00685 this->recurseFrom(pAction, pLight);
00686
00687 pAction->popState();
00688
00689 pAction->popPartition ();
00690 }
00691
00692
00693 ActionBase::ResultE SimpleShadowMapEngine::runOnEnter(
00694 Light *pLight,
00695 LightTypeE eType,
00696 RenderAction *pAction)
00697 {
00698 EngineDataUnrecPtr pEngineData =
00699 pAction->getData<SimpleShadowMapEngineData *>(_iDataSlotId);
00700
00701 if(pEngineData == NULL)
00702 {
00703 pEngineData = EngineData::createLocal();
00704
00705 this->setData(pEngineData, _iDataSlotId, pAction);
00706 }
00707
00708 BitVector bvMask = pAction->getPassMask() & (bvLightPassMask |
00709 bvAmbientPassMask |
00710 bvDiffusePassMask );
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724 if(0x0000 != bvMask)
00725 {
00726 if(0x0000 != (bvMask & bvDiffusePassMask))
00727 {
00728 this->recurseFrom(pAction, pLight);
00729
00730 setupCamera (pLight, eType, pAction, pEngineData);
00731 doFinalPass (pLight, pAction, pEngineData);
00732 }
00733
00734 if(0x0000 != (bvMask & bvAmbientPassMask))
00735 {
00736 this->recurseFrom(pAction, pLight);
00737
00738 setupLightChunk(pLight, eType, pAction, pEngineData);
00739 }
00740
00741 if(0x0000 != (bvMask & bvLightPassMask))
00742 {
00743 this->recurseFrom(pAction, pLight);
00744
00745 doLightPass (pLight, pAction, pEngineData);
00746 }
00747 }
00748 else
00749 {
00750 setupCamera (pLight, eType, pAction, pEngineData);
00751
00752 setupLightChunk(pLight, eType, pAction, pEngineData);
00753
00754 pAction->addPassMask(bvDiffusePassMask);
00755 doFinalPass (pLight, pAction, pEngineData);
00756 pAction->subPassMask(bvDiffusePassMask);
00757
00758 pAction->addPassMask(bvAmbientPassMask);
00759 doAmbientPass (pLight, pAction, pEngineData);
00760 pAction->subPassMask(bvAmbientPassMask);
00761
00762 pAction->addPassMask(bvLightPassMask);
00763 doLightPass (pLight, pAction, pEngineData);
00764 pAction->subPassMask(bvLightPassMask);
00765 }
00766
00767 return ActionBase::Skip;
00768 }
00769
00770 ActionBase::ResultE SimpleShadowMapEngine::runOnLeave(
00771 Light *pLight,
00772 LightTypeE eType,
00773 RenderAction *pAction)
00774 {
00775 return ActionBase::Continue;
00776 }
00777