diff --git a/modules/ovis/include/opencv2/ovis.hpp b/modules/ovis/include/opencv2/ovis.hpp index c471b09e6a9..699e56e3689 100644 --- a/modules/ovis/include/opencv2/ovis.hpp +++ b/modules/ovis/include/opencv2/ovis.hpp @@ -52,7 +52,9 @@ enum SceneSettings /// Apply anti-aliasing. The first window determines the setting for all windows. SCENE_AA = 8, /// Render off-screen without a window. Allows separate AA setting. Requires manual update via @ref WindowScene::update - SCENE_OFFSCREEN = 16 + SCENE_OFFSCREEN = 16, + /// Enable real-time shadows in the scene. All entities cast shadows by default. Control via @ref ENTITY_CAST_SHADOWS + SCENE_SHADOWS = 32 }; enum MaterialProperty @@ -74,7 +76,8 @@ enum EntityProperty ENTITY_MATERIAL, ENTITY_SCALE, ENTITY_AABB_WORLD, - ENTITY_ANIMBLEND_MODE + ENTITY_ANIMBLEND_MODE, + ENTITY_CAST_SHADOWS }; /** diff --git a/modules/ovis/src/ovis.cpp b/modules/ovis/src/ovis.cpp index 1ad8bad2c63..2f9f69a6f73 100644 --- a/modules/ovis/src/ovis.cpp +++ b/modules/ovis/src/ovis.cpp @@ -187,6 +187,7 @@ struct Application : public OgreBites::ApplicationContext, public OgreBites::Inp uint32_t h; int key_pressed; int flags; + Ogre::MaterialPtr casterMat; Application(const Ogre::String& _title, const Size& sz, int _flags) : OgreBites::ApplicationContext("ovis"), mainWin(NULL), title(_title), w(sz.width), @@ -287,6 +288,9 @@ struct Application : public OgreBites::ApplicationContext, public OgreBites::Inp MaterialManager& matMgr = MaterialManager::getSingleton(); matMgr.setDefaultTextureFiltering(TFO_ANISOTROPIC); matMgr.setDefaultAnisotropy(16); + casterMat = matMgr.create("DepthCaster", Ogre::RGN_INTERNAL); + casterMat->setLightingEnabled(false); + casterMat->setDepthBias(-1, -1); } }; @@ -318,6 +322,21 @@ class WindowSceneImpl : public WindowScene RTShader::ShaderGenerator& shadergen = RTShader::ShaderGenerator::getSingleton(); shadergen.addSceneManager(sceneMgr); // must be done before we do anything with the scene + if (flags & SCENE_SHADOWS) + { + sceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED); + sceneMgr->setShadowTexturePixelFormat(PF_DEPTH32); + // arbitrary heuristic for shadowmap size + sceneMgr->setShadowTextureSize(std::max(sz.width, sz.height) * 2); + sceneMgr->setShadowCameraSetup(FocusedShadowCameraSetup::create()); + sceneMgr->setShadowTextureCasterMaterial(app->casterMat); + + // inject shadowmap into materials + const auto& schemeName = RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME; + auto rs = shadergen.getRenderState(schemeName); + rs->addTemplateSubRenderState(shadergen.createSubRenderState("SGX_IntegratedPSSM3")); + } + sceneMgr->setAmbientLight(ColourValue(.1, .1, .1)); _createBackground(); } @@ -716,6 +735,13 @@ class WindowSceneImpl : public WindowScene SceneNode& node = _getSceneNode(sceneMgr, name); switch(prop) { + case ENTITY_CAST_SHADOWS: + { + Entity* ent = dynamic_cast(node.getAttachedObject(name)); + CV_Assert(ent && "invalid entity"); + ent->setCastShadows(bool(value[0])); + break; + } case ENTITY_SCALE: { node.setScale(value[0], value[1], value[2]);