Revise light source configuration (bug #4965)

Set up attenuation less awkwardly
Use global attenuation settings for magic light source
Use constant attenuation settings
pull/2315/head
Capostrophic 6 years ago
parent 7158f09b87
commit 85e99182ce

@ -57,6 +57,7 @@
Bug #4947: Player character doesn't use lip animation
Bug #4948: Footstep sounds while levitating on ground level
Bug #4963: Enchant skill progress is incorrect
Bug #4965: Global light attenuation settings setup is lacking
Feature #2229: Improve pathfinding AI
Feature #3442: Default values for fallbacks from ini file
Feature #3610: Option to invert X axis

@ -29,7 +29,6 @@
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/lightutil.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/fallback/fallback.hpp>
#include "actor.hpp"
#include "mask.hpp"
@ -140,16 +139,8 @@ void CSVRender::Object::update()
if (light)
{
static bool outQuadInLin = Fallback::Map::getBool("LightAttenuation_OutQuadInLin");
static bool useQuadratic = Fallback::Map::getBool("LightAttenuation_UseQuadratic");
static float quadraticValue = Fallback::Map::getFloat("LightAttenuation_QuadraticValue");
static float quadraticRadiusMult = Fallback::Map::getFloat("LightAttenuation_QuadraticRadiusMult");
static bool useLinear = Fallback::Map::getBool("LightAttenuation_UseLinear");
static float linearRadiusMult = Fallback::Map::getFloat("LightAttenuation_LinearRadiusMult");
static float linearValue = Fallback::Map::getFloat("LightAttenuation_LinearValue");
bool isExterior = false; // FIXME
SceneUtil::addLight(mBaseNode, light, Mask_ParticleSystem, Mask_Lighting, isExterior, outQuadInLin, useQuadratic,
quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue);
SceneUtil::addLight(mBaseNode, light, Mask_ParticleSystem, Mask_Lighting, isExterior);
}
}

@ -16,8 +16,6 @@
#include <components/sceneutil/lightutil.hpp>
#include <components/sceneutil/visitor.hpp>
#include <components/fallback/fallback.hpp>
#include <components/misc/stringops.hpp>
#include <components/settings/settings.hpp>
@ -428,18 +426,10 @@ void ActorAnimation::addHiddenItemLight(const MWWorld::ConstPtr& item, const ESM
if (mItemLights.find(item) != mItemLights.end())
return;
static bool outQuadInLin = Fallback::Map::getBool("LightAttenuation_OutQuadInLin");
static bool useQuadratic = Fallback::Map::getBool("LightAttenuation_UseQuadratic");
static float quadraticValue = Fallback::Map::getFloat("LightAttenuation_QuadraticValue");
static float quadraticRadiusMult = Fallback::Map::getFloat("LightAttenuation_QuadraticRadiusMult");
static bool useLinear = Fallback::Map::getBool("LightAttenuation_UseLinear");
static float linearRadiusMult = Fallback::Map::getFloat("LightAttenuation_LinearRadiusMult");
static float linearValue = Fallback::Map::getFloat("LightAttenuation_LinearValue");
bool exterior = mPtr.isInCell() && mPtr.getCell()->getCell()->isExterior();
osg::Vec4f ambient(1,1,1,1);
osg::ref_ptr<SceneUtil::LightSource> lightSource = SceneUtil::createLightSource(esmLight, Mask_Lighting, exterior, outQuadInLin,
useQuadratic, quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue, ambient);
osg::ref_ptr<SceneUtil::LightSource> lightSource = SceneUtil::createLightSource(esmLight, Mask_Lighting, exterior, ambient);
mInsert->addChild(lightSource);

@ -38,8 +38,6 @@
#include <components/settings/settings.hpp>
#include <components/fallback/fallback.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/esmstore.hpp"
@ -1628,17 +1626,9 @@ namespace MWRender
void Animation::addExtraLight(osg::ref_ptr<osg::Group> parent, const ESM::Light *esmLight)
{
static bool outQuadInLin = Fallback::Map::getBool("LightAttenuation_OutQuadInLin");
static bool useQuadratic = Fallback::Map::getBool("LightAttenuation_UseQuadratic");
static float quadraticValue = Fallback::Map::getFloat("LightAttenuation_QuadraticValue");
static float quadraticRadiusMult = Fallback::Map::getFloat("LightAttenuation_QuadraticRadiusMult");
static bool useLinear = Fallback::Map::getBool("LightAttenuation_UseLinear");
static float linearRadiusMult = Fallback::Map::getFloat("LightAttenuation_LinearRadiusMult");
static float linearValue = Fallback::Map::getFloat("LightAttenuation_LinearValue");
bool exterior = mPtr.isInCell() && mPtr.getCell()->getCell()->isExterior();
SceneUtil::addLight(parent, esmLight, Mask_ParticleSystem, Mask_Lighting, exterior, outQuadInLin,
useQuadratic, quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue);
SceneUtil::addLight(parent, esmLight, Mask_ParticleSystem, Mask_Lighting, exterior);
}
void Animation::addEffect (const std::string& model, int effectId, bool loop, const std::string& bonename, const std::string& texture, float scale)
@ -1833,14 +1823,12 @@ namespace MWRender
}
else
{
// TODO: use global attenuation settings
// 1 pt of Light magnitude corresponds to 1 foot of radius
float radius = effect * std::ceil(Constants::UnitsPerFoot);
const float linearValue = 3.f; // Currently hardcoded: unmodified Morrowind attenuation settings
float linearAttenuation = linearValue / radius;
// Arbitrary multiplier used to make the obvious cut-off less obvious
float cutoffMult = 3;
if (!mGlowLight || linearAttenuation != mGlowLight->getLight(0)->getLinearAttenuation())
if (!mGlowLight || (radius * cutoffMult) != mGlowLight->getRadius())
{
if (mGlowLight)
{
@ -1852,7 +1840,9 @@ namespace MWRender
light->setDiffuse(osg::Vec4f(0,0,0,0));
light->setSpecular(osg::Vec4f(0,0,0,0));
light->setAmbient(osg::Vec4f(1.5f,1.5f,1.5f,1.f));
light->setLinearAttenuation(linearAttenuation);
bool isExterior = mPtr.isInCell() && mPtr.getCell()->getCell()->isExterior();
SceneUtil::configureLight(light, radius, isExterior);
mGlowLight = new SceneUtil::LightSource;
mGlowLight->setNodeMask(Mask_Lighting);
@ -1860,8 +1850,7 @@ namespace MWRender
mGlowLight->setLight(light);
}
// Make the obvious cut-off a bit less obvious
mGlowLight->setRadius(radius * 3);
mGlowLight->setRadius(radius * cutoffMult);
}
}

