From 954a09dce13bbba8f85bca6b77bed4f28a49e91d Mon Sep 17 00:00:00 2001 From: Frederic Bouvier Date: Fri, 30 Mar 2012 22:30:26 +0200 Subject: [PATCH] Shadow map size settable at run-time. It needs to be a power of two. Now needs a real gui dialog --- src/Main/CameraGroup.cxx | 8 +++++ src/Main/CameraGroup.hxx | 2 +- src/Main/renderer.cxx | 65 ++++++++++++++++++++++++++++++++++++++-- src/Main/renderer.hxx | 1 + 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/Main/CameraGroup.cxx b/src/Main/CameraGroup.cxx index 2795191a8..0b676633f 100644 --- a/src/Main/CameraGroup.cxx +++ b/src/Main/CameraGroup.cxx @@ -246,6 +246,14 @@ osg::Camera* CameraInfo::getCamera(CameraKind k) const return ii->second.camera.get(); } +osg::Texture2D* CameraInfo::getBuffer(RenderBufferInfo::Kind k) const +{ + RenderBufferMap::const_iterator ii = buffers.find(k); + if (ii == buffers.end()) + return 0; + return ii->second.texture.get(); +} + int CameraInfo::getMainSlaveIndex() const { return cameras.find( MAIN_CAMERA )->second.slaveIndex; diff --git a/src/Main/CameraGroup.hxx b/src/Main/CameraGroup.hxx index 5877429d5..606bfc347 100644 --- a/src/Main/CameraGroup.hxx +++ b/src/Main/CameraGroup.hxx @@ -158,7 +158,7 @@ struct CameraInfo : public osg::Referenced */ RenderBufferMap buffers; void addBuffer(RenderBufferInfo::Kind k, osg::Texture2D* tex, float scale = 1.0 ) { buffers[k] = RenderBufferInfo(tex,scale); } - osg::Texture2D* getBuffer(RenderBufferInfo::Kind k) { return buffers[k].texture.get(); } + osg::Texture2D* getBuffer(RenderBufferInfo::Kind k) const; osg::ref_ptr shadowTexGen[4]; diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index db17e0a86..f7198fb9a 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -446,11 +446,19 @@ FGRenderer::splashinit( void ) { fgSetDouble("/sim/startup/splash-alpha", 1.0); } +class ShadowMapSizeListener : public SGPropertyChangeListener { +public: + virtual void valueChanged(SGPropertyNode* node) { + globals->get_renderer()->updateShadowMapSize(node->getIntValue()); + } +}; + void FGRenderer::init( void ) { _classicalRenderer = !fgGetBool("/sim/rendering/rembrandt", false); _shadowMapSize = fgGetInt( "/sim/rendering/shadows/map-size", 4096 ); + fgAddChangeListener( new ShadowMapSizeListener, "/sim/rendering/shadows/map-size" ); _scenery_loaded = fgGetNode("/sim/sceneryloaded", true); _scenery_override = fgGetNode("/sim/sceneryloaded-override", true); _panel_hotspots = fgGetNode("/sim/panel-hotspots", true); @@ -856,7 +864,7 @@ void FGRenderer::updateShadowCamera(const flightgear::CameraInfo* info, const os updateShadowCascade(info, camera, grp, 0, left, right, bottom, top, zNear, 1.0, 5.0/zNear); updateShadowCascade(info, camera, grp, 1, left, right, bottom, top, zNear, 5.0/zNear,50.0/zNear); updateShadowCascade(info, camera, grp, 2, left, right, bottom, top, zNear, 50.0/zNear,512.0/zNear); - updateShadowCascade(info, camera, grp, 3, left, right, bottom, top, zNear, 512.0/zNear,10000.0/zNear); + updateShadowCascade(info, camera, grp, 3, left, right, bottom, top, zNear, 512.0/zNear,5000.0/zNear); { osg::Camera* cascade = static_cast( mainShadowCamera ); osg::Matrixd &viewMatrix = cascade->getViewMatrix(); @@ -872,6 +880,57 @@ void FGRenderer::updateShadowCamera(const flightgear::CameraInfo* info, const os } } +void FGRenderer::updateShadowMapSize(int mapSize) +{ + if ( ((~( mapSize-1 )) & mapSize) != mapSize ) { + SG_LOG( SG_VIEW, SG_ALERT, "Map size is not a power of two" ); + return; + } + for ( CameraGroup::CameraIterator ii = CameraGroup::getDefault()->camerasBegin(); + ii != CameraGroup::getDefault()->camerasEnd(); + ++ii ) + { + CameraInfo* info = ii->get(); + Camera* camera = info->getCamera(SHADOW_CAMERA); + if (camera == 0) continue; + + Texture2D* tex = info->getBuffer(RenderBufferInfo::SHADOW_BUFFER); + if (tex == 0) continue; + + tex->setTextureSize( mapSize, mapSize ); + tex->dirtyTextureObject(); + + Viewport* vp = camera->getViewport(); + vp->width() = mapSize; + vp->height() = mapSize; + + osgViewer::Renderer* renderer + = static_cast(camera->getRenderer()); + for (int i = 0; i < 2; ++i) { + osgUtil::SceneView* sceneView = renderer->getSceneView(i); + sceneView->getRenderStage()->setFrameBufferObject(0); + sceneView->getRenderStage()->setCameraRequiresSetUp(true); + if (sceneView->getRenderStageLeft()) { + sceneView->getRenderStageLeft()->setFrameBufferObject(0); + sceneView->getRenderStageLeft()->setCameraRequiresSetUp(true); + } + if (sceneView->getRenderStageRight()) { + sceneView->getRenderStageRight()->setFrameBufferObject(0); + sceneView->getRenderStageRight()->setCameraRequiresSetUp(true); + } + } + + int cascadeSize = mapSize / 2; + Group* grp = camera->getChild(0)->asGroup(); + for (int i = 0; i < 4; ++i ) { + Camera* cascadeCam = static_cast( grp->getChild(i) ); + cascadeCam->setViewport( int( i / 2 ) * cascadeSize, (i & 1) * cascadeSize, cascadeSize, cascadeSize ); + } + + _shadowMapSize = mapSize; + } +} + #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) @@ -1050,7 +1109,7 @@ const char *fog_frag_src = "" osg::Camera* FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc ) { - SG_LOG( SG_INPUT, SG_ALERT, "Harmless warning messages on effects not found beyond this point" ); + SG_LOG( SG_VIEW, SG_ALERT, "Harmless warning messages on effects not found beyond this point" ); osg::Camera* camera = new osg::Camera; info->addCamera(flightgear::LIGHTING_CAMERA, camera ); @@ -1236,7 +1295,7 @@ osg::Camera* FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* in camera->addChild( lightingGroup ); - SG_LOG( SG_INPUT, SG_ALERT, "End of harmless warning messages on effects not found" ); + SG_LOG( SG_VIEW, SG_ALERT, "End of harmless warning messages on effects not found" ); return camera; } diff --git a/src/Main/renderer.hxx b/src/Main/renderer.hxx index 0db0fa5d7..819745538 100644 --- a/src/Main/renderer.hxx +++ b/src/Main/renderer.hxx @@ -105,6 +105,7 @@ public: const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc); void updateShadowCamera(const flightgear::CameraInfo* info, const osg::Vec3d& position); + void updateShadowMapSize(int mapSize); SGSky* getSky() const { return _sky; }