From 4afc332a0ccc07db0d737a8d57f966d4a2b826fd Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 7 Jun 2020 10:35:33 +0400 Subject: [PATCH] Add a FogManager --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwrender/fogmanager.cpp | 104 ++++++++++++++++++++++ apps/openmw/mwrender/fogmanager.hpp | 39 ++++++++ apps/openmw/mwrender/renderingmanager.cpp | 86 +++--------------- apps/openmw/mwrender/renderingmanager.hpp | 14 +-- 5 files changed, 157 insertions(+), 88 deletions(-) create mode 100644 apps/openmw/mwrender/fogmanager.cpp create mode 100644 apps/openmw/mwrender/fogmanager.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index a6b68df86..99bd1c2cd 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -21,7 +21,7 @@ add_openmw_dir (mwrender actors objects renderingmanager animation rotatecontroller sky npcanimation vismask creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation - renderbin actoranimation landmanager navmesh actorspaths recastmesh + renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager ) add_openmw_dir (mwinput diff --git a/apps/openmw/mwrender/fogmanager.cpp b/apps/openmw/mwrender/fogmanager.cpp new file mode 100644 index 000000000..837e6ad04 --- /dev/null +++ b/apps/openmw/mwrender/fogmanager.cpp @@ -0,0 +1,104 @@ +#include "fogmanager.hpp" + +#include + +#include +#include +#include +#include + +namespace +{ + float DLLandFogStart; + float DLLandFogEnd; + float DLUnderwaterFogStart; + float DLUnderwaterFogEnd; + float DLInteriorFogStart; + float DLInteriorFogEnd; +} + +namespace MWRender +{ + FogManager::FogManager() + : mLandFogStart(0.f) + , mLandFogEnd(std::numeric_limits::max()) + , mUnderwaterFogStart(0.f) + , mUnderwaterFogEnd(std::numeric_limits::max()) + , mFogColor(osg::Vec4f()) + , mDistantFog(Settings::Manager::getBool("use distant fog", "Fog")) + , mUnderwaterColor(Fallback::Map::getColour("Water_UnderwaterColor")) + , mUnderwaterWeight(Fallback::Map::getFloat("Water_UnderwaterColorWeight")) + , mUnderwaterIndoorFog(Fallback::Map::getFloat("Water_UnderwaterIndoorFog")) + { + DLLandFogStart = Settings::Manager::getFloat("distant land fog start", "Fog"); + DLLandFogEnd = Settings::Manager::getFloat("distant land fog end", "Fog"); + DLUnderwaterFogStart = Settings::Manager::getFloat("distant underwater fog start", "Fog"); + DLUnderwaterFogEnd = Settings::Manager::getFloat("distant underwater fog end", "Fog"); + DLInteriorFogStart = Settings::Manager::getFloat("distant interior fog start", "Fog"); + DLInteriorFogEnd = Settings::Manager::getFloat("distant interior fog end", "Fog"); + } + + void FogManager::configure(float viewDistance, const ESM::Cell *cell) + { + osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog); + + if (mDistantFog) + { + float density = std::max(0.2f, cell->mAmbi.mFogDensity); + mLandFogStart = DLInteriorFogEnd * (1.0f - density) + DLInteriorFogStart*density; + mLandFogEnd = DLInteriorFogEnd; + mUnderwaterFogStart = DLUnderwaterFogStart; + mUnderwaterFogEnd = DLUnderwaterFogEnd; + mFogColor = color; + } + else + configure(viewDistance, cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, 1.0f, 0.0f, color); + } + + void FogManager::configure(float viewDistance, float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f &color) + { + if (mDistantFog) + { + mLandFogStart = dlFactor * (DLLandFogStart - dlOffset * DLLandFogEnd); + mLandFogEnd = dlFactor * (1.0f - dlOffset) * DLLandFogEnd; + mUnderwaterFogStart = DLUnderwaterFogStart; + mUnderwaterFogEnd = DLUnderwaterFogEnd; + } + else + { + if (fogDepth == 0.0) + { + mLandFogStart = 0.0f; + mLandFogEnd = std::numeric_limits::max(); + } + else + { + mLandFogStart = viewDistance * (1 - fogDepth); + mLandFogEnd = viewDistance; + } + mUnderwaterFogStart = std::min(viewDistance, 6666.f) * (1 - underwaterFog); + mUnderwaterFogEnd = std::min(viewDistance, 6666.f); + } + mFogColor = color; + } + + float FogManager::getFogStart(bool isUnderwater) const + { + return isUnderwater ? mUnderwaterFogStart : mLandFogStart; + } + + float FogManager::getFogEnd(bool isUnderwater) const + { + return isUnderwater ? mUnderwaterFogEnd : mLandFogEnd; + } + + osg::Vec4f FogManager::getFogColor(bool isUnderwater) const + { + if (isUnderwater) + { + return mUnderwaterColor * mUnderwaterWeight + mFogColor * (1.f-mUnderwaterWeight); + } + + return mFogColor; + } +} diff --git a/apps/openmw/mwrender/fogmanager.hpp b/apps/openmw/mwrender/fogmanager.hpp new file mode 100644 index 000000000..c3efd06ab --- /dev/null +++ b/apps/openmw/mwrender/fogmanager.hpp @@ -0,0 +1,39 @@ +#ifndef OPENMW_MWRENDER_FOGMANAGER_H +#define OPENMW_MWRENDER_FOGMANAGER_H + +#include + +namespace ESM +{ + struct Cell; +} + +namespace MWRender +{ + class FogManager + { + public: + FogManager(); + + void configure(float viewDistance, const ESM::Cell *cell); + void configure(float viewDistance, float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f &color); + + osg::Vec4f getFogColor(bool isUnderwater) const; + float getFogStart(bool isUnderwater) const; + float getFogEnd(bool isUnderwater) const; + + private: + float mLandFogStart; + float mLandFogEnd; + float mUnderwaterFogStart; + float mUnderwaterFogEnd; + osg::Vec4f mFogColor; + bool mDistantFog; + + osg::Vec4f mUnderwaterColor; + float mUnderwaterWeight; + float mUnderwaterIndoorFog; + }; +} + +#endif diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 3eb71db03..462f9fbb6 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -69,16 +69,7 @@ #include "navmesh.hpp" #include "actorspaths.hpp" #include "recastmesh.hpp" - -namespace -{ - float DLLandFogStart; - float DLLandFogEnd; - float DLUnderwaterFogStart; - float DLUnderwaterFogEnd; - float DLInteriorFogStart; - float DLInteriorFogEnd; -} +#include "fogmanager.hpp" namespace MWRender { @@ -204,15 +195,7 @@ namespace MWRender , mWorkQueue(workQueue) , mUnrefQueue(new SceneUtil::UnrefQueue) , mNavigator(navigator) - , mLandFogStart(0.f) - , mLandFogEnd(std::numeric_limits::max()) - , mUnderwaterFogStart(0.f) - , mUnderwaterFogEnd(std::numeric_limits::max()) - , mUnderwaterColor(Fallback::Map::getColour("Water_UnderwaterColor")) - , mUnderwaterWeight(Fallback::Map::getFloat("Water_UnderwaterColorWeight")) - , mUnderwaterIndoorFog(Fallback::Map::getFloat("Water_UnderwaterIndoorFog")) , mNightEyeFactor(0.f) - , mDistantFog(false) , mFieldOfViewOverridden(false) , mFieldOfViewOverride(0.f) { @@ -282,14 +265,6 @@ namespace MWRender mEffectManager.reset(new EffectManager(sceneRoot, mResourceSystem)); - DLLandFogStart = Settings::Manager::getFloat("distant land fog start", "Fog"); - DLLandFogEnd = Settings::Manager::getFloat("distant land fog end", "Fog"); - DLUnderwaterFogStart = Settings::Manager::getFloat("distant underwater fog start", "Fog"); - DLUnderwaterFogEnd = Settings::Manager::getFloat("distant underwater fog end", "Fog"); - DLInteriorFogStart = Settings::Manager::getFloat("distant interior fog start", "Fog"); - DLInteriorFogEnd = Settings::Manager::getFloat("distant interior fog end", "Fog"); - mDistantFog = Settings::Manager::getBool("use distant fog", "Fog"); - const std::string normalMapPattern = Settings::Manager::getString("normal map pattern", "Shaders"); const std::string heightMapPattern = Settings::Manager::getString("normal height map pattern", "Shaders"); const std::string specularMapPattern = Settings::Manager::getString("terrain specular map pattern", "Shaders"); @@ -345,8 +320,9 @@ namespace MWRender defaultMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f)); sceneRoot->getOrCreateStateSet()->setAttribute(defaultMat); - mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager())); + mFog.reset(new FogManager()); + mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager())); mSky->setCamera(mViewer->getCamera()); mSky->setRainIntensityUniform(mWater->getRainIntensityUniform()); @@ -602,46 +578,12 @@ namespace MWRender void RenderingManager::configureFog(const ESM::Cell *cell) { - osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog); - - if(mDistantFog) - { - float density = std::max(0.2f, cell->mAmbi.mFogDensity); - mLandFogStart = (DLInteriorFogEnd*(1.0f-density) + DLInteriorFogStart*density); - mLandFogEnd = DLInteriorFogEnd; - mUnderwaterFogStart = DLUnderwaterFogStart; - mUnderwaterFogEnd = DLUnderwaterFogEnd; - mFogColor = color; - } - else - configureFog(cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, 1.0f, 0.0f, color); + mFog->configure(mViewDistance, cell); } void RenderingManager::configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f &color) { - if(mDistantFog) - { - mLandFogStart = dlFactor * (DLLandFogStart - dlOffset*DLLandFogEnd); - mLandFogEnd = dlFactor * (1.0f-dlOffset) * DLLandFogEnd; - mUnderwaterFogStart = DLUnderwaterFogStart; - mUnderwaterFogEnd = DLUnderwaterFogEnd; - } - else - { - if(fogDepth == 0.0) - { - mLandFogStart = 0.0f; - mLandFogEnd = std::numeric_limits::max(); - } - else - { - mLandFogStart = mViewDistance * (1 - fogDepth); - mLandFogEnd = mViewDistance; - } - mUnderwaterFogStart = std::min(mViewDistance, 6666.f) * (1 - underwaterFog); - mUnderwaterFogEnd = std::min(mViewDistance, 6666.f); - } - mFogColor = color; + mFog->configure(mViewDistance, fogDepth, underwaterFog, dlFactor, dlOffset, color); } SkyManager* RenderingManager::getSkyManager() @@ -670,19 +612,11 @@ namespace MWRender osg::Vec3f focal, cameraPos; mCamera->getPosition(focal, cameraPos); mCurrentCameraPos = cameraPos; - if (mWater->isUnderwater(cameraPos)) - { - setFogColor(mUnderwaterColor * mUnderwaterWeight + mFogColor * (1.f-mUnderwaterWeight)); - mStateUpdater->setFogStart(mUnderwaterFogStart); - mStateUpdater->setFogEnd(mUnderwaterFogEnd); - } - else - { - setFogColor(mFogColor); - mStateUpdater->setFogStart(mLandFogStart); - mStateUpdater->setFogEnd(mLandFogEnd); - } + bool isUnderwater = mWater->isUnderwater(cameraPos); + mStateUpdater->setFogStart(mFog->getFogStart(isUnderwater)); + mStateUpdater->setFogEnd(mFog->getFogEnd(isUnderwater)); + setFogColor(mFog->getFogColor(isUnderwater)); } void RenderingManager::updatePlayerPtr(const MWWorld::Ptr &ptr) @@ -1331,7 +1265,7 @@ namespace MWRender else if (it->first == "Camera" && it->second == "viewing distance") { mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera"); - if(!mDistantFog) + if(!Settings::Manager::getBool("use distant fog", "Fog")) mStateUpdater->setFogEnd(mViewDistance); updateProjectionMatrix(); } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 30826fb38..13f09b359 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -73,6 +73,7 @@ namespace MWRender class StateUpdater; class EffectManager; + class FogManager; class SkyManager; class NpcAnimation; class Pathgrid; @@ -275,6 +276,7 @@ namespace MWRender std::unique_ptr mTerrain; TerrainStorage* mTerrainStorage; std::unique_ptr mSky; + std::unique_ptr mFog; std::unique_ptr mEffectManager; std::unique_ptr mShadowManager; osg::ref_ptr mPlayerAnimation; @@ -284,22 +286,12 @@ namespace MWRender osg::ref_ptr mStateUpdater; - float mLandFogStart; - float mLandFogEnd; - float mUnderwaterFogStart; - float mUnderwaterFogEnd; - osg::Vec4f mUnderwaterColor; - float mUnderwaterWeight; - float mUnderwaterIndoorFog; - osg::Vec4f mFogColor; - osg::Vec4f mAmbientColor; float mNightEyeFactor; float mNearClip; float mViewDistance; - bool mDistantFog : 1; - bool mFieldOfViewOverridden : 1; + bool mFieldOfViewOverridden; float mFieldOfViewOverride; float mFieldOfView; float mFirstPersonFieldOfView;