You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
7.5 KiB
C++
188 lines
7.5 KiB
C++
#include "shadows.hpp"
|
|
|
|
#include <components/settings/settings.hpp>
|
|
#include <openengine/ogre/renderer.hpp>
|
|
|
|
#include <OgreSceneManager.h>
|
|
#include <OgreColourValue.h>
|
|
#include <OgreShadowCameraSetupLiSPSM.h>
|
|
#include <OgreShadowCameraSetupPSSM.h>
|
|
#include <OgreHardwarePixelBuffer.h>
|
|
#include <OgreCamera.h>
|
|
#include <OgreRenderTexture.h>
|
|
#include <OgreViewport.h>
|
|
|
|
#include <extern/shiny/Main/Factory.hpp>
|
|
|
|
#include "renderconst.hpp"
|
|
|
|
using namespace Ogre;
|
|
using namespace MWRender;
|
|
|
|
Shadows::Shadows(OEngine::Render::OgreRenderer* rend) :
|
|
mRendering(rend), mSceneMgr(rend->getScene()), mPSSMSetup(NULL),
|
|
mShadowFar(1000), mFadeStart(0.9f)
|
|
{
|
|
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 = Settings::Manager::getFloat(split ? "split shadow distance" : "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<sh::Vector3>(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<sh::Vector4>(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<OverlayContainer*>(
|
|
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;
|
|
}
|