mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-08-03 15:27:13 -04:00
Merge branch 'underwater_sun' into 'master'
Fix sun flash and glare rendering underwater (#8083) See merge request OpenMW/openmw!4388
This commit is contained in:
commit
c39d9490d6
@ -24,6 +24,7 @@ Programmers
|
|||||||
Aleksandar Jovanov
|
Aleksandar Jovanov
|
||||||
Alex Haddad (rainChu)
|
Alex Haddad (rainChu)
|
||||||
Alex McKibben
|
Alex McKibben
|
||||||
|
Alexander Booher (Sleepy_wade)
|
||||||
alexanderkjall
|
alexanderkjall
|
||||||
Alexander Nadeau (wareya)
|
Alexander Nadeau (wareya)
|
||||||
Alexander Olofsson (Ananace)
|
Alexander Olofsson (Ananace)
|
||||||
|
@ -286,6 +286,7 @@
|
|||||||
Bug #8048: Actors can generate negative collision extents and have no collision
|
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 #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 #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 #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 #8097: GetEffect doesn't detect 0 magnitude spells
|
||||||
Bug #8099: Reaching Lua memory limit leads to a crash
|
Bug #8099: Reaching Lua memory limit leads to a crash
|
||||||
|
@ -543,6 +543,7 @@ namespace MWRender
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
switchUnderwaterRain();
|
switchUnderwaterRain();
|
||||||
|
switchUnderwaterSun();
|
||||||
|
|
||||||
if (mIsStorm && mParticleNode)
|
if (mIsStorm && mParticleNode)
|
||||||
{
|
{
|
||||||
@ -640,6 +641,14 @@ namespace MWRender
|
|||||||
mRainParticleSystem->setFrozen(freeze);
|
mRainParticleSystem->setFrozen(freeze);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkyManager::switchUnderwaterSun()
|
||||||
|
{
|
||||||
|
if (!mSun)
|
||||||
|
return;
|
||||||
|
bool underwater = mUnderwaterSwitch->isUnderwater();
|
||||||
|
mSun->setUnderwater(underwater);
|
||||||
|
}
|
||||||
|
|
||||||
void SkyManager::setWeather(const WeatherResult& weather)
|
void SkyManager::setWeather(const WeatherResult& weather)
|
||||||
{
|
{
|
||||||
if (!mCreated)
|
if (!mCreated)
|
||||||
|
@ -112,6 +112,7 @@ namespace MWRender
|
|||||||
void createRain();
|
void createRain();
|
||||||
void destroyRain();
|
void destroyRain();
|
||||||
void switchUnderwaterRain();
|
void switchUnderwaterRain();
|
||||||
|
void switchUnderwaterSun();
|
||||||
void updateRainParameters();
|
void updateRainParameters();
|
||||||
|
|
||||||
Resource::SceneManager* mSceneManager;
|
Resource::SceneManager* mSceneManager;
|
||||||
|
@ -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<osg::Camera>(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<osg::Camera>(camera)] = visibleRatio;
|
||||||
|
return visibleRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
OcclusionCallback::~OcclusionCallback() {}
|
||||||
|
|
||||||
|
float OcclusionCallback::updateVisibleRatio(osg::Camera* camera)
|
||||||
{
|
{
|
||||||
int visible = mOcclusionQueryVisiblePixels->getQueryGeometry()->getNumPixels(camera);
|
int visible = mOcclusionQueryVisiblePixels->getQueryGeometry()->getNumPixels(camera);
|
||||||
int total = mOcclusionQueryTotalPixels->getQueryGeometry()->getNumPixels(camera);
|
int total = mOcclusionQueryTotalPixels->getQueryGeometry()->getNumPixels(camera);
|
||||||
|
|
||||||
float visibleRatio = 0.f;
|
float visibleRatio = 0.f;
|
||||||
|
|
||||||
if (total > 0)
|
if (total > 0)
|
||||||
visibleRatio = static_cast<float>(visible) / static_cast<float>(total);
|
visibleRatio = static_cast<float>(visible) / static_cast<float>(total);
|
||||||
|
|
||||||
float dt = MWBase::Environment::get().getFrameDuration();
|
|
||||||
|
|
||||||
float lastRatio = mLastRatio[osg::observer_ptr<osg::Camera>(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<osg::Camera>(camera)] = visibleRatio;
|
|
||||||
|
|
||||||
return visibleRatio;
|
return visibleRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SunOcclusionCallback::SunOcclusionCallback(
|
||||||
|
osg::ref_ptr<osg::OcclusionQueryNode> oqnVisible, osg::ref_ptr<osg::OcclusionQueryNode> 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
|
/// SunFlashCallback handles fading/scaling of a node depending on occlusion query result. Must be attached as a
|
||||||
/// cull callback.
|
/// cull callback.
|
||||||
class SunFlashCallback : public OcclusionCallback,
|
class SunFlashCallback : public SunOcclusionCallback,
|
||||||
public SceneUtil::NodeCallback<SunFlashCallback, osg::Node*, osgUtil::CullVisitor*>
|
public SceneUtil::NodeCallback<SunFlashCallback, osg::Node*, osgUtil::CullVisitor*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SunFlashCallback(
|
SunFlashCallback(
|
||||||
osg::ref_ptr<osg::OcclusionQueryNode> oqnVisible, osg::ref_ptr<osg::OcclusionQueryNode> oqnTotal)
|
osg::ref_ptr<osg::OcclusionQueryNode> oqnVisible, osg::ref_ptr<osg::OcclusionQueryNode> oqnTotal)
|
||||||
: OcclusionCallback(std::move(oqnVisible), std::move(oqnTotal))
|
: SunOcclusionCallback(std::move(oqnVisible), std::move(oqnTotal))
|
||||||
, mGlareView(1.f)
|
, mGlareView(1.f)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~SunFlashCallback() {}
|
||||||
|
|
||||||
void operator()(osg::Node* node, osgUtil::CullVisitor* cv)
|
void operator()(osg::Node* node, osgUtil::CullVisitor* cv)
|
||||||
{
|
{
|
||||||
float visibleRatio = getVisibleRatio(cv->getCurrentCamera());
|
float visibleRatio = getVisibleRatio(cv->getCurrentCamera(), !isUnderwater());
|
||||||
|
|
||||||
osg::ref_ptr<osg::StateSet> stateset;
|
osg::ref_ptr<osg::StateSet> stateset;
|
||||||
|
|
||||||
@ -232,13 +272,13 @@ namespace MWRender
|
|||||||
|
|
||||||
/// SunGlareCallback controls a full-screen glare effect depending on occlusion query result and the angle between
|
/// 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.
|
/// 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<SunGlareCallback, osg::Node*, osgUtil::CullVisitor*>
|
public SceneUtil::NodeCallback<SunGlareCallback, osg::Node*, osgUtil::CullVisitor*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SunGlareCallback(osg::ref_ptr<osg::OcclusionQueryNode> oqnVisible,
|
SunGlareCallback(osg::ref_ptr<osg::OcclusionQueryNode> oqnVisible,
|
||||||
osg::ref_ptr<osg::OcclusionQueryNode> oqnTotal, osg::ref_ptr<osg::PositionAttitudeTransform> sunTransform)
|
osg::ref_ptr<osg::OcclusionQueryNode> oqnTotal, osg::ref_ptr<osg::PositionAttitudeTransform> sunTransform)
|
||||||
: OcclusionCallback(std::move(oqnVisible), std::move(oqnTotal))
|
: SunOcclusionCallback(std::move(oqnVisible), std::move(oqnTotal))
|
||||||
, mSunTransform(std::move(sunTransform))
|
, mSunTransform(std::move(sunTransform))
|
||||||
, mTimeOfDayFade(1.f)
|
, mTimeOfDayFade(1.f)
|
||||||
, mGlareView(1.f)
|
, mGlareView(1.f)
|
||||||
@ -255,10 +295,12 @@ namespace MWRender
|
|||||||
mColor[i] = std::min(1.f, mColor[i]);
|
mColor[i] = std::min(1.f, mColor[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~SunGlareCallback() {}
|
||||||
|
|
||||||
void operator()(osg::Node* node, osgUtil::CullVisitor* cv)
|
void operator()(osg::Node* node, osgUtil::CullVisitor* cv)
|
||||||
{
|
{
|
||||||
float angleRadians = getAngleToSunInRadians(*cv->getCurrentRenderStage()->getInitialViewMatrix());
|
float angleRadians = getAngleToSunInRadians(*cv->getCurrentRenderStage()->getInitialViewMatrix());
|
||||||
float visibleRatio = getVisibleRatio(cv->getCurrentCamera());
|
float visibleRatio = getVisibleRatio(cv->getCurrentCamera(), !isUnderwater());
|
||||||
|
|
||||||
const float angleMaxRadians = osg::DegreesToRadians(mSunGlareFaderAngleMax);
|
const float angleMaxRadians = osg::DegreesToRadians(mSunGlareFaderAngleMax);
|
||||||
|
|
||||||
@ -831,6 +873,14 @@ namespace MWRender
|
|||||||
mSunFlashCallback->setGlareView(ratio);
|
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)
|
void Sun::setDirection(const osg::Vec3f& direction)
|
||||||
{
|
{
|
||||||
osg::Vec3f normalizedDirection = direction / direction.length();
|
osg::Vec3f normalizedDirection = direction / direction.length();
|
||||||
|
@ -113,17 +113,32 @@ namespace MWRender
|
|||||||
public:
|
public:
|
||||||
OcclusionCallback(
|
OcclusionCallback(
|
||||||
osg::ref_ptr<osg::OcclusionQueryNode> oqnVisible, osg::ref_ptr<osg::OcclusionQueryNode> oqnTotal);
|
osg::ref_ptr<osg::OcclusionQueryNode> oqnVisible, osg::ref_ptr<osg::OcclusionQueryNode> oqnTotal);
|
||||||
|
float getVisibleRatio(osg::Camera* camera, bool smooth);
|
||||||
|
virtual ~OcclusionCallback();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float getVisibleRatio(osg::Camera* camera);
|
virtual float updateVisibleRatio(osg::Camera* camera);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<osg::OcclusionQueryNode> mOcclusionQueryVisiblePixels;
|
osg::ref_ptr<osg::OcclusionQueryNode> mOcclusionQueryVisiblePixels;
|
||||||
osg::ref_ptr<osg::OcclusionQueryNode> mOcclusionQueryTotalPixels;
|
osg::ref_ptr<osg::OcclusionQueryNode> mOcclusionQueryTotalPixels;
|
||||||
|
|
||||||
std::map<osg::observer_ptr<osg::Camera>, float> mLastRatio;
|
std::map<osg::observer_ptr<osg::Camera>, float> mLastRatio;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SunOcclusionCallback : public OcclusionCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SunOcclusionCallback(
|
||||||
|
osg::ref_ptr<osg::OcclusionQueryNode> oqnVisible, osg::ref_ptr<osg::OcclusionQueryNode> oqnTotal);
|
||||||
|
virtual ~SunOcclusionCallback();
|
||||||
|
virtual float updateVisibleRatio(osg::Camera* camera) override;
|
||||||
|
void setUnderwater(bool underwater);
|
||||||
|
bool isUnderwater();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mUnderwater;
|
||||||
|
};
|
||||||
|
|
||||||
class AtmosphereUpdater : public SceneUtil::StateSetUpdater
|
class AtmosphereUpdater : public SceneUtil::StateSetUpdater
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -249,7 +264,7 @@ namespace MWRender
|
|||||||
|
|
||||||
void setColor(const osg::Vec4f& color);
|
void setColor(const osg::Vec4f& color);
|
||||||
void adjustTransparency(const float ratio) override;
|
void adjustTransparency(const float ratio) override;
|
||||||
|
void setUnderwater(bool underwater);
|
||||||
void setDirection(const osg::Vec3f& direction);
|
void setDirection(const osg::Vec3f& direction);
|
||||||
void setGlareTimeOfDayFade(float val);
|
void setGlareTimeOfDayFade(float val);
|
||||||
void setSunglare(bool enabled);
|
void setSunglare(bool enabled);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user