#include "shadows.hpp" #include #include #include #include #include #include #include #include #include #include #include #include "renderconst.hpp" using namespace Ogre; using namespace MWRender; Shadows::Shadows(OEngine::Render::OgreRenderer* rend) : mShadowFar(1000), mFadeStart(0.9) { mRendering = rend; mSceneMgr = mRendering->getScene(); recreate(); } void Shadows::recreate() { bool enabled = Settings::Manager::getBool("enabled", "Shadows"); bool split = Settings::Manager::getBool("split", "Shadows"); sh::Factory::getInstance ().setGlobalSetting ("shadows", enabled && !split ? "true" : "false"); sh::Factory::getInstance ().setGlobalSetting ("shadows_pssm", enabled && split ? "true" : "false"); if (!enabled) { mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE); return; } int texsize = Settings::Manager::getInt("texture size", "Shadows"); mSceneMgr->setShadowTextureSize(texsize); mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED); // no point light shadows, i'm afraid. might revisit this with Deferred Shading mSceneMgr->setShadowTextureCountPerLightType(Light::LT_POINT, 0); mSceneMgr->setShadowTextureCountPerLightType(Light::LT_DIRECTIONAL, split ? 3 : 1); mSceneMgr->setShadowTextureCount(split ? 3 : 1); mSceneMgr->setShadowTextureSelfShadow(true); mSceneMgr->setShadowCasterRenderBackFaces(true); mSceneMgr->setShadowTextureCasterMaterial("openmw_shadowcaster_default"); mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R); mSceneMgr->setShadowDirectionalLightExtrusionDistance(1000000); mShadowFar = split ? Settings::Manager::getInt("split shadow distance", "Shadows") : Settings::Manager::getInt("shadow distance", "Shadows"); mSceneMgr->setShadowFarDistance(mShadowFar); mFadeStart = Settings::Manager::getFloat("fade start", "Shadows"); ShadowCameraSetupPtr shadowCameraSetup; if (split) { mPSSMSetup = new PSSMShadowCameraSetup(); // Make sure to keep this in sync with the camera's near clip distance! mPSSMSetup->setSplitPadding(mRendering->getCamera()->getNearClipDistance()); mPSSMSetup->calculateSplitPoints(3, mRendering->getCamera()->getNearClipDistance(), mShadowFar); const Real adjustFactors[3] = {64, 64, 64}; for (int i=0; i < 3; ++i) { mPSSMSetup->setOptimalAdjustFactor(i, adjustFactors[i]); /*if (i==0) mSceneMgr->setShadowTextureConfig(i, texsize, texsize, Ogre::PF_FLOAT32_R); else if (i ==1) mSceneMgr->setShadowTextureConfig(i, texsize/2, texsize/2, Ogre::PF_FLOAT32_R); else if (i ==2) mSceneMgr->setShadowTextureConfig(i, texsize/4, texsize/4, Ogre::PF_FLOAT32_R);*/ } // Populate from split point 1, not 0, since split 0 isn't useful (usually 0) const PSSMShadowCameraSetup::SplitPointList& splitPointList = getPSSMSetup()->getSplitPoints(); sh::Vector3* splitPoints = new sh::Vector3(splitPointList[1], splitPointList[2], splitPointList[3]); sh::Factory::getInstance ().setSharedParameter ("pssmSplitPoints", sh::makeProperty(splitPoints)); shadowCameraSetup = ShadowCameraSetupPtr(mPSSMSetup); } else { LiSPSMShadowCameraSetup* lispsmSetup = new LiSPSMShadowCameraSetup(); lispsmSetup->setOptimalAdjustFactor(64); //lispsmSetup->setCameraLightDirectionThreshold(Degree(0)); //lispsmSetup->setUseAggressiveFocusRegion(false); shadowCameraSetup = ShadowCameraSetupPtr(lispsmSetup); } mSceneMgr->setShadowCameraSetup(shadowCameraSetup); sh::Vector4* shadowFar_fadeStart = new sh::Vector4(mShadowFar, mFadeStart * mShadowFar, 0, 0); sh::Factory::getInstance ().setSharedParameter ("shadowFar_fadeStart", sh::makeProperty(shadowFar_fadeStart)); // Set visibility mask for the shadow render textures int visibilityMask = RV_Actors * Settings::Manager::getBool("actor shadows", "Shadows") + (RV_Statics + RV_StaticsSmall) * Settings::Manager::getBool("statics shadows", "Shadows") + RV_Misc * Settings::Manager::getBool("misc shadows", "Shadows") + RV_Terrain * (Settings::Manager::getBool("terrain shadows", "Shadows")); for (int i = 0; i < (split ? 3 : 1); ++i) { TexturePtr shadowTexture = mSceneMgr->getShadowTexture(i); Viewport* vp = shadowTexture->getBuffer()->getRenderTarget()->getViewport(0); vp->setVisibilityMask(visibilityMask); } // -------------------------------------------------------------------------------------------------------------------- // --------------------------- Debug overlays to display the content of shadow maps ----------------------------------- // -------------------------------------------------------------------------------------------------------------------- /* if (Settings::Manager::getBool("debug", "Shadows")) { OverlayManager& mgr = OverlayManager::getSingleton(); Overlay* overlay; // destroy if already exists if ((overlay = mgr.getByName("DebugOverlay"))) mgr.destroy(overlay); overlay = mgr.create("DebugOverlay"); for (size_t i = 0; i < (split ? 3 : 1); ++i) { TexturePtr tex = mRendering->getScene()->getShadowTexture(i); // Set up a debug panel to display the shadow if (MaterialManager::getSingleton().resourceExists("Ogre/DebugTexture" + StringConverter::toString(i))) MaterialManager::getSingleton().remove("Ogre/DebugTexture" + StringConverter::toString(i)); MaterialPtr debugMat = MaterialManager::getSingleton().create( "Ogre/DebugTexture" + StringConverter::toString(i), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false); TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName()); t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); OverlayContainer* debugPanel; // destroy container if exists try { if ((debugPanel = static_cast( mgr.getOverlayElement("Ogre/DebugTexPanel" + StringConverter::toString(i) )))) mgr.destroyOverlayElement(debugPanel); } catch (Ogre::Exception&) {} debugPanel = (OverlayContainer*) (OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugTexPanel" + StringConverter::toString(i))); debugPanel->_setPosition(0.8, i*0.25); debugPanel->_setDimensions(0.2, 0.24); debugPanel->setMaterialName(debugMat->getName()); debugPanel->show(); overlay->add2D(debugPanel); overlay->show(); } } else { OverlayManager& mgr = OverlayManager::getSingleton(); Overlay* overlay; if ((overlay = mgr.getByName("DebugOverlay"))) mgr.destroy(overlay); } */ } PSSMShadowCameraSetup* Shadows::getPSSMSetup() { return mPSSMSetup; } float Shadows::getShadowFar() const { return mShadowFar; } float Shadows::getFadeStart() const { return mFadeStart; }