24#include <boost/lexical_cast.hpp>
37 shadowStandardTexture.reset();
38 shadowCubicTexture.reset();
41 shadowStandardMaterial.reset();
42 shadowCubicMaterial.reset();
45 PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE = Ogre::Matrix4(0.5, 0, 0, 0.5,
51 standardTextureSize = 1024;
52 standardTexturePixelFormat = Ogre::PF_FLOAT16_R;
53 standardTextureFsaa = 0;
54 standardTextureNeedRebuild =
true;
55 cubicTextureSize = 512;
56 cubicTexturePixelFormat = Ogre::PF_FLOAT16_R;
58 cubicTextureNeedRebuild =
true;
61 deferredShadowStandardTextureName = std::string(SO3_DEFERRED_SHADOWS_SCHEME_NAME) + std::string(SO3_DEFERRED_SHADOWS_STANDARD_BASE_NAME) + std::string(SO3_DEFERRED_SHADOWS_TEXTURE_NAME);
62 deferredShadowStandardCameraName = std::string(SO3_DEFERRED_SHADOWS_SCHEME_NAME) + std::string(SO3_DEFERRED_SHADOWS_STANDARD_BASE_NAME) + std::string(SO3_DEFERRED_SHADOWS_CAMERA_NAME);
63 deferredShadowStandardMaterialName = std::string(SO3_DEFERRED_SHADOWS_SCHEME_NAME) + std::string(SO3_DEFERRED_SHADOWS_STANDARD_BASE_NAME) + std::string(SO3_DEFERRED_SHADOWS_MATERIAL_NAME);
64 deferredShadowCubicTextureName = std::string(SO3_DEFERRED_SHADOWS_SCHEME_NAME) + std::string(SO3_DEFERRED_SHADOWS_CUBIC_BASE_NAME) + std::string(SO3_DEFERRED_SHADOWS_TEXTURE_NAME);
65 deferredShadowCubicCameraName = std::string(SO3_DEFERRED_SHADOWS_SCHEME_NAME) + std::string(SO3_DEFERRED_SHADOWS_CUBIC_BASE_NAME) + std::string(SO3_DEFERRED_SHADOWS_CAMERA_NAME);
66 deferredShadowCubicMaterialName = std::string(SO3_DEFERRED_SHADOWS_SCHEME_NAME) + std::string(SO3_DEFERRED_SHADOWS_CUBIC_BASE_NAME) + std::string(SO3_DEFERRED_SHADOWS_MATERIAL_NAME);
69 spotShadowCameraSetup =
new Ogre::DefaultShadowCameraSetup();
70 pointShadowCameraSetup =
new Ogre::DefaultShadowCameraSetup();
71 directionalShadowCameraSetup =
new Ogre::DefaultShadowCameraSetup();
78 Ogre::MaterialManager::getSingleton().addListener(
this, SO3_DEFERRED_SHADOWS_SCHEME_NAME);
83 Ogre::MaterialManager::getSingleton().removeListener(
this, SO3_DEFERRED_SHADOWS_SCHEME_NAME);
84 DestroyShadowStandardTexture();
85 DestroyShadowCubicTexture();
88 SO3_SAFE_DELETE(spotShadowCameraSetup);
89 SO3_SAFE_DELETE(pointShadowCameraSetup);
90 SO3_SAFE_DELETE(directionalShadowCameraSetup);
101 return (*msSingleton);
106 OgreSceneManagerList::iterator ogreSceneManagerSearched = ogreSceneManagerList.find(targetScene);
107 if (ogreSceneManagerSearched != ogreSceneManagerList.end())
108 SO3_EXCEPT(
SExceptionItemIdentity,
"Trying to register an already registered scene manager!",
"SDeferredShadowManager::RegisterSceneManager",
true);
113 targetScene->setShadowTechnique(Ogre::SHADOWTYPE_NONE);
116 Ogre::Camera* ogreStandardShadowCamera = targetScene->createCamera(deferredShadowStandardCameraName);
117 ogreStandardShadowCamera->setAspectRatio(1);
118 standardTextureCameraByScene.insert(StandardTextureCameraByScene::value_type(targetScene, ogreStandardShadowCamera));
121 std::vector<Ogre::Camera*> ogreCubicCameras;
122 for(
int cpt = 0; cpt < 6; cpt++)
124 Ogre::Camera* ogreCubicShadowCamera = targetScene->createCamera(deferredShadowCubicCameraName + boost::lexical_cast<std::string, int>(cpt));
126 ogreCubicCameras.push_back(ogreCubicShadowCamera);
128 cubicTextureCamerasByScene.insert(CubicTextureCamerasByScene::value_type(targetScene, ogreCubicCameras));
131 ogreSceneManagerList.insert(targetScene);
137 OgreSceneManagerList::iterator ogreSceneManagerSearched = ogreSceneManagerList.find(existingScene);
138 if (ogreSceneManagerSearched == ogreSceneManagerList.end())
139 SO3_EXCEPT(
SExceptionItemNotFound,
"Trying to unregister a scene manager that is not registered!",
"SDeferredShadowManager::UnregisterSceneManager",
true);
143 StandardTextureCameraByScene::iterator iCamera = standardTextureCameraByScene.find(existingScene);
144 Ogre::Camera* ogreStandardShadowCamera = iCamera->second;
145 standardTextureCameraByScene.erase(iCamera);
146 existingScene->destroyCamera(ogreStandardShadowCamera);
149 CubicTextureCamerasByScene::iterator iCameras = cubicTextureCamerasByScene.find(existingScene);
150 for(
int cpt = 0; cpt < 6; cpt++)
152 Ogre::Camera* ogreCubicShadowCamera = iCameras->second.at(cpt);
153 existingScene->destroyCamera(ogreCubicShadowCamera);
155 iCameras->second.clear();
156 cubicTextureCamerasByScene.erase(iCameras);
160 ogreSceneManagerList.erase(ogreSceneManagerSearched);
184 if(standardTextureSize != size)
185 standardTextureNeedRebuild =
true;
187 standardTextureSize = size;
192 if(standardTexturePixelFormat != fmt)
193 standardTextureNeedRebuild =
true;
195 standardTexturePixelFormat = fmt;
200 if(standardTextureFsaa != fsaa)
201 standardTextureNeedRebuild =
true;
203 standardTextureFsaa = fsaa;
208 if(cubicTextureSize != size)
209 cubicTextureNeedRebuild =
true;
211 cubicTextureSize = size;
216 if(cubicTexturePixelFormat != fmt)
217 cubicTextureNeedRebuild =
true;
219 cubicTexturePixelFormat = fmt;
224 if(cubicTextureFsaa != fsaa)
225 cubicTextureNeedRebuild =
true;
227 cubicTextureFsaa = fsaa;
230void SDeferredShadowManager::CreateShadowStandardTexture()
233 DestroyShadowStandardTexture();
236 shadowStandardTexture = Ogre::TextureManager::getSingleton().createManual(deferredShadowStandardTextureName,
237 Ogre::ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME,
242 standardTexturePixelFormat,
243 Ogre::TU_RENDERTARGET,
246 standardTextureFsaa);
248 shadowStandardTexture->load();
251 shadowStandardMaterial = Ogre::MaterialManager::getSingleton().create(deferredShadowStandardMaterialName, Ogre::ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
254 Ogre::Pass* ogreShadowPass = shadowStandardMaterial->getTechnique(0)->getPass(0);
255 ogreShadowPass->removeAllTextureUnitStates();
256 Ogre::TextureUnitState* texUnit = ogreShadowPass->createTextureUnitState(deferredShadowStandardTextureName);
257 texUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_BORDER);
258 texUnit->setTextureBorderColour(Ogre::ColourValue::White);
259 shadowStandardMaterial->touch();
262 standardTextureNeedRebuild =
false;
265void SDeferredShadowManager::CreateShadowCubicTexture()
268 DestroyShadowCubicTexture();
271 shadowCubicTexture = Ogre::TextureManager::getSingleton().createManual(deferredShadowCubicTextureName,
272 Ogre::ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME,
273 Ogre::TEX_TYPE_CUBE_MAP,
277 cubicTexturePixelFormat,
278 Ogre::TU_RENDERTARGET,
283 shadowCubicTexture->load();
286 shadowCubicMaterial = Ogre::MaterialManager::getSingleton().create(deferredShadowCubicMaterialName, Ogre::ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
289 Ogre::Pass* ogreShadowPass = shadowCubicMaterial->getTechnique(0)->getPass(0);
290 ogreShadowPass->removeAllTextureUnitStates();
291 Ogre::TextureUnitState* texUnit = ogreShadowPass->createTextureUnitState(deferredShadowCubicTextureName);
293 texUnit->setCubicTextureName(shadowCubicTexture->getName(),
true);
294 texUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_BORDER);
295 texUnit->setTextureBorderColour(Ogre::ColourValue::White);
296 shadowCubicMaterial->touch();
299 cubicTextureNeedRebuild =
false;
302void SDeferredShadowManager::DestroyShadowStandardTexture()
305 if(shadowStandardTexture)
308 Ogre::RenderTarget* ogreShadowRenderTarget = shadowStandardTexture->getBuffer()->getRenderTarget();
309 Ogre::Viewport* ogreShadowViewport = ogreShadowRenderTarget->getViewport(0);
310 if(ogreShadowViewport->getCamera() != 0)
311 ogreShadowViewport->setCamera(0);
312 ogreShadowRenderTarget->removeViewport(0);
316 Ogre::MaterialManager::getSingleton().remove(shadowStandardMaterial->getHandle());
317 shadowStandardMaterial.reset();
320 Ogre::TextureManager::getSingleton().remove(shadowStandardTexture->getHandle());
321 shadowStandardTexture.reset();
322 standardTextureNeedRebuild =
true;
326void SDeferredShadowManager::DestroyShadowCubicTexture()
329 if(shadowCubicTexture)
332 for(
int cpt = 0; cpt < 6; cpt++)
334 Ogre::RenderTarget* ogreShadowRenderTarget = shadowCubicTexture->getBuffer(cpt)->getRenderTarget();
335 Ogre::Viewport* ogreShadowViewport = ogreShadowRenderTarget->getViewport(0);
336 if(ogreShadowViewport->getCamera() != 0)
337 ogreShadowViewport->setCamera(0);
338 ogreShadowRenderTarget->removeViewport(0);
343 Ogre::MaterialManager::getSingleton().remove(shadowCubicMaterial->getHandle());
344 shadowCubicMaterial.reset();
347 Ogre::TextureManager::getSingleton().remove(shadowCubicTexture->getHandle());
348 shadowCubicTexture.reset();
349 cubicTextureNeedRebuild =
true;
356 Ogre::SceneManager* ogreTargetScene = ogreCamera->getSceneManager();
357 OgreSceneManagerList::iterator ogreSceneManagerSearched = ogreSceneManagerList.find(ogreTargetScene);
358 if (ogreSceneManagerSearched == ogreSceneManagerList.end())
359 SO3_EXCEPT(
SExceptionItemNotFound,
"Can not prepare shadow texture for the scenemanager \""+ ogreTargetScene->getName() +
"\", as it seems that it does not use deferred rendering!",
"SDeferredShadowManager::PrepareShadowTexture",
true);
362 Ogre::SceneManager::RenderContext* context = ogreTargetScene->_pauseRendering();
365 if(light->getType() == Ogre::Light::LT_POINT)
366 PrepareShadowCubicTextureImpl(ogreTargetScene, ogreCamera, ogreViewport, light);
368 PrepareShadowTextureImpl(ogreTargetScene, ogreCamera, ogreViewport, light);
371 ogreTargetScene->_resumeRendering(context);
376 Ogre::Camera* ogreShadowCamera = 0;
377 if(light->getType() == Ogre::Light::LT_POINT)
378 ogreShadowCamera = cubicTextureCamerasByScene.find(ogreTargetScene)->second.front();
380 ogreShadowCamera = standardTextureCameraByScene.find(ogreTargetScene)->second;
382 assert(ogreShadowCamera != 0);
383 Ogre::GpuProgramParametersSharedPtr params = ogrePass->getFragmentProgramParameters();
384 Ogre::Matrix4 textureProjectionMatrix = PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE * ogreShadowCamera->getProjectionMatrixWithRSDepth() * ogreShadowCamera->getViewMatrix();
385 if (params->_findNamedConstantDefinition(
"shadowViewProjMat"))
386 params->setNamedConstant(
"shadowViewProjMat", textureProjectionMatrix);
389 if(light->getType() == Ogre::Light::LT_POINT)
390 return shadowCubicTexture;
392 return shadowStandardTexture;
395void SDeferredShadowManager::PrepareShadowTextureImpl(Ogre::SceneManager* ogreTargetScene, Ogre::Camera* ogreCamera, Ogre::Viewport* ogreViewport,
const Ogre::Light* ogreLight)
398 if(standardTextureNeedRebuild)
399 CreateShadowStandardTexture();
402 StandardTextureCameraByScene::iterator iCamera = standardTextureCameraByScene.find(ogreTargetScene);
403 Ogre::Camera* ogreShadowCamera = iCamera->second;
406 Ogre::RenderTarget* ogreShadowRTT = shadowStandardTexture->getBuffer()->getRenderTarget();
407 Ogre::Viewport* ogreShadowViewport = 0;
408 if(ogreShadowRTT->getNumViewports() == 0)
410 ogreShadowViewport = ogreShadowRTT->addViewport(ogreShadowCamera);
411 ogreShadowViewport->setClearEveryFrame(
true);
412 ogreShadowViewport->setOverlaysEnabled(
false);
413 ogreShadowViewport->setMaterialScheme(SO3_DEFERRED_SHADOWS_SCHEME_NAME);
414 ogreShadowRTT->setAutoUpdated(
false);
417 ogreShadowViewport = ogreShadowRTT->getViewport(0);
420 assert(ogreShadowViewport != 0);
421 ogreShadowViewport->setCamera(ogreShadowCamera);
424 ogreShadowCamera->setLodCamera(ogreCamera);
425 ogreShadowCamera->setDirection(ogreLight->getDerivedDirection());
426 if (ogreLight->getType() == Ogre::Light::LT_SPOTLIGHT)
428 ogreShadowCamera->setPosition(ogreLight->getDerivedPosition());
429 spotShadowCameraSetup->getShadowCamera(ogreTargetScene, ogreCamera, ogreViewport, ogreLight, ogreShadowCamera, 0);
433 directionalShadowCameraSetup->getShadowCamera(ogreTargetScene, ogreCamera, ogreViewport, ogreLight, ogreShadowCamera, 0);
437 shadowStandardMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setProjectiveTexturing(
true, ogreShadowCamera);
440 ogreShadowViewport->setBackgroundColour(Ogre::ColourValue::White);
443 ogreShadowRTT->update();
446void SDeferredShadowManager::PrepareShadowCubicTextureImpl(Ogre::SceneManager* ogreTargetScene, Ogre::Camera* ogreCamera, Ogre::Viewport* ogreViewport,
const Ogre::Light* ogreLight)
449 if(cubicTextureNeedRebuild)
450 CreateShadowCubicTexture();
453 std::vector<Ogre::Camera*> ogreCubicCameras = cubicTextureCamerasByScene.find(ogreTargetScene)->second;
456 for(
int cpt = 0; cpt < 6; cpt++)
459 Ogre::Camera* ogreShadowCamera = ogreCubicCameras.at(cpt);
462 Ogre::RenderTarget* ogreShadowRTT = shadowCubicTexture->getBuffer(cpt)->getRenderTarget();
463 Ogre::Viewport* ogreShadowViewport = 0;
464 if(ogreShadowRTT->getNumViewports() == 0)
466 ogreShadowViewport = ogreShadowRTT->addViewport(ogreShadowCamera);
467 ogreShadowViewport->setClearEveryFrame(
true);
468 ogreShadowViewport->setOverlaysEnabled(
false);
469 ogreShadowViewport->setMaterialScheme(SO3_DEFERRED_SHADOWS_SCHEME_NAME);
470 ogreShadowRTT->setAutoUpdated(
false);
473 ogreShadowViewport = ogreShadowRTT->getViewport(0);
476 assert(ogreShadowViewport != 0);
477 ogreShadowViewport->setCamera(ogreShadowCamera);
480 pointShadowCameraSetup->getShadowCamera(ogreTargetScene, ogreCamera, ogreViewport, ogreLight, ogreShadowCamera, 0);
483 ogreShadowCamera->setProjectionType(Ogre::PT_PERSPECTIVE);
484 ogreShadowCamera->setAspectRatio(1);
485 ogreShadowCamera->setFOVy(Ogre::Degree(90));
488 ogreShadowCamera->setLodCamera(ogreCamera);
491 ogreShadowCamera->setPosition(ogreLight->getDerivedPosition());
494 ogreShadowCamera->setOrientation(Ogre::Quaternion::IDENTITY);
498 ogreShadowCamera->yaw(Ogre::Degree(-90));
501 ogreShadowCamera->yaw(Ogre::Degree(90));
504 ogreShadowCamera->pitch(Ogre::Degree(90));
507 ogreShadowCamera->pitch(Ogre::Degree(-90));
510 ogreShadowCamera->yaw(Ogre::Degree(180));
515 shadowCubicMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setProjectiveTexturing(
true, ogreShadowCamera);
518 ogreShadowViewport->setBackgroundColour(Ogre::ColourValue::White);
521 ogreShadowRTT->update();
527 Ogre::Material::TechniqueIterator schemeTechniqueIt = originalMaterial->getTechniqueIterator();
528 while(schemeTechniqueIt.hasMoreElements())
530 Ogre::Technique* schemeTechnique = schemeTechniqueIt.getNext();
531 if(schemeTechnique->getSchemeName() == schemeName)
532 return schemeTechnique;
535 Ogre::Technique* shadowTechnique = 0;
536 if(schemeName == SO3_DEFERRED_SHADOWS_SCHEME_NAME)
539 Ogre::MaterialManager& ogreMaterialManager = Ogre::MaterialManager::getSingleton();
540 ogreMaterialManager.setActiveScheme(Ogre::MaterialManager::DEFAULT_SCHEME_NAME);
541 Ogre::Technique* originalTechnique = originalMaterial->getBestTechnique(lodIndex, rend);
544 Ogre::MaterialPtr shadowCasterMaterial = Ogre::MaterialManager::getSingleton().getByName(SO3_DEFERRED_SHADOW_CASTER_NAME);
545 if (!shadowCasterMaterial)
546 SO3_EXCEPT(
SExceptionItemNotFound,
"Cannot locate the shadow caster material named \"" + std::string(SO3_DEFERRED_SHADOW_CASTER_NAME) +
"'",
"SDeferredShadowManager::handleSchemeNotFound",
true);
549 if(!shadowCasterMaterial->isLoaded())
550 shadowCasterMaterial->load();
553 Ogre::Technique* shadowCasterTechnique = shadowCasterMaterial->getBestTechnique();
556 ogreMaterialManager.setActiveScheme(SO3_DEFERRED_SHADOWS_SCHEME_NAME);
559 shadowTechnique = originalMaterial->createTechnique();
560 shadowTechnique->removeAllPasses();
561 shadowTechnique->setSchemeName(SO3_DEFERRED_SHADOWS_SCHEME_NAME);
564 for (
unsigned short i=0; i<originalTechnique->getNumPasses(); i++)
566 Ogre::Pass* originalPass = originalTechnique->getPass(i);
567 Ogre::Pass* shadowPass = shadowTechnique->createPass();
570 if((originalPass->getSourceBlendFactor() == Ogre::SBF_SOURCE_ALPHA)
571 &&(originalPass->getDestBlendFactor() == Ogre::SBF_ONE_MINUS_SOURCE_ALPHA)
572 ||(originalPass->getAlphaRejectFunction() != Ogre::CMPF_ALWAYS_PASS))
576 shadowPass->setAlphaRejectSettings(originalPass->getAlphaRejectFunction(), originalPass->getAlphaRejectValue());
577 shadowPass->setSceneBlending(originalPass->getSourceBlendFactor(), originalPass->getDestBlendFactor());
578 shadowPass->getParent()->getParent()->setTransparencyCastsShadows(
true);
582 unsigned short origPassTUCount = originalPass->getNumTextureUnitStates();
583 for (
unsigned short t = 0; t < origPassTUCount; ++t)
586 Ogre::TextureUnitState* shadowTextureUnit = originalPass->createTextureUnitState();
587 (*shadowTextureUnit) = *(originalPass->getTextureUnitState(t));
590 shadowTextureUnit->setColourOperationEx(Ogre::LBX_SOURCE1, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, Ogre::ColourValue::Black);
596 shadowPass->setSceneBlending(Ogre::SBT_REPLACE);
597 shadowPass->setAlphaRejectFunction(Ogre::CMPF_ALWAYS_PASS);
601 shadowPass->setCullingMode(originalPass->getCullingMode());
602 shadowPass->setManualCullingMode(originalPass->getManualCullingMode());
605 Ogre::Pass* shadowCasterDefaultPass = shadowCasterTechnique->getPass(0);
608 if(shadowCasterDefaultPass->hasVertexProgram())
610 shadowPass->setVertexProgram(shadowCasterDefaultPass->getVertexProgramName(),
false);
611 const Ogre::GpuProgramPtr& shadowPassVertexProgram = shadowPass->getVertexProgram();
612 if (!shadowPassVertexProgram->isLoaded())
613 shadowPassVertexProgram->load();
616 shadowPass->setVertexProgramParameters(shadowCasterDefaultPass->getVertexProgramParameters());
620 if(shadowCasterDefaultPass->hasFragmentProgram())
622 shadowPass->setFragmentProgram(shadowCasterDefaultPass->getFragmentProgramName(),
false);
623 const Ogre::GpuProgramPtr& shadowPassFragmentProgram = shadowPass->getVertexProgram();
624 if (!shadowPassFragmentProgram->isLoaded())
625 shadowPassFragmentProgram->load();
628 shadowPass->setFragmentProgramParameters(shadowCasterDefaultPass->getFragmentProgramParameters());
632 shadowPass->getParent()->getParent()->compile();
633 shadowPass = shadowPass->getParent()->getParent()->getBestTechnique()->getPass(0);
638 return shadowTechnique;
void RegisterSceneManager(Ogre::SceneManager *targetScene)
static SDeferredShadowManager * getSingletonPtr()
void SetShadowStandardTextureFSAA(unsigned short fsaa)
void SetShadowStandardTextureSize(unsigned short size)
void SetShadowCubicTextureSize(unsigned short size)
static SDeferredShadowManager & getSingleton()
void UnregisterSceneManager(Ogre::SceneManager *existingScene)
void SetShadowStandardTexturePixelFormat(Ogre::PixelFormat fmt)
Ogre::TexturePtr & PrepareShadowTexture(Ogre::Camera *ogreCamera, Ogre::Viewport *ogreViewport, const Ogre::Light *light, Ogre::Pass *ogrePass)
void SetShadowTextureFSAA(unsigned short fsaa)
void SetShadowTextureSize(unsigned short size)
void SetShadowTexturePixelFormat(Ogre::PixelFormat fmt)
void SetShadowCubicTexturePixelFormat(Ogre::PixelFormat fmt)
~SDeferredShadowManager()
void SetShadowCubicTextureFSAA(unsigned short fsaa)
virtual Ogre::Technique * handleSchemeNotFound(unsigned short schemeIndex, const Ogre::String &schemeName, Ogre::Material *originalMaterial, unsigned short lodIndex, const Ogre::Renderable *rend)
SException indicating that an attempt to create a new item with a given identifier fails cause anothe...
SException indicating that an attempt to get an item fails, cause there's no item with the given iden...