Revise light source configuration (bug #4965)

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

@ -57,6 +57,7 @@
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 #4963: Enchant skill progress is incorrect Bug #4963: Enchant skill progress is incorrect
Bug #4965: Global light attenuation settings setup is lacking
Feature #2229: Improve pathfinding AI Feature #2229: Improve pathfinding AI
Feature #3442: Default values for fallbacks from ini file Feature #3442: Default values for fallbacks from ini file
Feature #3610: Option to invert X axis Feature #3610: Option to invert X axis

@ -29,7 +29,6 @@
#include <components/resource/scenemanager.hpp> #include <components/resource/scenemanager.hpp>
#include <components/sceneutil/lightutil.hpp> #include <components/sceneutil/lightutil.hpp>
#include <components/sceneutil/lightmanager.hpp> #include <components/sceneutil/lightmanager.hpp>
#include <components/fallback/fallback.hpp>
#include "actor.hpp" #include "actor.hpp"
#include "mask.hpp" #include "mask.hpp"
@ -140,16 +139,8 @@ void CSVRender::Object::update()
if (light) 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 bool isExterior = false; // FIXME
SceneUtil::addLight(mBaseNode, light, Mask_ParticleSystem, Mask_Lighting, isExterior, outQuadInLin, useQuadratic, SceneUtil::addLight(mBaseNode, light, Mask_ParticleSystem, Mask_Lighting, isExterior);
quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue);
} }
} }

@ -16,8 +16,6 @@
#include <components/sceneutil/lightutil.hpp> #include <components/sceneutil/lightutil.hpp>
#include <components/sceneutil/visitor.hpp> #include <components/sceneutil/visitor.hpp>
#include <components/fallback/fallback.hpp>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <components/settings/settings.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()) if (mItemLights.find(item) != mItemLights.end())
return; 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(); bool exterior = mPtr.isInCell() && mPtr.getCell()->getCell()->isExterior();
osg::Vec4f ambient(1,1,1,1); osg::Vec4f ambient(1,1,1,1);
osg::ref_ptr<SceneUtil::LightSource> lightSource = SceneUtil::createLightSource(esmLight, Mask_Lighting, exterior, outQuadInLin, osg::ref_ptr<SceneUtil::LightSource> lightSource = SceneUtil::createLightSource(esmLight, Mask_Lighting, exterior, ambient);
useQuadratic, quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue, ambient);
mInsert->addChild(lightSource); mInsert->addChild(lightSource);

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

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

@ -7,6 +7,7 @@
namespace osg namespace osg
{ {
class Group; class Group;
class Light;
} }
namespace ESM namespace ESM
@ -18,6 +19,11 @@ namespace SceneUtil
{ {
class LightSource; 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. /// @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. /// @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. /// 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 partsysMask Node mask to ignore when computing the sub graph's bounding box.
/// @param lightMask Mask to assign to the newly created LightSource. /// @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 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);
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);
/// @brief Convert an ESM::Light to a SceneUtil::LightSource, and return it. /// @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 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 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 isExterior Is the light outside? May be used for deciding which attenuation settings to use.
/// @param ambient Ambient component of the light. /// @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, const osg::Vec4f& ambient=osg::Vec4f(0,0,0,1));
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));
} }

Loading…
Cancel
Save