OSGPCSSShadowMapHandler.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *               Copyright (C) 2000-2002 by the OpenSG Forum                 *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041
00042 #include "OSGPCSSShadowMapHandler.h"
00043 #include "OSGRenderAction.h"
00044 #include "OSGShadowStage.h"
00045 #include "OSGShadowStageData.h"
00046 #include "OSGSpotLight.h"
00047 #include "OSGDirectionalLight.h"
00048
00049 OSG_BEGIN_NAMESPACE
00050
00051 #include "ShaderCode/OSGPCSSShadowMapShaderCode.cinl"
00052
00053 PCSSShadowMapHandler::PCSSShadowMapHandler(ShadowStage     *pSource,
00054                                            ShadowStageData *pData  ) :
00055      Inherited     (pSource,
00056                     pData  ),
00057     _pClearSMapBack(NULL   ),
00058     _pPoly         (NULL   ),
00059     _shadowSHL     (NULL   ),
00060     _firstRun      (1      )
00061 {
00062     _uiMode = ShadowStage::PCSS_SHADOW_MAP;
00063
00064
00065     //SHL Chunk 1
00066
00067     _shadowSHL = SimpleSHLChunk::createLocal();
00068     _shadowSHL->setVertexProgram  (_pcss_shadow_vp);
00069     _shadowSHL->setFragmentProgram(_pcss_shadow_fp);
00070
00071
00072     _pPoly = PolygonChunk::createLocal();
00073
00074     _unlitMat->addChunk(_pPoly);
00075
00076     _pClearSMapBack = SolidBackground::createLocal();
00077
00078     _pClearSMapBack->setColor(Color3f(1.f, 1.f, 1.f));
00079 }
00080
00081 PCSSShadowMapHandler::~PCSSShadowMapHandler(void)
00082 {
00083     _pClearSMapBack  = NULL;
00084     _pPoly           = NULL;
00085     _shadowSHL       = NULL;
00086
00087     _vShadowCmat  .clear();
00088     _vShadowSHLVar.clear();
00089
00090 }
00091
00092
00093 void PCSSShadowMapHandler::createShadowMapsFBO(RenderAction *a,
00094                                                DrawEnv      *pEnv)
00095 {
00096     // disable all lights more speed
00097     std::vector<bool> vLocalLightStates;
00098
00099     const ShadowStageData::LightStore  &vLights      =
00100         _pStageData->getLights();
00101
00102     const ShadowStageData::LStateStore &vLightStates =
00103         _pStageData->getLightStates();
00104
00105     const ShadowStageData::CamStore    &vLCams       =
00106         _pStageData->getLightCameras();
00107
00108     const ShadowStageData::StatusStore &vExclActive  =
00109         _pStageData->getExcludeNodeActive();
00110
00111     for(UInt32 i = 0;i < vLights.size();++i)
00112     {
00113         // store old states.
00114         vLocalLightStates.push_back(vLights[i].second->getOn());
00115
00116         vLights[i].second->setOn(false);
00117     }
00118
00119     // deactivate exclude nodes:
00120     for(UInt32 i = 0;i < _pStage->getMFExcludeNodes()->size();++i)
00121     {
00122         Node *exnode = _pStage->getExcludeNodes(i);
00123
00124         if(exnode != NULL)
00125             exnode->setTravMask(0);
00126     }
00127
00128     ShadowStageData::ShadowMapStore &vShadowMaps = _pStageData->getShadowMaps();
00129
00130     for(UInt32 i = 0;i < vLights.size();++i)
00131     {
00132         if(vLightStates[i] != 0)
00133         {
00134             if(_pStage->getGlobalShadowIntensity() != 0.0 ||
00135                vLights[i].second->getShadowIntensity() != 0.0)
00136             {
00137                 a->pushPartition();
00138                 {
00139                     RenderPartition   *pPart    = a->getActivePartition();
00140
00141                     pPart->addPreRenderCallback(
00142                         &ShadowTreeHandler::setupAmbientModelAndMasks);
00143                     pPart->addPostRenderCallback(
00144                         &ShadowTreeHandler::endAmbientModelAndMasks);
00145
00146                     pPart->setRenderTarget(vShadowMaps[i].pFBO);
00147
00148                     pPart->setWindow  (a->getWindow());
00149
00150                     pPart->calcViewportDimension(0.f,
00151                                                  0.f,
00152                                                  _pStage->getMapSize()-1,
00153                                                  _pStage->getMapSize()-1,
00154
00155                                                  _pStage->getMapSize(),
00156                                                  _pStage->getMapSize() );
00157
00158
00159                     Matrix m, t;
00160
00161                     // set the projection
00162                     vLCams[i]->getProjection(
00163                         m,
00164                         pPart->getViewportWidth (),
00165                         pPart->getViewportHeight());
00166
00167                     vLCams[i]->getProjectionTranslation(
00168                         t,
00169                         pPart->getViewportWidth (),
00170                         pPart->getViewportHeight());
00171
00172                     pPart->setupProjection(m, t);
00173
00174                     vLCams[i]->getViewing(
00175                         m,
00176                         pPart->getViewportWidth (),
00177                         pPart->getViewportHeight());
00178
00179
00180                     pPart->setupViewing(m);
00181
00182                     pPart->setNear     (vLCams[i]->getNear());
00183                     pPart->setFar      (vLCams[i]->getFar ());
00184
00185                     pPart->calcFrustum();
00186
00187                     pPart->setBackground(_pClearSMapBack);
00188
00189                     Node *light  = vLights[i].first;
00190                     Node *parent = light->getParent();
00191
00192                     if(parent != NULL)
00193                     {
00194                         a->pushMatrix(parent->getToWorld());
00195                     }
00196
00197
00198                     a->overrideMaterial(_unlitMat, a->getActNode());
00199                     _pStage->recurse(a, light);
00200                     a->overrideMaterial( NULL,       a->getActNode());
00201
00202                     if(parent != NULL)
00203                     {
00204                         a->popMatrix();
00205                     }
00206                 }
00207                 a->popPartition();
00208             }
00209         }
00210     }
00211
00212     //-------Restoring old states of Window and Viewport----------
00213     // enable all lights.
00214     for(UInt32 i = 0;i < vLights.size();++i)
00215     {
00216         // restore old states.
00217         vLights[i].second->setOn(vLocalLightStates[i]);
00218     }
00219
00220     // activate exclude nodes:
00221     for(UInt32 i = 0;i < _pStage->getMFExcludeNodes()->size();++i)
00222     {
00223         Node *exnode = _pStage->getExcludeNodes(i);
00224         if(exnode != NULL)
00225         {
00226             if(vExclActive[i])
00227             {
00228                 exnode->setTravMask(TypeTraits<UInt32>::BitsSet);
00229             }
00230         }
00231     }
00232 }
00233
00234
00235 void PCSSShadowMapHandler::createColorMapFBO(RenderAction *a,
00236                                              DrawEnv      *pEnv)
00237 {
00238     a->pushPartition((RenderPartition::CopyWindow      |
00239                       RenderPartition::CopyViewing     |
00240                       RenderPartition::CopyProjection  |
00241                       RenderPartition::CopyFrustum     |
00242                       RenderPartition::CopyNearFar     |
00243                       RenderPartition::CopyViewportSize),
00244                      RenderPartition::StateSorting);
00245     {
00246         RenderPartition *pPart = a->getActivePartition();
00247
00248         pPart->addPreRenderCallback (&ShadowTreeHandler::setupAmbientModel);
00249         pPart->addPostRenderCallback(&ShadowTreeHandler::endAmbientModel  );
00250
00251         pPart->setRenderTarget(_pSceneFBO);
00252         pPart->setDrawBuffer  (GL_COLOR_ATTACHMENT0_EXT);
00253
00254         Node *parent = a->getActNode()->getParent();
00255
00256         if(parent != NULL)
00257         {
00258             a->pushMatrix(parent->getToWorld());
00259         }
00260
00261         pPart->setBackground(a->getBackground());
00262
00263         _pStage->recurseFromThis(a);
00264
00265         if(parent != NULL)
00266         {
00267             a->popMatrix();
00268         }
00269     }
00270     a->popPartition();
00271
00272
00273 }
00274
00275 void PCSSShadowMapHandler::createShadowFactorMapFBO(
00276     RenderAction *a,
00277     DrawEnv      *pEnv,
00278     UInt32        num,
00279     UInt32        uiActiveLightCount)
00280 {
00281     //Finde alle aktiven Lichtquellen
00282
00283     Real32  activeLights = 0;
00284
00285     const ShadowStageData::LightStore  &vLights      =
00286         _pStageData->getLights();
00287
00288     const ShadowStageData::LStateStore &vLightStates =
00289         _pStageData->getLightStates();
00290
00291     const ShadowStageData::CamStore    &vLCams       =
00292         _pStageData->getLightCameras();
00293
00294
00295     if(_pStage->getGlobalShadowIntensity() != 0.0)
00296     {
00297         for(UInt32 i = 0;i < vLights.size();i++)
00298         {
00299             if(vLightStates[i] != 0)
00300                 activeLights++;
00301         }
00302     }
00303     else
00304     {
00305         for(UInt32 i = 0;i < vLights.size();i++)
00306         {
00307             if(vLightStates[i]                         != 0 &&
00308                vLights[i].second->getShadowIntensity() != 0.0)
00309             {
00310                 activeLights++;
00311             }
00312         }
00313     }
00314
00315     Real32  shadowIntensity;
00316
00317     if(_pStage->getGlobalShadowIntensity() != 0.0)
00318     {
00319         shadowIntensity = (_pStage->getGlobalShadowIntensity() /
00320                            activeLights);
00321     }
00322     else
00323     {
00324         shadowIntensity =
00325             (vLights[num].second->getShadowIntensity() /
00326              activeLights);
00327     }
00328
00329     if(vLights[num].second->getShadowIntensity() != 0.0 ||
00330        _pStage->getGlobalShadowIntensity()     != 0.0)
00331     {
00332
00333         Matrix  LVM, LPM, CVM;
00334
00335         vLCams[num]->getViewing(
00336             LVM,
00337             pEnv->getPixelWidth(),
00338             pEnv->getPixelHeight());
00339
00340         vLCams[num]->getProjection(
00341             LPM,
00342             pEnv->getPixelWidth(),
00343             pEnv->getPixelHeight());
00344
00345         CVM = pEnv->getCameraViewing();
00346
00347         Matrix  iCVM = CVM;
00348         iCVM.invert();
00349
00350         Real32  texFactor;
00351
00352         if(vLights[num].second->getType() == SpotLight::getClassType () ||
00353            vLights[num].second->getType() == PointLight::getClassType()  )
00354         {
00355             texFactor = Real32(_width) / Real32(_height);
00356         }
00357         else
00358         {
00359             texFactor = 1.0;
00360         }
00361
00362         Matrix  shadowMatrix = LPM;
00363         shadowMatrix.mult(LVM);
00364         shadowMatrix.mult(iCVM);
00365
00366         Real32  xFactor = 1.0;
00367         Real32  yFactor = 1.0;
00368
00369         Real32  lightSize;
00370
00371         if(vLights[num].second->getType() != DirectionalLight::getClassType())
00372         {
00373             lightSize = _pStage->getShadowSmoothness() * 10.0;
00374         }
00375         else
00376         {
00377             lightSize = _pStage->getShadowSmoothness() / 25.0;
00378         }
00379
00380         if(_vShadowCmat.size() == uiActiveLightCount)
00381         {
00382             _vShadowCmat.push_back(ChunkMaterial::createLocal());
00383         }
00384
00385         OSG_ASSERT( uiActiveLightCount < _vShadowCmat.size());
00386
00387         if(_vShadowSHLVar.size() == uiActiveLightCount)
00388         {
00389             _vShadowSHLVar.push_back(SimpleSHLVariableChunk::createLocal());
00390
00391 #ifndef OSG_NEW_SHADER
00392             _vShadowSHLVar[uiActiveLightCount]->setSHLChunk(_shadowSHL);
00393 #endif
00394         }
00395
00396         _shadowSHL->addUniformVariable("shadowMap",    0);
00397         _shadowSHL->addUniformVariable("oldFactorMap", 1);
00398
00399         _vShadowSHLVar[uiActiveLightCount]->addUniformVariable(
00400             "firstRun", (uiActiveLightCount == 0) ? Int32(1) : Int32(0));
00401
00402         _vShadowSHLVar[uiActiveLightCount]->addUniformVariable(
00403             "intensity", shadowIntensity);
00404
00405         _vShadowSHLVar[uiActiveLightCount]->addUniformVariable(
00406             "texFactor", texFactor);
00407
00408         _vShadowSHLVar[uiActiveLightCount]->addUniformVariable(
00409             "lightPM", shadowMatrix);
00410
00411         _vShadowSHLVar[uiActiveLightCount]->addUniformVariable(
00412             "mapSize",
00413             Real32(_pStage->getMapSize()));
00414
00415         _vShadowSHLVar[uiActiveLightCount]->addUniformVariable(
00416             "lightSize", Real32(lightSize));
00417
00418         _vShadowSHLVar[uiActiveLightCount]->addUniformVariable(
00419             "xFactor", Real32(xFactor));
00420
00421         _vShadowSHLVar[uiActiveLightCount]->addUniformVariable(
00422             "yFactor", Real32(yFactor));
00423
00424
00425         ShadowStageData::ShadowMapStore &vShadowMaps =
00426             _pStageData->getShadowMaps();
00427
00428
00429         _vShadowCmat[uiActiveLightCount]->clearChunks();
00430
00431         _vShadowCmat[uiActiveLightCount]->addChunk(
00432             _shadowSHL);
00433
00434         _vShadowCmat[uiActiveLightCount]->addChunk(
00435             _vShadowSHLVar[uiActiveLightCount]);
00436
00437         _vShadowCmat[uiActiveLightCount]->addChunk(
00438             vShadowMaps[num].pTexO);
00439
00440         _vShadowCmat[uiActiveLightCount]->addChunk(
00441             vShadowMaps[num].pTexE);
00442
00443         _vShadowCmat[uiActiveLightCount]->addChunk(
00444             _shadowFactorMapO);
00445
00446         a->pushPartition((RenderPartition::CopyWindow      |
00447                           RenderPartition::CopyViewing     |
00448                           RenderPartition::CopyProjection  |
00449                           RenderPartition::CopyFrustum     |
00450                           RenderPartition::CopyNearFar     |
00451                           RenderPartition::CopyViewportSize),
00452                          RenderPartition::StateSorting);
00453         {
00454             RenderPartition *pPart = a->getActivePartition();
00455
00456             pPart->addPreRenderCallback (&ShadowTreeHandler::setupAmbientModel);
00457             pPart->addPostRenderCallback(&ShadowTreeHandler::endAmbientModel  );
00458
00459             pPart->setRenderTarget(_pSceneFBO);
00460             pPart->setDrawBuffer  (GL_COLOR_ATTACHMENT1_EXT);
00461
00462             Node *light  = vLights[num].first;
00463             Node *parent = light->getParent();
00464
00465             if(parent != NULL)
00466             {
00467                 a->pushMatrix(parent->getToWorld());
00468             }
00469
00470             if(uiActiveLightCount == 0)
00471             {
00472                 pPart->setBackground(_pClearBackground);
00473             }
00474
00475             commitChanges();
00476
00477             a->overrideMaterial(_vShadowCmat[uiActiveLightCount],
00478                                  a->getActNode());
00479             _pStage->recurse(a, light);
00480             a->overrideMaterial( NULL,
00481                                  a->getActNode());
00482
00483             if(parent != NULL)
00484             {
00485                 a->popMatrix();
00486             }
00487         }
00488         a->popPartition();
00489
00490         _firstRun = 0;
00491     }
00492 }
00493
00494 void PCSSShadowMapHandler::configureShadowMaps(void)
00495 {
00496     ShadowStageData::ShadowMapStore &vShadowMaps = _pStageData->getShadowMaps();
00497
00498     const ShadowStageData::LightStore  &vLights  = _pStageData->getLights();
00499
00500
00501     UInt32 uiSHMSize = vShadowMaps.size();
00502     UInt32 uiMapSize = _pStage-> getMapSize ();
00503
00504     for(UInt32 i = 0; i < uiSHMSize; ++i)
00505     {
00506         vShadowMaps[i].pTexO->setCompareMode(GL_NONE     );
00507         vShadowMaps[i].pTexO->setCompareFunc(GL_LEQUAL   );
00508         vShadowMaps[i].pTexO->setDepthMode  (GL_LUMINANCE);
00509
00510         vShadowMaps[i].pTexO->setMinFilter  (GL_NEAREST  );
00511         vShadowMaps[i].pTexO->setMagFilter  (GL_NEAREST  );
00512
00513         if(vShadowMaps[i].uiType ==
00514                                 ShadowStageData::ShadowMapElem::ColorShadowMap)
00515         {
00516             vShadowMaps[i].pTexO->setInternalFormat(GL_DEPTH_COMPONENT);
00517             vShadowMaps[i].pTexO->setExternalFormat(GL_DEPTH_COMPONENT);
00518
00519             if(vLights[i].second->getType() != PointLight::getClassType())
00520             {
00521                 vShadowMaps[i].pTexO->setWrapS(GL_CLAMP_TO_EDGE);
00522                 vShadowMaps[i].pTexO->setWrapT(GL_CLAMP_TO_EDGE);
00523             }
00524             else
00525             {
00526                 vShadowMaps[i].pTexO->setWrapS(GL_CLAMP_TO_BORDER);
00527                 vShadowMaps[i].pTexO->setWrapT(GL_CLAMP_TO_BORDER);
00528             }
00529
00530             vShadowMaps[i].pTexO->setAnisotropy(1.0);
00531
00532             vShadowMaps[i].pImage->set(Image::OSG_L_PF,
00533                                        uiMapSize, uiMapSize, 1,
00534                                        1, 1, 0.f,
00535                                        NULL,
00536                                        Image::OSG_UINT8_IMAGEDATA,
00537                                        false);
00538
00539             vShadowMaps[i].pFBO->setDepthAttachment(
00540                 vShadowMaps[i].pFBO->getColorAttachments(0));
00541
00542             vShadowMaps[i].pFBO->setColorAttachment(NULL, 0);
00543
00544             vShadowMaps[i].uiType =
00545                                 ShadowStageData::ShadowMapElem::DepthShadowMap;
00546         }
00547     }
00548
00549     _bShadowMapsConfigured = true;
00550 }
00551
00552 void PCSSShadowMapHandler::render(RenderAction *a,
00553                                   DrawEnv      *pEnv)
00554 {
00555     const ShadowStageData::LightStore  &vLights      =
00556         _pStageData->getLights();
00557
00558     const ShadowStageData::NodeStore   &vTransparents =
00559         _pStageData->getTransparents();
00560
00561     const ShadowStageData::LStateStore &vLightStates =
00562         _pStageData->getLightStates();
00563
00564 #ifndef SHADOW_CHECK
00565     if(_bShadowMapsConfigured == false)
00566         _pStageData->getShadowMaps().clear();
00567 #endif
00568 
00569     if(_pStageData->getShadowMaps().size() != vLights.size())
00570     {
00571         initShadowMaps();
00572     }
00573
00574     if(_bShadowMapsConfigured == false)
00575     {
00576         configureShadowMaps();
00577     }
00578
00579     if(_uiMapSize != _pStage->getMapSize())
00580     {
00581         updateShadowMapSize();
00582     }
00583
00584     if(_pSceneFBO == NULL)
00585         initSceneFBO(pEnv, false);
00586
00587     if(_width  != pEnv->getPixelWidth () ||
00588        _height != pEnv->getPixelHeight()  )
00589     {
00590         updateSceneFBOSize(pEnv, false);
00591     }
00592
00593     commitChanges();
00594
00595     _firstRun = 1;
00596
00597     if(_pStage->getMapAutoUpdate() == true ||
00598        _pStage->_trigger_update    == true  )
00599     {
00600         _pPoly->setOffsetFill  (true                   );
00601         _pPoly->setOffsetFactor(_pStage->getOffFactor());
00602         _pPoly->setOffsetBias  (_pStage->getOffBias  ());
00603
00604         createColorMapFBO(a, pEnv);
00605
00606
00607         //deactivate transparent Nodes
00608         for(UInt32 t = 0;t < vTransparents.size();++t)
00609         {
00610             vTransparents[t]->setTravMask(0);
00611         }
00612
00613
00614         createShadowMapsFBO(a, pEnv);
00615
00616
00617         // switch on all transparent geos
00618         for(UInt32 t = 0;t < vTransparents.size();++t)
00619         {
00620             vTransparents[t]->setTravMask(TypeTraits<UInt32>::BitsSet);
00621         }
00622
00623
00624         UInt32 uiActiveLightCount = 0;
00625
00626         for(UInt32 i = 0;i < vLights.size();i++)
00627         {
00628             if(vLightStates[i] != 0)
00629             {
00630                 if(_pStage->getGlobalShadowIntensity()   != 0.0 ||
00631                    vLights[i].second->getShadowIntensity() != 0.0)
00632                 {
00633                     createShadowFactorMapFBO(a,
00634                                              pEnv,
00635                                              i,
00636                                              uiActiveLightCount);
00637
00638                     ++uiActiveLightCount;
00639                 }
00640             }
00641         }
00642
00643         _pStage->_trigger_update = false;
00644     }
00645
00646     setupDrawCombineMap1(a);
00647 }
00648
00649 OSG_END_NAMESPACE