1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-20 06:53:52 +00:00

shareable shadow maps

This commit is contained in:
Mads Buvik Sandvei 2020-07-22 14:37:43 +02:00
parent 49b78ef463
commit d923c3f77a
2 changed files with 116 additions and 0 deletions

View file

@ -900,6 +900,75 @@ MWShadowTechnique::ViewDependentData* MWShadowTechnique::getViewDependentData(os
return vdd.release();
}
MWShadowTechnique::ViewDependentData* MWShadowTechnique::getSharedVdd(const SharedShadowMapConfig& config)
{
auto it = _viewDependentDataShareMap.find(config._id);
if (it != _viewDependentDataShareMap.end())
return it->second;
return nullptr;
}
void MWShadowTechnique::addSharedVdd(const SharedShadowMapConfig& config, ViewDependentData* vdd)
{
_viewDependentDataShareMap[config._id] = vdd;
}
void SceneUtil::MWShadowTechnique::shareShadowMap(osgUtil::CullVisitor& cv, ViewDependentData* lhs, ViewDependentData* rhs)
{
// Prepare for rendering shadows using the shadow map owned by rhs.
// To achieve this i first copy all data that is not specific to this cv's camera and thus read-only,
// trusting openmw and osg won't overwrite that data before this frame is done rendering.
// This works due to the double buffering of CullVisitors by osg, but also requires that cull passes are serialized (relative to one another).
// Then initialize new copies of the data that will be written with view-specific data
// (the stateset and the texgens).
lhs->_viewDependentShadowMap = rhs->_viewDependentShadowMap;
lhs->_stateset->clear();
lhs->_lightDataList = rhs->_lightDataList;
lhs->_numValidShadows = rhs->_numValidShadows;
ShadowDataList& sdl = lhs->getShadowDataList();
ShadowDataList previous_sdl;
previous_sdl.swap(sdl);
for (auto rhs_sd : rhs->getShadowDataList())
{
osg::ref_ptr<ShadowData> lhs_sd;
if (previous_sdl.empty())
{
OSG_INFO << "Create new ShadowData" << std::endl;
lhs_sd = new ShadowData(lhs);
}
else
{
OSG_INFO << "Taking ShadowData from from of previous_sdl" << std::endl;
lhs_sd = previous_sdl.front();
previous_sdl.erase(previous_sdl.begin());
}
lhs_sd->_camera = rhs_sd->_camera;
lhs_sd->_textureUnit = rhs_sd->_textureUnit;
lhs_sd->_texture = rhs_sd->_texture;
sdl.push_back(lhs_sd);
}
cv.pushStateSet(_shadowRecievingPlaceholderStateSet.get());
osg::ref_ptr<osgUtil::StateGraph> decoratorStateGraph = cv.getCurrentStateGraph();
cullShadowReceivingScene(&cv);
cv.popStateSet();
for (auto sd : sdl)
{
assignTexGenSettings(&cv, sd->_camera, sd->_textureUnit, sd->_texgen.get());
}
if (lhs->numValidShadows() > 0)
{
decoratorStateGraph->setStateSet(selectStateSetForRenderingShadow(*lhs));
}
}
void MWShadowTechnique::update(osg::NodeVisitor& nv)
{
OSG_INFO<<"MWShadowTechnique::update(osg::NodeVisitor& "<<&nv<<")"<<std::endl;
@ -925,6 +994,29 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
ViewDependentData* vdd = getViewDependentData(&cv);
// Use shared shadow map if applicable
auto* sharedConfig = dynamic_cast<SharedShadowMapConfig*>(cv.getCurrentCamera()->getUserData());
if (sharedConfig)
{
if (sharedConfig->_master)
{
addSharedVdd(*sharedConfig, vdd);
}
else
{
auto* sharedVdd = getSharedVdd(*sharedConfig);
if (sharedVdd)
{
OSG_INFO << "Using shared shadow map" << std::endl;
return shareShadowMap(cv, vdd, sharedVdd);
}
else
{
OSG_INFO << "Warning, view configured to reuse shared shadow map but no shadow map has been shared. Shadows will be generated instead." << std::endl;
}
}
}
if (!vdd)
{
OSG_INFO<<"Warning, now ViewDependentData created, unable to create shadows."<<std::endl;
@ -1397,6 +1489,7 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
_debugHud->draw(sd->_texture, sm_i, camera->getViewMatrix() * camera->getProjectionMatrix(), cv);
}
}
vdd->setNumValidShadows(numValidShadows);
if (numValidShadows>0)
{

View file

@ -141,6 +141,17 @@ namespace SceneUtil {
// forward declare
class ViewDependentData;
/// Configuration of shadow maps shared by multiple views
struct SharedShadowMapConfig : public osg::Referenced
{
virtual ~SharedShadowMapConfig() {}
/// String identifier of the shared shadow map
std::string _id;
bool _master;
};
struct LightData : public osg::Referenced
{
LightData(ViewDependentData* vdd);
@ -195,7 +206,12 @@ namespace SceneUtil {
virtual void releaseGLObjects(osg::State* = 0) const;
unsigned int numValidShadows(void) const { return _numValidShadows; }
void setNumValidShadows(unsigned int numValidShadows) { _numValidShadows = numValidShadows; }
protected:
friend class MWShadowTechnique;
virtual ~ViewDependentData() {}
MWShadowTechnique* _viewDependentShadowMap;
@ -204,11 +220,16 @@ namespace SceneUtil {
LightDataList _lightDataList;
ShadowDataList _shadowDataList;
unsigned int _numValidShadows;
};
virtual ViewDependentData* createViewDependentData(osgUtil::CullVisitor* cv);
ViewDependentData* getViewDependentData(osgUtil::CullVisitor* cv);
ViewDependentData* getSharedVdd(const SharedShadowMapConfig& config);
void addSharedVdd(const SharedShadowMapConfig& config, ViewDependentData* vdd);
void shareShadowMap(osgUtil::CullVisitor& cv, ViewDependentData* lhs, ViewDependentData* rhs);
@ -237,7 +258,9 @@ namespace SceneUtil {
typedef std::map< osgUtil::CullVisitor*, osg::ref_ptr<ViewDependentData> > ViewDependentDataMap;
mutable std::mutex _viewDependentDataMapMutex;
typedef std::map< std::string, osg::ref_ptr<ViewDependentData> > ViewDependentDataShareMap;
ViewDependentDataMap _viewDependentDataMap;
ViewDependentDataShareMap _viewDependentDataShareMap;
osg::ref_ptr<osg::StateSet> _shadowRecievingPlaceholderStateSet;