From e05d97502095d71506eb9595a42ed07f47b728f0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 14 Feb 2016 23:14:52 +0100 Subject: [PATCH] Change the way that texture filtering settings are applied at runtime --- apps/openmw/engine.cpp | 3 +-- apps/openmw/mwrender/renderingmanager.cpp | 10 ++++++---- apps/openmw/mwrender/water.cpp | 3 --- components/resource/objectcache.cpp | 16 +++++++++++++++ components/resource/objectcache.hpp | 4 ++++ components/resource/scenemanager.cpp | 24 +++-------------------- components/resource/scenemanager.hpp | 10 ++-------- components/terrain/terraingrid.cpp | 8 +++++++- components/terrain/terraingrid.hpp | 4 ++++ components/terrain/world.hpp | 2 ++ 10 files changed, 45 insertions(+), 39 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index b3a58d18e..5fd328022 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -453,8 +453,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) Settings::Manager::getString("texture mag filter", "General"), Settings::Manager::getString("texture min filter", "General"), Settings::Manager::getString("texture mipmap", "General"), - Settings::Manager::getInt("anisotropy", "General"), - NULL + Settings::Manager::getInt("anisotropy", "General") ); // Create input and UI first to set up a bootstrapping environment for diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 29b641f6b..7569cea1f 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -836,16 +836,18 @@ namespace MWRender void RenderingManager::updateTextureFiltering() { - if (mTerrain.get()) - mTerrain->updateCache(); + mViewer->stopThreading(); mResourceSystem->getSceneManager()->setFilterSettings( Settings::Manager::getString("texture mag filter", "General"), Settings::Manager::getString("texture min filter", "General"), Settings::Manager::getString("texture mipmap", "General"), - Settings::Manager::getInt("anisotropy", "General"), - mViewer + Settings::Manager::getInt("anisotropy", "General") ); + + mTerrain->updateTextureFiltering(); + + mViewer->startThreading(); } void RenderingManager::updateAmbient() diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index e20590ecb..e6acbb500 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -318,7 +318,6 @@ public: mRefractionTexture->setInternalFormat(GL_RGB); mRefractionTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); mRefractionTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - mRefractionTexture->getOrCreateUserDataContainer()->addDescription("dont_override_filter"); attach(osg::Camera::COLOR_BUFFER, mRefractionTexture); @@ -330,7 +329,6 @@ public: mRefractionDepthTexture->setSourceType(GL_UNSIGNED_INT); mRefractionDepthTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); mRefractionDepthTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - mRefractionDepthTexture->getOrCreateUserDataContainer()->addDescription("dont_override_filter"); attach(osg::Camera::DEPTH_BUFFER, mRefractionDepthTexture); } @@ -393,7 +391,6 @@ public: mReflectionTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); mReflectionTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); mReflectionTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - mReflectionTexture->getOrCreateUserDataContainer()->addDescription("dont_override_filter"); attach(osg::Camera::COLOR_BUFFER, mReflectionTexture); diff --git a/components/resource/objectcache.cpp b/components/resource/objectcache.cpp index a0a3cf3a5..5fec6730d 100644 --- a/components/resource/objectcache.cpp +++ b/components/resource/objectcache.cpp @@ -14,6 +14,7 @@ #include "objectcache.hpp" #include +#include namespace Resource { @@ -119,4 +120,19 @@ void ObjectCache::releaseGLObjects(osg::State* state) } } +void ObjectCache::accept(osg::NodeVisitor &nv) +{ + OpenThreads::ScopedLock lock(_objectCacheMutex); + + for(ObjectCacheMap::iterator itr = _objectCache.begin(); + itr != _objectCache.end(); + ++itr) + { + osg::Object* object = itr->second.first.get(); + osg::Node* node = object->asNode(); + if (node) + node->accept(nv); + } +} + } diff --git a/components/resource/objectcache.hpp b/components/resource/objectcache.hpp index 79ebabd5b..82aca76f0 100644 --- a/components/resource/objectcache.hpp +++ b/components/resource/objectcache.hpp @@ -27,6 +27,7 @@ namespace osg { class Object; class State; + class NodeVisitor; } namespace Resource { @@ -66,6 +67,9 @@ class ObjectCache : public osg::Referenced /** call releaseGLObjects on all objects attached to the object cache.*/ void releaseGLObjects(osg::State* state); + /** call node->accept(nv); for all nodes in the objectCache. */ + void accept(osg::NodeVisitor& nv); + protected: virtual ~ObjectCache(); diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index ffe8dd881..e78cc7cb2 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -10,8 +10,6 @@ #include -#include - #include #include @@ -192,13 +190,6 @@ namespace Resource osg::Texture* tex = attr->asTexture(); if (tex) { - if (tex->getUserDataContainer()) - { - const std::vector& descriptions = tex->getUserDataContainer()->getDescriptions(); - if (std::find(descriptions.begin(), descriptions.end(), "dont_override_filter") != descriptions.end()) - return; - } - tex->setFilter(osg::Texture::MIN_FILTER, mMinFilter); tex->setFilter(osg::Texture::MAG_FILTER, mMagFilter); tex->setMaxAnisotropy(mMaxAnisotropy); @@ -425,8 +416,7 @@ namespace Resource } void SceneManager::setFilterSettings(const std::string &magfilter, const std::string &minfilter, - const std::string &mipmap, int maxAnisotropy, - osgViewer::Viewer *viewer) + const std::string &mipmap, int maxAnisotropy) { osg::Texture::FilterMode min = osg::Texture::LINEAR; osg::Texture::FilterMode mag = osg::Texture::LINEAR; @@ -458,23 +448,15 @@ namespace Resource min = osg::Texture::LINEAR_MIPMAP_LINEAR; } - if(viewer) viewer->stopThreading(); - mMinFilter = min; mMagFilter = mag; mMaxAnisotropy = std::max(1, maxAnisotropy); - mCache->clear(); - SetFilterSettingsControllerVisitor setFilterSettingsControllerVisitor (mMinFilter, mMagFilter, mMaxAnisotropy); SetFilterSettingsVisitor setFilterSettingsVisitor (mMinFilter, mMagFilter, mMaxAnisotropy); - if (viewer && viewer->getSceneData()) - { - viewer->getSceneData()->accept(setFilterSettingsControllerVisitor); - viewer->getSceneData()->accept(setFilterSettingsVisitor); - } - if(viewer) viewer->startThreading(); + mCache->accept(setFilterSettingsVisitor); + mCache->accept(setFilterSettingsControllerVisitor); } void SceneManager::applyFilterSettings(osg::Texture *tex) diff --git a/components/resource/scenemanager.hpp b/components/resource/scenemanager.hpp index 8357e63cd..987b7898e 100644 --- a/components/resource/scenemanager.hpp +++ b/components/resource/scenemanager.hpp @@ -21,11 +21,6 @@ namespace osgUtil class IncrementalCompileOperation; } -namespace osgViewer -{ - class Viewer; -} - namespace Resource { @@ -83,10 +78,9 @@ namespace Resource /// @param mask The node mask to apply to loaded particle system nodes. void setParticleSystemMask(unsigned int mask); - /// @param viewer used to apply the new filter settings to the existing scene graph. If there is no scene yet, you can pass a NULL viewer. + /// @warning It is unsafe to call this method while the draw thread is using textures! call Viewer::stopThreading first. void setFilterSettings(const std::string &magfilter, const std::string &minfilter, - const std::string &mipmap, int maxAnisotropy, - osgViewer::Viewer *viewer); + const std::string &mipmap, int maxAnisotropy); /// Apply filter settings to the given texture. Note, when loading an object through this scene manager (i.e. calling getTemplate or createInstance) /// the filter settings are applied automatically. This method is provided for textures that were created outside of the SceneManager. diff --git a/components/terrain/terraingrid.cpp b/components/terrain/terraingrid.cpp index 981a984e4..fefb0b8bc 100644 --- a/components/terrain/terraingrid.cpp +++ b/components/terrain/terraingrid.cpp @@ -175,7 +175,6 @@ osg::ref_ptr TerrainGrid::buildTerrain (osg::Group* parent, float chu texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); texture->setResizeNonPowerOfTwoHint(false); - texture->getOrCreateUserDataContainer()->addDescription("dont_override_filter"); blendmapTextures.push_back(texture); textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(dummyTextureCounter++, blendmapTextures.back()); @@ -278,4 +277,11 @@ void TerrainGrid::updateCache() } } +void TerrainGrid::updateTextureFiltering() +{ + OpenThreads::ScopedLock lock(mTextureCacheMutex); + for (TextureCache::iterator it = mTextureCache.begin(); it != mTextureCache.end(); ++it) + mResourceSystem->getSceneManager()->applyFilterSettings(it->second); +} + } diff --git a/components/terrain/terraingrid.hpp b/components/terrain/terraingrid.hpp index 46a95e817..d2276a0af 100644 --- a/components/terrain/terraingrid.hpp +++ b/components/terrain/terraingrid.hpp @@ -36,6 +36,10 @@ namespace Terrain /// @note Thread safe. void updateCache(); + /// Apply the scene manager's texture filtering settings to all cached textures. + /// @note Thread safe. + void updateTextureFiltering(); + private: osg::ref_ptr buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter); diff --git a/components/terrain/world.hpp b/components/terrain/world.hpp index 992438a6a..f5638750c 100644 --- a/components/terrain/world.hpp +++ b/components/terrain/world.hpp @@ -39,6 +39,8 @@ namespace Terrain Storage* storage, int nodeMask); virtual ~World(); + virtual void updateTextureFiltering() {} + virtual void updateCache() {} float getHeightAt (const osg::Vec3f& worldPos);