diff --git a/AUTHORS.md b/AUTHORS.md index 28a1a3a33a..65e9774676 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -24,6 +24,7 @@ Programmers Aleksandar Jovanov Alex Haddad (rainChu) Alex McKibben + Alexander Booher (Sleepy_wade) alexanderkjall Alexander Nadeau (wareya) Alexander Olofsson (Ananace) diff --git a/CHANGELOG.md b/CHANGELOG.md index 830ab93094..de68546426 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -309,6 +309,7 @@ Bug #8048: Actors can generate negative collision extents and have no collision Bug #8063: menu_background.bik video with audio freezes the game forever Bug #8064: Lua move360 script doesn't respect the enableZoom/disableZoom Camera interface setting + Bug #8083: Sun glare visible when underwater Bug #8085: Don't search in scripts or shaders directories for "Select directories you wish to add" menu in launcher Bug #8097: GetEffect doesn't detect 0 magnitude spells Bug #8099: Reaching Lua memory limit leads to a crash diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 244e1035ed..72b8f29644 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -543,6 +543,7 @@ namespace MWRender return; switchUnderwaterRain(); + switchUnderwaterSun(); if (mIsStorm && mParticleNode) { @@ -640,6 +641,14 @@ namespace MWRender mRainParticleSystem->setFrozen(freeze); } + void SkyManager::switchUnderwaterSun() + { + if (!mSun) + return; + bool underwater = mUnderwaterSwitch->isUnderwater(); + mSun->setUnderwater(underwater); + } + void SkyManager::setWeather(const WeatherResult& weather) { if (!mCreated) diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 6d33165c36..44d5853dce 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -112,6 +112,7 @@ namespace MWRender void createRain(); void destroyRain(); void switchUnderwaterRain(); + void switchUnderwaterSun(); void updateRainParameters(); Resource::SceneManager* mSceneManager; diff --git a/apps/openmw/mwrender/skyutil.cpp b/apps/openmw/mwrender/skyutil.cpp index dacf628a2c..3b631c4c53 100644 --- a/apps/openmw/mwrender/skyutil.cpp +++ b/apps/openmw/mwrender/skyutil.cpp @@ -133,47 +133,87 @@ namespace MWRender { } - float OcclusionCallback::getVisibleRatio(osg::Camera* camera) + float OcclusionCallback::getVisibleRatio(osg::Camera* camera, bool smooth) + { + float visibleRatio = updateVisibleRatio(camera); + float dt = MWBase::Environment::get().getFrameDuration(); + + if (smooth) + { + float lastRatio = mLastRatio[osg::observer_ptr(camera)]; + + float change = dt * 5; + + if (visibleRatio > lastRatio) + visibleRatio = std::min(visibleRatio, lastRatio + change); + else + visibleRatio = std::max(visibleRatio, lastRatio - change); + } + + mLastRatio[osg::observer_ptr(camera)] = visibleRatio; + return visibleRatio; + } + + OcclusionCallback::~OcclusionCallback() {} + + float OcclusionCallback::updateVisibleRatio(osg::Camera* camera) { int visible = mOcclusionQueryVisiblePixels->getQueryGeometry()->getNumPixels(camera); int total = mOcclusionQueryTotalPixels->getQueryGeometry()->getNumPixels(camera); - float visibleRatio = 0.f; + if (total > 0) visibleRatio = static_cast(visible) / static_cast(total); - float dt = MWBase::Environment::get().getFrameDuration(); - - float lastRatio = mLastRatio[osg::observer_ptr(camera)]; - - float change = dt * 10; - - if (visibleRatio > lastRatio) - visibleRatio = std::min(visibleRatio, lastRatio + change); - else - visibleRatio = std::max(visibleRatio, lastRatio - change); - - mLastRatio[osg::observer_ptr(camera)] = visibleRatio; - return visibleRatio; } + SunOcclusionCallback::SunOcclusionCallback( + osg::ref_ptr oqnVisible, osg::ref_ptr oqnTotal) + : OcclusionCallback(oqnVisible, oqnTotal) + , mUnderwater(false) + { + } + + SunOcclusionCallback::~SunOcclusionCallback() {} + + float SunOcclusionCallback::updateVisibleRatio(osg::Camera* camera) + { + if (mUnderwater) + { + return 0.0f; + } + return OcclusionCallback::updateVisibleRatio(camera); + } + + void SunOcclusionCallback::setUnderwater(bool underwater) + { + mUnderwater = underwater; + } + + bool SunOcclusionCallback::isUnderwater() + { + return mUnderwater; + } + /// SunFlashCallback handles fading/scaling of a node depending on occlusion query result. Must be attached as a /// cull callback. - class SunFlashCallback : public OcclusionCallback, + class SunFlashCallback : public SunOcclusionCallback, public SceneUtil::NodeCallback { public: SunFlashCallback( osg::ref_ptr oqnVisible, osg::ref_ptr oqnTotal) - : OcclusionCallback(std::move(oqnVisible), std::move(oqnTotal)) + : SunOcclusionCallback(std::move(oqnVisible), std::move(oqnTotal)) , mGlareView(1.f) { } + virtual ~SunFlashCallback() {} + void operator()(osg::Node* node, osgUtil::CullVisitor* cv) { - float visibleRatio = getVisibleRatio(cv->getCurrentCamera()); + float visibleRatio = getVisibleRatio(cv->getCurrentCamera(), !isUnderwater()); osg::ref_ptr stateset; @@ -232,13 +272,13 @@ namespace MWRender /// SunGlareCallback controls a full-screen glare effect depending on occlusion query result and the angle between /// sun and camera. Must be attached as a cull callback to the node above the glare node. - class SunGlareCallback : public OcclusionCallback, + class SunGlareCallback : public SunOcclusionCallback, public SceneUtil::NodeCallback { public: SunGlareCallback(osg::ref_ptr oqnVisible, osg::ref_ptr oqnTotal, osg::ref_ptr sunTransform) - : OcclusionCallback(std::move(oqnVisible), std::move(oqnTotal)) + : SunOcclusionCallback(std::move(oqnVisible), std::move(oqnTotal)) , mSunTransform(std::move(sunTransform)) , mTimeOfDayFade(1.f) , mGlareView(1.f) @@ -255,10 +295,12 @@ namespace MWRender mColor[i] = std::min(1.f, mColor[i]); } + virtual ~SunGlareCallback() {} + void operator()(osg::Node* node, osgUtil::CullVisitor* cv) { float angleRadians = getAngleToSunInRadians(*cv->getCurrentRenderStage()->getInitialViewMatrix()); - float visibleRatio = getVisibleRatio(cv->getCurrentCamera()); + float visibleRatio = getVisibleRatio(cv->getCurrentCamera(), !isUnderwater()); const float angleMaxRadians = osg::DegreesToRadians(mSunGlareFaderAngleMax); @@ -831,6 +873,14 @@ namespace MWRender mSunFlashCallback->setGlareView(ratio); } + void Sun::setUnderwater(bool underwater) + { + if (mSunFlashCallback) + mSunFlashCallback->setUnderwater(underwater); + if (mSunGlareCallback) + mSunGlareCallback->setUnderwater(underwater); + } + void Sun::setDirection(const osg::Vec3f& direction) { osg::Vec3f normalizedDirection = direction / direction.length(); diff --git a/apps/openmw/mwrender/skyutil.hpp b/apps/openmw/mwrender/skyutil.hpp index da038e6c58..5fabdd8cd0 100644 --- a/apps/openmw/mwrender/skyutil.hpp +++ b/apps/openmw/mwrender/skyutil.hpp @@ -113,17 +113,32 @@ namespace MWRender public: OcclusionCallback( osg::ref_ptr oqnVisible, osg::ref_ptr oqnTotal); + float getVisibleRatio(osg::Camera* camera, bool smooth); + virtual ~OcclusionCallback(); protected: - float getVisibleRatio(osg::Camera* camera); + virtual float updateVisibleRatio(osg::Camera* camera); private: osg::ref_ptr mOcclusionQueryVisiblePixels; osg::ref_ptr mOcclusionQueryTotalPixels; - std::map, float> mLastRatio; }; + class SunOcclusionCallback : public OcclusionCallback + { + public: + SunOcclusionCallback( + osg::ref_ptr oqnVisible, osg::ref_ptr oqnTotal); + virtual ~SunOcclusionCallback(); + virtual float updateVisibleRatio(osg::Camera* camera) override; + void setUnderwater(bool underwater); + bool isUnderwater(); + + private: + bool mUnderwater; + }; + class AtmosphereUpdater : public SceneUtil::StateSetUpdater { public: @@ -249,7 +264,7 @@ namespace MWRender void setColor(const osg::Vec4f& color); void adjustTransparency(const float ratio) override; - + void setUnderwater(bool underwater); void setDirection(const osg::Vec3f& direction); void setGlareTimeOfDayFade(float val); void setSunglare(bool enabled);