@ -5,6 +5,7 @@
#include <osg/ComputeBoundsVisitor>
#include <components/esm/loadligh.hpp>
#include <components/fallback/fallback.hpp>
#include "lightmanager.hpp"
#include "lightcontroller.hpp"
@ -15,32 +16,43 @@
namespace SceneUtil
{
void configureLight(osg::Light *light, float radius, bool isExterior, bool outQuadInLin, bool useQuadratic,
float quadraticValue, float quadraticRadiusMult, bool useLinear, float linearRadiusMult, float linearValue)
void configureLight(osg::Light *light, float radius, bool isExterior)
{
bool quadratic = useQuadratic && (!outQuadInLin || isExterior);
float quadraticAttenuation = 0.f;
float linearAttenuation = 0.f;
float constantAttenuation = 0.f;
float quadraticAttenuation = 0;
float linearAttenuation = 0;
if (quadratic)
const bool useConstant = Fallback::Map::getBool("LightAttenuation_UseConstant");
if (useConstant)
{
float r = radius * quadraticRadiusMult;
quadraticAttenuation = quadraticValue / std::pow(r, 2);
constantAttenuation = Fallback::Map::getFloat("LightAttenuation_ConstantValue");
}
const bool useLinear = Fallback::Map::getBool("LightAttenuation_UseLinear");
if (useLinear)
{
const float linearValue = Fallback::Map::getFloat("LightAttenuation_LinearValue");
const float linearRadiusMult = Fallback::Map::getFloat("LightAttenuation_LinearRadiusMult");
float r = radius * linearRadiusMult;
linearAttenuation = linearValue / r;
if (r) linearAttenuation = linearValue / r;
}
const bool useQuadratic = Fallback::Map::getBool("LightAttenuation_UseQuadratic");
const bool outQuadInLin = Fallback::Map::getBool("LightAttenuation_OutQuadInLin");
if (useQuadratic && (!outQuadInLin || isExterior))
{
const float quadraticValue = Fallback::Map::getFloat("LightAttenuation_QuadraticValue");
const float quadraticRadiusMult = Fallback::Map::getFloat("LightAttenuation_QuadraticRadiusMult");
float r = radius * quadraticRadiusMult;
if (r) quadraticAttenuation = quadraticValue / std::pow(r, 2);
}
light->setConstantAttenuation(constantAttenuation);
light->setLinearAttenuation(linearAttenuation);
light->setQuadraticAttenuation(quadraticAttenuation);
light->setConstantAttenuation(0.f);
}
void addLight (osg::Group* node, const ESM::Light* esmLight, unsigned int partsysMask, unsigned int lightMask, bool isExterior, bool outQuadInLin, bool useQuadratic,
float quadraticValue, float quadraticRadiusMult, bool useLinear, float linearRadiusMult,
float linearValue)
void addLight (osg::Group* node, const ESM::Light* esmLight, unsigned int partsysMask, unsigned int lightMask, bool isExterior)
{
SceneUtil::FindByNameVisitor visitor("AttachLight");
node->accept(visitor);
@ -67,13 +79,11 @@ namespace SceneUtil
attachTo = trans;
}
osg::ref_ptr<LightSource> lightSource = createLightSource(esmLight, lightMask, isExterior, outQuadInLin, useQuadratic, quadraticValue,
quadraticRadiusMult, useLinear, linearRadiusMult, linearValue);
osg::ref_ptr<LightSource> lightSource = createLightSource(esmLight, lightMask, isExterior);
attachTo->addChild(lightSource);
}
osg::ref_ptr<LightSource> createLightSource(const ESM::Light* esmLight, unsigned int lightMask, bool isExterior, bool outQuadInLin, bool useQuadratic, float quadraticValue,
float quadraticRadiusMult, bool useLinear, float linearRadiusMult, float linearValue, const osg::Vec4f& ambient)
osg::ref_ptr<LightSource> createLightSource(const ESM::Light* esmLight, unsigned int lightMask, bool isExterior, const osg::Vec4f& ambient)
{
osg::ref_ptr<SceneUtil::LightSource> lightSource (new SceneUtil::LightSource);
osg::ref_ptr<osg::Light> light (new osg::Light);
@ -82,8 +92,7 @@ namespace SceneUtil
float radius = esmLight->mData.mRadius;
lightSource->setRadius(radius);
configureLight(light, radius, isExterior, outQuadInLin, useQuadratic, quadraticValue,
quadraticRadiusMult, useLinear, linearRadiusMult, linearValue);
configureLight(light, radius, isExterior);
osg::Vec4f diffuse = SceneUtil::colourFromRGB(esmLight->mData.mColor);
if (esmLight->mData.mFlags & ESM::Light::Negative)

@ -7,6 +7,7 @@
namespace osg
{
class Group;
class Light;
}
namespace ESM
@ -18,6 +19,11 @@ namespace SceneUtil
{
class LightSource;
/// @brief Set up global attenuation settings for an osg::Light.
/// @param radius The radius of the light source.
/// @param isExterior Is the light outside? May be used for deciding which attenuation settings to use.
void configureLight (osg::Light *light, float radius, bool isExterior);
/// @brief Convert an ESM::Light to a SceneUtil::LightSource, and add it to a sub graph.
/// @note If the sub graph contains a node named "AttachLight" (case insensitive), then the light is added to that.
/// Otherwise, the light is added in the center of the node's bounds.
@ -26,19 +32,14 @@ namespace SceneUtil
/// @param partsysMask Node mask to ignore when computing the sub graph's bounding box.
/// @param lightMask Mask to assign to the newly created LightSource.
/// @param isExterior Is the light outside? May be used for deciding which attenuation settings to use.
/// @par Attenuation parameters come from the game INI file.
void addLight (osg::Group* node, const ESM::Light* esmLight, unsigned int partsysMask, unsigned int lightMask, bool isExterior, bool outQuadInLin, bool useQuadratic,
float quadraticValue, float quadraticRadiusMult, bool useLinear, float linearRadiusMult,
float linearValue);
void addLight (osg::Group* node, const ESM::Light* esmLight, unsigned int partsysMask, unsigned int lightMask, bool isExterior);
/// @brief Convert an ESM::Light to a SceneUtil::LightSource, and return it.
/// @param esmLight The light definition coming from the game files containing radius, color, flicker, etc.
/// @param lightMask Mask to assign to the newly created LightSource.
/// @param isExterior Is the light outside? May be used for deciding which attenuation settings to use.
/// @param ambient Ambient component of the light.
/// @par Attenuation parameters come from the game INI file.
osg::ref_ptr<LightSource> createLightSource (const ESM::Light* esmLight, unsigned int lightMask, bool isExterior, bool outQuadInLin, bool useQuadratic,
float quadraticValue, float quadraticRadiusMult, bool useLinear, float linearRadiusMult, float linearValue, const osg::Vec4f& ambient=osg::Vec4f(0,0,0,1));
osg::ref_ptr<LightSource> createLightSource (const ESM::Light* esmLight, unsigned int lightMask, bool isExterior, const osg::Vec4f& ambient=osg::Vec4f(0,0,0,1));
}

Loading…
Cancel
Save