allows to skip ComputeLightSpaceBounds traversal (#3152)

Currently, we always traverse the scene graph an additional time with a ComputeLightSpaceBounds visitor during shadow casting. ComputeLightSpaceBounds is only useful when the shadow casting mask allows us to shrink the bounds of the rendered scene, so we guard its traversal with a check against getCastsShadowTraversalMask. In practice, this guard never works because we build the traversal mask inclusively.

With this PR we limit the getCastsShadowTraversalMask check to relevant masks. This new check allows us to skip a superfluous ComputeLightSpaceBounds traversal with most settings.
pull/3169/head
Bo Svensson 3 years ago committed by GitHub
parent 66a6b80df9
commit 98f8295765
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -195,7 +195,7 @@ osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, f
camera->setNodeMask(Mask_RenderToTexture);
// Disable small feature culling, it's not going to be reliable for this camera
osg::Camera::CullingMode cullingMode = (osg::Camera::DEFAULT_CULLING|osg::Camera::FAR_PLANE_CULLING) & ~(osg::CullStack::SMALL_FEATURE_CULLING);
osg::Camera::CullingMode cullingMode = (osg::Camera::DEFAULT_CULLING|osg::Camera::FAR_PLANE_CULLING) & ~(osg::Camera::SMALL_FEATURE_CULLING);
camera->setCullingMode(cullingMode);
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;

@ -340,14 +340,14 @@ namespace MWRender
shadowCastingTraversalMask |= Mask_Actor;
if (Settings::Manager::getBool("player shadows", "Shadows"))
shadowCastingTraversalMask |= Mask_Player;
if (Settings::Manager::getBool("terrain shadows", "Shadows"))
shadowCastingTraversalMask |= Mask_Terrain;
int indoorShadowCastingTraversalMask = shadowCastingTraversalMask;
if (Settings::Manager::getBool("object shadows", "Shadows"))
shadowCastingTraversalMask |= (Mask_Object|Mask_Static);
if (Settings::Manager::getBool("terrain shadows", "Shadows"))
shadowCastingTraversalMask |= Mask_Terrain;
mShadowManager.reset(new SceneUtil::ShadowManager(sceneRoot, mRootNode, shadowCastingTraversalMask, indoorShadowCastingTraversalMask, mResourceSystem->getSceneManager()->getShaderManager()));
mShadowManager.reset(new SceneUtil::ShadowManager(sceneRoot, mRootNode, shadowCastingTraversalMask, indoorShadowCastingTraversalMask, Mask_Terrain|Mask_Object|Mask_Static, mResourceSystem->getSceneManager()->getShaderManager()));
Shader::ShaderManager::DefineMap shadowDefines = mShadowManager->getShadowDefines();
Shader::ShaderManager::DefineMap lightDefines = sceneRoot->getLightDefines();

@ -357,8 +357,6 @@ MWShadowTechnique::ComputeLightSpaceBounds::ComputeLightSpaceBounds() :
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN)
{
setCullingMode(osg::CullSettings::VIEW_FRUSTUM_CULLING);
setName("SceneUtil::MWShadowTechnique::ComputeLightSpaceBounds,AcceptedByComponentsTerrainQuadTreeWorld");
}
void MWShadowTechnique::ComputeLightSpaceBounds::reset()
@ -393,14 +391,6 @@ void MWShadowTechnique::ComputeLightSpaceBounds::apply(osg::Drawable& drawable)
popCurrentMask();
}
void MWShadowTechnique::ComputeLightSpaceBounds::apply(Terrain::QuadTreeWorld & quadTreeWorld)
{
// For now, just expand the bounds fully as terrain will fill them up and possible ways to detect which terrain definitely won't cast shadows aren't implemented.
update(osg::Vec3(-1.0, -1.0, 0.0));
update(osg::Vec3(1.0, 1.0, 0.0));
}
void MWShadowTechnique::ComputeLightSpaceBounds::apply(osg::Billboard&)
{
OSG_INFO << "Warning Billboards not yet supported" << std::endl;
@ -1122,7 +1112,7 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
// if we are using multiple shadow maps and CastShadowTraversalMask is being used
// traverse the scene to compute the extents of the objects
if (/*numShadowMapsPerLight>1 &&*/ _shadowedScene->getCastsShadowTraversalMask()!=0xffffffff)
if (/*numShadowMapsPerLight>1 &&*/ (_shadowedScene->getCastsShadowTraversalMask() & _worldMask) == 0)
{
// osg::ElapsedTime timer;

@ -31,7 +31,6 @@
#include <osgShadow/ShadowTechnique>
#include <components/shader/shadermanager.hpp>
#include <components/terrain/quadtreeworld.hpp>
namespace SceneUtil {
@ -96,8 +95,6 @@ namespace SceneUtil {
void apply(osg::Drawable& drawable) override;
void apply(Terrain::QuadTreeWorld& quadTreeWorld);
void apply(osg::Billboard&) override;
void apply(osg::Projection&) override;
@ -237,6 +234,8 @@ namespace SceneUtil {
virtual osg::StateSet* prepareStateSetForRenderingShadow(ViewDependentData& vdd, unsigned int traversalNumber) const;
void setWorldMask(unsigned int worldMask) { _worldMask = worldMask; }
protected:
virtual ~MWShadowTechnique();
@ -270,6 +269,8 @@ namespace SceneUtil {
float _shadowFadeStart = 0.0;
unsigned int _worldMask = ~0u;
class DebugHUD final : public osg::Referenced
{
public:

@ -1,10 +1,13 @@
#include "shadow.hpp"
#include <osgShadow/ShadowedScene>
#include <osgShadow/ShadowSettings>
#include <components/misc/stringops.hpp>
#include <components/settings/settings.hpp>
#include "mwshadowtechnique.hpp"
namespace SceneUtil
{
using namespace osgShadow;
@ -94,7 +97,7 @@ namespace SceneUtil
}
}
ShadowManager::ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, Shader::ShaderManager &shaderManager) : mShadowedScene(new osgShadow::ShadowedScene),
ShadowManager::ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, unsigned int worldMask, Shader::ShaderManager &shaderManager) : mShadowedScene(new osgShadow::ShadowedScene),
mShadowTechnique(new MWShadowTechnique),
mOutdoorShadowCastingMask(outdoorShadowCastingMask),
mIndoorShadowCastingMask(indoorShadowCastingMask)
@ -109,10 +112,15 @@ namespace SceneUtil
setupShadowSettings();
mShadowTechnique->setupCastingShader(shaderManager);
mShadowTechnique->setWorldMask(worldMask);
enableOutdoorMode();
}
ShadowManager::~ShadowManager()
{
}
Shader::ShaderManager::DefineMap ShadowManager::getShadowDefines()
{
if (!mEnableShadows)

@ -1,15 +1,22 @@
#ifndef COMPONENTS_SCENEUTIL_SHADOW_H
#define COMPONENTS_SCENEUTIL_SHADOW_H
#include <osgShadow/ShadowSettings>
#include <osgShadow/ShadowedScene>
#include <components/shader/shadermanager.hpp>
#include "mwshadowtechnique.hpp"
namespace osg
{
class StateSet;
class Group;
}
namespace osgShadow
{
class ShadowSettings;
class ShadowedScene;
}
namespace SceneUtil
{
class MWShadowTechnique;
class ShadowManager
{
public:
@ -17,7 +24,8 @@ namespace SceneUtil
static Shader::ShaderManager::DefineMap getShadowsDisabledDefines();
ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, Shader::ShaderManager &shaderManager);
ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, unsigned int worldMask, Shader::ShaderManager &shaderManager);
~ShadowManager();
void setupShadowSettings();

@ -3,12 +3,12 @@
#include <osgUtil/CullVisitor>
#include <osg/ShapeDrawable>
#include <osg/PolygonMode>
#include <osg/Material>
#include <limits>
#include <sstream>
#include <components/misc/constants.hpp>
#include <components/sceneutil/mwshadowtechnique.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
#include <components/loadinglistener/reporter.hpp>
#include <components/resource/resourcesystem.hpp>
@ -257,10 +257,10 @@ public:
{
osg::Vec3f center = { chunkCenter.x(), chunkCenter.y(), 0 };
auto chunkBorder = CellBorder::createBorderGeometry(center.x() - size / 2.f, center.y() - size / 2.f, size, mStorage, mSceneManager, mNodeMask, 5.f, { 1, 0, 0, 0 });
osg::ref_ptr<osg::MatrixTransform> trans = new osg::MatrixTransform(osg::Matrixf::translate(-center*Constants::CellSizeInUnits));
trans->setDataVariance(osg::Object::STATIC);
trans->addChild(chunkBorder);
return trans;
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> pat = new SceneUtil::PositionAttitudeTransform;
pat->setPosition(-center*Constants::CellSizeInUnits);
pat->addChild(chunkBorder);
return pat;
}
unsigned int getNodeMask() { return mNodeMask; }
private:
@ -440,19 +440,7 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv)
{
bool isCullVisitor = nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR;
if (!isCullVisitor && nv.getVisitorType() != osg::NodeVisitor::INTERSECTION_VISITOR)
{
if (nv.getName().find("AcceptedByComponentsTerrainQuadTreeWorld") != std::string::npos)
{
if (nv.getName().find("SceneUtil::MWShadowTechnique::ComputeLightSpaceBounds") != std::string::npos)
{
SceneUtil::MWShadowTechnique::ComputeLightSpaceBounds* clsb = static_cast<SceneUtil::MWShadowTechnique::ComputeLightSpaceBounds*>(&nv);
clsb->apply(*this);
}
else
nv.apply(*mRootNode);
}
return;
}
osg::Object * viewer = isCullVisitor ? static_cast<osgUtil::CullVisitor*>(&nv)->getCurrentCamera() : nullptr;
bool needsUpdate = true;

Loading…
Cancel
Save