From 85e99182cef1a9c80e193fed65b10ac71a7a9873 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Tue, 9 Apr 2019 23:32:34 +0300 Subject: [PATCH] Revise light source configuration (bug #4965) Set up attenuation less awkwardly Use global attenuation settings for magic light source Use constant attenuation settings --- CHANGELOG.md | 1 + apps/opencs/view/render/object.cpp | 11 +----- apps/openmw/mwrender/actoranimation.cpp | 12 +------ apps/openmw/mwrender/animation.cpp | 27 +++++--------- components/sceneutil/lightutil.cpp | 47 +++++++++++++++---------- components/sceneutil/lightutil.hpp | 15 ++++---- 6 files changed, 47 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77d3b9c35..3d31fba12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/apps/opencs/view/render/object.cpp b/apps/opencs/view/render/object.cpp index 1ed7b3c05..fe4adfcb6 100644 --- a/apps/opencs/view/render/object.cpp +++ b/apps/opencs/view/render/object.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #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); } } diff --git a/apps/openmw/mwrender/actoranimation.cpp b/apps/openmw/mwrender/actoranimation.cpp index b5908e5b4..c54e28426 100644 --- a/apps/openmw/mwrender/actoranimation.cpp +++ b/apps/openmw/mwrender/actoranimation.cpp @@ -16,8 +16,6 @@ #include #include -#include - #include #include @@ -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 lightSource = SceneUtil::createLightSource(esmLight, Mask_Lighting, exterior, outQuadInLin, - useQuadratic, quadraticValue, quadraticRadiusMult, useLinear, linearRadiusMult, linearValue, ambient); + osg::ref_ptr lightSource = SceneUtil::createLightSource(esmLight, Mask_Lighting, exterior, ambient); mInsert->addChild(lightSource); diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 13d3df267..96b377b10 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -38,8 +38,6 @@ #include -#include - #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwworld/esmstore.hpp" @@ -1628,17 +1626,9 @@ namespace MWRender void Animation::addExtraLight(osg::ref_ptr 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); } } diff --git a/components/sceneutil/lightutil.cpp b/components/sceneutil/lightutil.cpp index d44724e8f..a1dc84994 100644 --- a/components/sceneutil/lightutil.cpp +++ b/components/sceneutil/lightutil.cpp @@ -5,6 +5,7 @@ #include #include +#include #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 = createLightSource(esmLight, lightMask, isExterior, outQuadInLin, useQuadratic, quadraticValue, - quadraticRadiusMult, useLinear, linearRadiusMult, linearValue); + osg::ref_ptr lightSource = createLightSource(esmLight, lightMask, isExterior); attachTo->addChild(lightSource); } - osg::ref_ptr 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 createLightSource(const ESM::Light* esmLight, unsigned int lightMask, bool isExterior, const osg::Vec4f& ambient) { osg::ref_ptr lightSource (new SceneUtil::LightSource); osg::ref_ptr 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) diff --git a/components/sceneutil/lightutil.hpp b/components/sceneutil/lightutil.hpp index 95172e239..7096c38b2 100644 --- a/components/sceneutil/lightutil.hpp +++ b/components/sceneutil/lightutil.hpp @@ -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 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 createLightSource (const ESM::Light* esmLight, unsigned int lightMask, bool isExterior, const osg::Vec4f& ambient=osg::Vec4f(0,0,0,1)); }