mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-01 19:45:35 +00:00
Merge pull request #2486 from Capostrophic/flicker
Rewrite flickering/pulsing to work like vanilla (bug #4952)
This commit is contained in:
commit
fe0791d34b
3 changed files with 31 additions and 87 deletions
|
@ -84,6 +84,7 @@
|
||||||
Bug #4945: Poor random magic magnitude distribution
|
Bug #4945: Poor random magic magnitude distribution
|
||||||
Bug #4947: Player character doesn't use lip animation
|
Bug #4947: Player character doesn't use lip animation
|
||||||
Bug #4948: Footstep sounds while levitating on ground level
|
Bug #4948: Footstep sounds while levitating on ground level
|
||||||
|
Bug #4952: Torches held by NPCs flicker too quickly
|
||||||
Bug #4961: Flying creature combat engagement takes z-axis into account
|
Bug #4961: Flying creature combat engagement takes z-axis into account
|
||||||
Bug #4963: Enchant skill progress is incorrect
|
Bug #4963: Enchant skill progress is incorrect
|
||||||
Bug #4964: Multiple effect spell projectile sounds play louder than vanilla
|
Bug #4964: Multiple effect spell projectile sounds play louder than vanilla
|
||||||
|
|
|
@ -8,48 +8,16 @@
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
float pulseAmplitude(float time)
|
|
||||||
{
|
|
||||||
return std::sin(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
float flickerAmplitude(float time)
|
|
||||||
{
|
|
||||||
static const float fb = 1.17024f;
|
|
||||||
static const float f[3] = { 1.5708f, 4.18774f, 5.19934f };
|
|
||||||
static const float o[3] = { 0.804248f, 2.11115f, 3.46832f };
|
|
||||||
static const float m[3] = { 1.0f, 0.785f, 0.876f };
|
|
||||||
static const float s = 0.394f;
|
|
||||||
|
|
||||||
float v = 0.0f;
|
|
||||||
for(int i = 0;i < 3;++i)
|
|
||||||
v += std::sin(fb*time*f[i] + o[i])*m[i];
|
|
||||||
return v * s;
|
|
||||||
}
|
|
||||||
|
|
||||||
float flickerFrequency(float phase)
|
|
||||||
{
|
|
||||||
static const float fa = 0.785398f;
|
|
||||||
static const float tdo = 0.94f;
|
|
||||||
static const float tdm = 2.48f;
|
|
||||||
|
|
||||||
return tdo + tdm*std::sin(fa * phase);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
|
|
||||||
LightController::LightController()
|
LightController::LightController()
|
||||||
: mType(LT_Normal)
|
: mType(LT_Normal)
|
||||||
, mPhase((Misc::Rng::rollClosedProbability() * 2.f - 1.f) * 500.f)
|
, mPhase(0.25f + Misc::Rng::rollClosedProbability() * 0.75f)
|
||||||
, mDeltaCount(0.f)
|
, mBrightness(0.675f)
|
||||||
, mDirection(1.f)
|
, mStartTime(0.0)
|
||||||
, mLastTime(0.0)
|
, mLastTime(0.0)
|
||||||
|
, mTicksToAdvance(0.f)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,66 +29,40 @@ namespace SceneUtil
|
||||||
void LightController::operator ()(osg::Node* node, osg::NodeVisitor* nv)
|
void LightController::operator ()(osg::Node* node, osg::NodeVisitor* nv)
|
||||||
{
|
{
|
||||||
double time = nv->getFrameStamp()->getSimulationTime();
|
double time = nv->getFrameStamp()->getSimulationTime();
|
||||||
|
if (mStartTime == 0)
|
||||||
|
mStartTime = time;
|
||||||
|
|
||||||
// disabled early out, light state needs to be set every frame regardless of change, due to the double buffering
|
// disabled early out, light state needs to be set every frame regardless of change, due to the double buffering
|
||||||
//if (time == mLastTime)
|
//if (time == mLastTime)
|
||||||
// return;
|
// return;
|
||||||
|
|
||||||
float dt = static_cast<float>(time - mLastTime);
|
if (mType == LT_Normal)
|
||||||
mLastTime = time;
|
|
||||||
|
|
||||||
float brightness = 1.0f;
|
|
||||||
float cycle_time;
|
|
||||||
float time_distortion;
|
|
||||||
|
|
||||||
if(mType == LT_Pulse || mType == LT_PulseSlow)
|
|
||||||
{
|
{
|
||||||
cycle_time = 2.0f * osg::PI;
|
static_cast<SceneUtil::LightSource*>(node)->getLight(nv->getTraversalNumber())->setDiffuse(mDiffuseColor);
|
||||||
time_distortion = 3.0f;
|
traverse(node, nv);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Updating flickering at 15 FPS like vanilla.
|
||||||
|
constexpr float updateRate = 15.f;
|
||||||
|
mTicksToAdvance = static_cast<float>(time - mStartTime - mLastTime) * updateRate * 0.25f + mTicksToAdvance * 0.75f;
|
||||||
|
mLastTime = time - mStartTime;
|
||||||
|
|
||||||
|
float speed = (mType == LT_Flicker || mType == LT_Pulse) ? 0.1f : 0.05f;
|
||||||
|
if (mBrightness >= mPhase)
|
||||||
|
mBrightness -= mTicksToAdvance * speed;
|
||||||
else
|
else
|
||||||
{
|
mBrightness += mTicksToAdvance * speed;
|
||||||
static const float fa = osg::PI / 4.0f;
|
|
||||||
static const float phase_wavelength = 120.0f * osg::PI / fa;
|
|
||||||
|
|
||||||
cycle_time = 500.0f;
|
if (std::abs(mBrightness - mPhase) < speed)
|
||||||
mPhase = std::fmod(mPhase + dt, phase_wavelength);
|
{
|
||||||
time_distortion = flickerFrequency(mPhase);
|
if (mType == LT_Flicker || mType == LT_FlickerSlow)
|
||||||
|
mPhase = 0.25f + Misc::Rng::rollClosedProbability() * 0.75f;
|
||||||
|
else // if (mType == LT_Pulse || mType == LT_PulseSlow)
|
||||||
|
mPhase = mPhase <= 0.5f ? 1.f : 0.25f;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDeltaCount += mDirection*dt*time_distortion;
|
static_cast<SceneUtil::LightSource*>(node)->getLight(nv->getTraversalNumber())->setDiffuse(mDiffuseColor * mBrightness);
|
||||||
if(mDirection > 0 && mDeltaCount > +cycle_time)
|
|
||||||
{
|
|
||||||
mDirection = -1.0f;
|
|
||||||
float extra = mDeltaCount - cycle_time;
|
|
||||||
mDeltaCount -= 2*extra;
|
|
||||||
}
|
|
||||||
if(mDirection < 0 && mDeltaCount < -cycle_time)
|
|
||||||
{
|
|
||||||
mDirection = +1.0f;
|
|
||||||
float extra = cycle_time - mDeltaCount;
|
|
||||||
mDeltaCount += 2*extra;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const float fast = 4.0f/1.0f;
|
|
||||||
static const float slow = 1.0f/1.0f;
|
|
||||||
|
|
||||||
// These formulas are just guesswork, but they work pretty well
|
|
||||||
if(mType == LT_Normal)
|
|
||||||
{
|
|
||||||
// Less than 1/255 light modifier for a constant light:
|
|
||||||
brightness = 1.0f + flickerAmplitude(mDeltaCount*slow)/255.0f;
|
|
||||||
}
|
|
||||||
else if(mType == LT_Flicker)
|
|
||||||
brightness = 0.75f + flickerAmplitude(mDeltaCount*fast)*0.25f;
|
|
||||||
else if(mType == LT_FlickerSlow)
|
|
||||||
brightness = 0.75f + flickerAmplitude(mDeltaCount*slow)*0.25f;
|
|
||||||
else if(mType == LT_Pulse)
|
|
||||||
brightness = 0.7f + pulseAmplitude(mDeltaCount*fast)*0.3f;
|
|
||||||
else if(mType == LT_PulseSlow)
|
|
||||||
brightness = 0.7f + pulseAmplitude(mDeltaCount*slow)*0.3f;
|
|
||||||
|
|
||||||
static_cast<SceneUtil::LightSource*>(node)->getLight(nv->getTraversalNumber())->setDiffuse(mDiffuseColor * brightness);
|
|
||||||
|
|
||||||
traverse(node, nv);
|
traverse(node, nv);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,10 @@ namespace SceneUtil
|
||||||
LightType mType;
|
LightType mType;
|
||||||
osg::Vec4f mDiffuseColor;
|
osg::Vec4f mDiffuseColor;
|
||||||
float mPhase;
|
float mPhase;
|
||||||
float mDeltaCount;
|
float mBrightness;
|
||||||
int mDirection;
|
double mStartTime;
|
||||||
double mLastTime;
|
double mLastTime;
|
||||||
|
float mTicksToAdvance;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue