diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index b880943a4..ea0fef197 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -51,6 +51,20 @@ #include "terrainstorage.hpp" #include "util.hpp" +namespace +{ + // These values are what MGE XE uses by default when distant land is enabled, and are specified + // in cells (8192 units each). Should make them settings somewhere? Or wait to expose them + // "properly"? + const float DLRenderDistance = 5.0f; + const float DLLandFogStart = 2.0f; + const float DLLandFogEnd = 5.0f; + const float DLUnderwaterFogStart = -0.5f; + const float DLUnderwaterFogEnd = 0.3f; + const float DLInteriorFogStart = 0.0f; + const float DLInteriorFogEnd = 2.0f; +} + namespace MWRender { @@ -173,10 +187,12 @@ namespace MWRender , mResourceSystem(resourceSystem) , mWorkQueue(workQueue) , mUnrefQueue(new SceneUtil::UnrefQueue) - , mFogDepth(0.f) + , mLandFogStart(0.f) + , mLandFogEnd(std::numeric_limits::max()) + , mUnderwaterFogStart(0.f) + , mUnderwaterFogEnd(std::numeric_limits::max()) , mUnderwaterColor(fallback->getFallbackColour("Water_UnderwaterColor")) , mUnderwaterWeight(fallback->getFallbackFloat("Water_UnderwaterColorWeight")) - , mUnderwaterFog(0.f) , mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog")) , mNightEyeFactor(0.f) , mDistantTerrain(false) @@ -289,7 +305,7 @@ namespace MWRender mFirstPersonFieldOfView = Settings::Manager::getFloat("first person field of view", "Camera"); mStateUpdater->setFogEnd(mViewDistance); - mFarClip = mDistantTerrain ? 8192.0f*5.0f : mViewDistance; + mFarClip = mDistantTerrain ? DLRenderDistance*8192.0f : mViewDistance; mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip)); mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mFarClip)); @@ -482,14 +498,44 @@ namespace MWRender { osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog); - configureFog (cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, color); + if(mDistantTerrain) + { + float density = std::max(0.2f, cell->mAmbi.mFogDensity); + mLandFogStart = (DLInteriorFogEnd*(1.0f-density) + DLInteriorFogStart*density) * 8192.0f; + mLandFogEnd = DLInteriorFogEnd * 8192.0f; + mUnderwaterFogStart = DLUnderwaterFogStart * 8192.0f; + mUnderwaterFogEnd = DLUnderwaterFogEnd * 8192.0f; + mFogColor = color; + } + else + configureFog(cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, 1.0f, 0.0f, color); } - void RenderingManager::configureFog(float fogDepth, float underwaterFog, const osg::Vec4f &color) + void RenderingManager::configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f &color) { - mFogDepth = fogDepth; + if(mDistantTerrain) + { + mLandFogStart = dlFactor * (DLLandFogStart - dlOffset*DLLandFogEnd) * 8192.0f; + mLandFogEnd = dlFactor * (1.0f-dlOffset) * DLLandFogEnd * 8192.0f; + mUnderwaterFogStart = DLUnderwaterFogStart * 8192.0f; + mUnderwaterFogEnd = DLUnderwaterFogEnd * 8192.0f; + } + else + { + if(fogDepth == 0.0) + { + mLandFogStart = 0.0f; + mLandFogEnd = std::numeric_limits::max(); + } + else + { + mLandFogStart = mViewDistance * (1 - fogDepth); + mLandFogEnd = mViewDistance; + } + mUnderwaterFogStart = mViewDistance * (1 - underwaterFog); + mUnderwaterFogEnd = mViewDistance; + } mFogColor = color; - mUnderwaterFog = underwaterFog; } SkyManager* RenderingManager::getSkyManager() @@ -520,23 +566,15 @@ namespace MWRender float viewDistance = mViewDistance; viewDistance = std::min(viewDistance, 6666.f); setFogColor(mUnderwaterColor * mUnderwaterWeight + mFogColor * (1.f-mUnderwaterWeight)); - mStateUpdater->setFogStart(viewDistance * (1 - mUnderwaterFog)); - mStateUpdater->setFogEnd(viewDistance); + mStateUpdater->setFogStart(mUnderwaterFogStart); + mStateUpdater->setFogEnd(mUnderwaterFogEnd); } else { setFogColor(mFogColor); - if (mFogDepth == 0.f) - { - mStateUpdater->setFogStart(0.f); - mStateUpdater->setFogEnd(std::numeric_limits::max()); - } - else - { - mStateUpdater->setFogStart(mViewDistance * (1 - mFogDepth)); - mStateUpdater->setFogEnd(mViewDistance); - } + mStateUpdater->setFogStart(mLandFogStart); + mStateUpdater->setFogEnd(mLandFogEnd); } } @@ -963,9 +1001,12 @@ namespace MWRender else if (it->first == "Camera" && it->second == "viewing distance") { mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera"); - mFarClip = mDistantTerrain ? 8192.0f*5.0f : mViewDistance; - mStateUpdater->setFogEnd(mViewDistance); - updateProjectionMatrix(); + if(!mDistantTerrain) + { + mFarClip = mViewDistance; + mStateUpdater->setFogEnd(mViewDistance); + updateProjectionMatrix(); + } } else if (it->first == "General" && (it->second == "texture filter" || it->second == "texture mipmap" || diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 16854aaea..d44266e97 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -106,7 +106,7 @@ namespace MWRender void configureAmbient(const ESM::Cell* cell); void configureFog(const ESM::Cell* cell); - void configureFog(float fogDepth, float underwaterFog, const osg::Vec4f& colour); + void configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f& colour); void addCell(const MWWorld::CellStore* store); void removeCell(const MWWorld::CellStore* store); @@ -241,10 +241,12 @@ namespace MWRender osg::ref_ptr mStateUpdater; - float mFogDepth; + float mLandFogStart; + float mLandFogEnd; + float mUnderwaterFogStart; + float mUnderwaterFogEnd; osg::Vec4f mUnderwaterColor; float mUnderwaterWeight; - float mUnderwaterFog; float mUnderwaterIndoorFog; osg::Vec4f mFogColor; diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 4357d468c..a9345cdb4 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -65,6 +65,9 @@ namespace MWRender float mFogDepth; + float mDLFogFactor; + float mDLFogOffset; + float mWindSpeed; float mCloudSpeed; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 2f0a2f8cf..bde4c4c22 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -103,6 +103,8 @@ Weather::Weather(const std::string& name, const Fallback::Map& fallback, float stormWindSpeed, float rainSpeed, + float dlFactor, + float dlOffset, const std::string& particleEffect) : mCloudTexture(fallback.getFallbackString("Weather_" + name + "_Cloud_Texture")) , mSkyColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"), @@ -129,6 +131,7 @@ Weather::Weather(const std::string& name, , mWindSpeed(fallback.getFallbackFloat("Weather_" + name + "_Wind_Speed")) , mCloudSpeed(fallback.getFallbackFloat("Weather_" + name + "_Cloud_Speed")) , mGlareView(fallback.getFallbackFloat("Weather_" + name + "_Glare_View")) + , mDL{dlFactor, dlOffset} , mIsStorm(mWindSpeed > stormWindSpeed) , mRainSpeed(rainSpeed) , mRainFrequency(fallback.getFallbackFloat("Weather_" + name + "_Rain_Entrance_Speed")) @@ -541,16 +544,18 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const Fall mTimeSettings.mSunriseTime = mSunriseTime; mWeatherSettings.reserve(10); - addWeather("Clear", fallback); // 0 - addWeather("Cloudy", fallback); // 1 - addWeather("Foggy", fallback); // 2 - addWeather("Overcast", fallback); // 3 - addWeather("Rain", fallback); // 4 - addWeather("Thunderstorm", fallback); // 5 - addWeather("Ashstorm", fallback, "meshes\\ashcloud.nif"); // 6 - addWeather("Blight", fallback, "meshes\\blightcloud.nif"); // 7 - addWeather("Snow", fallback, "meshes\\snow.nif"); // 8 - addWeather("Blizzard", fallback, "meshes\\blizzard.nif"); // 9 + // These distant land fog factor and offset values are the defaults MGE XE provides. Should be + // provided by settings somewhere? + addWeather("Clear", fallback, 1.0f, 0.0f); // 0 + addWeather("Cloudy", fallback, 0.9f, 0.0f); // 1 + addWeather("Foggy", fallback, 0.2f, 30.0f); // 2 + addWeather("Overcast", fallback, 0.7f, 0.0f); // 3 + addWeather("Rain", fallback, 0.5f, 10.0f); // 4 + addWeather("Thunderstorm", fallback, 0.5f, 20.0f); // 5 + addWeather("Ashstorm", fallback, 0.2f, 50.0f, "meshes\\ashcloud.nif"); // 6 + addWeather("Blight", fallback, 0.2f, 60.0f, "meshes\\blightcloud.nif"); // 7 + addWeather("Snow", fallback, 0.5f, 40.0f, "meshes\\snow.nif"); // 8 + addWeather("Blizzard", fallback, 0.16f, 70.0f, "meshes\\blizzard.nif"); // 9 Store::iterator it = store.get().begin(); for(; it != store.get().end(); ++it) @@ -720,7 +725,8 @@ void WeatherManager::update(float duration, bool paused) mRendering.getSkyManager()->setMasserState(mMasser.calculateState(time)); mRendering.getSkyManager()->setSecundaState(mSecunda.calculateState(time)); - mRendering.configureFog(mResult.mFogDepth, underwaterFog, mResult.mFogColor); + mRendering.configureFog(mResult.mFogDepth, underwaterFog, mResult.mDLFogFactor, + mResult.mDLFogOffset/100.0f, mResult.mFogColor); mRendering.setAmbientColour(mResult.mAmbientColor); mRendering.setSunColour(mResult.mSunColor, mResult.mSunColor * mResult.mGlareView); @@ -866,11 +872,12 @@ void WeatherManager::clear() inline void WeatherManager::addWeather(const std::string& name, const Fallback::Map& fallback, + float dlFactor, float dlOffset, const std::string& particleEffect) { static const float fStromWindSpeed = mStore.get().find("fStromWindSpeed")->getFloat(); - Weather weather(name, fallback, fStromWindSpeed, mRainSpeed, particleEffect); + Weather weather(name, fallback, fStromWindSpeed, mRainSpeed, dlFactor, dlOffset, particleEffect); mWeatherSettings.push_back(weather); } @@ -1058,6 +1065,8 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam mResult.mNight = (gameHour < mSunriseTime || gameHour > mTimeSettings.mNightStart - 1); mResult.mFogDepth = current.mLandFogDepth.getValue(gameHour, mTimeSettings); + mResult.mDLFogFactor = current.mDL.FogFactor; + mResult.mDLFogOffset = current.mDL.FogOffset; mResult.mFogColor = current.mFogColor.getValue(gameHour, mTimeSettings); mResult.mAmbientColor = current.mAmbientColor.getValue(gameHour, mTimeSettings); mResult.mSunColor = current.mSunColor.getValue(gameHour, mTimeSettings); @@ -1113,6 +1122,8 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const mResult.mAmbientColor = lerp(current.mAmbientColor, other.mAmbientColor, factor); mResult.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor, factor); mResult.mFogDepth = lerp(current.mFogDepth, other.mFogDepth, factor); + mResult.mDLFogFactor = lerp(current.mDLFogFactor, other.mDLFogFactor, factor); + mResult.mDLFogOffset = lerp(current.mDLFogOffset, other.mDLFogOffset, factor); mResult.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed, factor); mResult.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed, factor); mResult.mGlareView = lerp(current.mGlareView, other.mGlareView, factor); diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 84a6c5105..4555a9d2a 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -73,6 +73,8 @@ namespace MWWorld const Fallback::Map& fallback, float stormWindSpeed, float rainSpeed, + float dlFactor, + float dlOffset, const std::string& particleEffect); std::string mCloudTexture; @@ -102,6 +104,12 @@ namespace MWWorld // Also appears to modify how visible the sun, moons, and stars are for various weather effects. float mGlareView; + // Fog factor and offset used with distant land rendering. + struct { + float FogFactor; + float FogOffset; + } mDL; + // Sound effect // This is used for Blight, Ashstorm and Blizzard (Bloodmoon) std::string mAmbientLoopSoundID; @@ -293,6 +301,7 @@ namespace MWWorld void addWeather(const std::string& name, const Fallback::Map& fallback, + float dlFactor, float dlOffset, const std::string& particleEffect = ""); void importRegions();