From f87aa02390acf0021bf76a38691c74ad2e5e9a4f Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 23 May 2024 18:06:10 +0300 Subject: [PATCH 1/4] Don't clamp individual light contribution in shaders as FFP doesn't do this --- files/shaders/lib/light/lighting_util.glsl | 2 -- 1 file changed, 2 deletions(-) diff --git a/files/shaders/lib/light/lighting_util.glsl b/files/shaders/lib/light/lighting_util.glsl index 059f024b4ad..81db04a3171 100644 --- a/files/shaders/lib/light/lighting_util.glsl +++ b/files/shaders/lib/light/lighting_util.glsl @@ -106,8 +106,6 @@ float lcalcRadius(int lightIndex) float lcalcIllumination(int lightIndex, float dist) { float illumination = 1.0 / (lcalcConstantAttenuation(lightIndex) + lcalcLinearAttenuation(lightIndex) * dist + lcalcQuadraticAttenuation(lightIndex) * dist * dist); - // FIXME: FFP doesn't do this - illumination = clamp(illumination, 0.0, 1.0); #if @lightingMethodPerObjectUniform || @lightingMethodUBO // Fade illumination between the radius and the radius doubled to diminish pop-in illumination *= 1.0 - quickstep((dist / lcalcRadius(lightIndex)) - 1.0); From debc37d93a559bd0c0e6672d9caef1b17fbc4d9c Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 23 May 2024 19:05:10 +0300 Subject: [PATCH 2/4] Fade out specularity according to light fade settings as well --- components/sceneutil/lightmanager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index c76f0b6b5ce..aa94495519e 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -1160,6 +1160,7 @@ namespace SceneUtil auto* light = transform.mLightSource->getLight(frameNum); light->setDiffuse(light->getDiffuse() * fade); + light->setSpecular(light->getSpecular() * fade); transform.mLightSource->setLastAppliedFrame(frameNum); } From e0e4b84e40cd7fd969e6f80f67193ad31b8670b0 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Fri, 24 May 2024 00:22:52 +0300 Subject: [PATCH 3/4] Disable specularity for negative lights --- components/sceneutil/lightcontroller.cpp | 12 +++++++++--- components/sceneutil/lightcontroller.hpp | 2 ++ components/sceneutil/lightutil.cpp | 6 +++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/components/sceneutil/lightcontroller.cpp b/components/sceneutil/lightcontroller.cpp index caff6826f53..18b45805719 100644 --- a/components/sceneutil/lightcontroller.cpp +++ b/components/sceneutil/lightcontroller.cpp @@ -41,6 +41,7 @@ namespace SceneUtil if (mType == LT_Normal) { light->setDiffuse(mDiffuseColor); + light->setSpecular(mSpecularColor); traverse(node, nv); return; } @@ -65,10 +66,10 @@ namespace SceneUtil mPhase = mPhase <= 0.5f ? 1.f : 0.25f; } - osg::Vec4f result = mDiffuseColor * mBrightness * node->getActorFade(); + const float result = mBrightness * node->getActorFade(); - light->setDiffuse(result); - light->setSpecular(result); + light->setDiffuse(mDiffuseColor * result); + light->setSpecular(mSpecularColor * result); traverse(node, nv); } @@ -78,4 +79,9 @@ namespace SceneUtil mDiffuseColor = color; } + void LightController::setSpecular(const osg::Vec4f& color) + { + mSpecularColor = color; + } + } diff --git a/components/sceneutil/lightcontroller.hpp b/components/sceneutil/lightcontroller.hpp index 13f5501bf9e..0c088d579f9 100644 --- a/components/sceneutil/lightcontroller.hpp +++ b/components/sceneutil/lightcontroller.hpp @@ -27,12 +27,14 @@ namespace SceneUtil void setType(LightType type); void setDiffuse(const osg::Vec4f& color); + void setSpecular(const osg::Vec4f& color); void operator()(SceneUtil::LightSource* node, osg::NodeVisitor* nv); private: LightType mType; osg::Vec4f mDiffuseColor; + osg::Vec4f mSpecularColor; float mPhase; float mBrightness; double mStartTime; diff --git a/components/sceneutil/lightutil.cpp b/components/sceneutil/lightutil.cpp index f69461fa3ca..8a38ee9b721 100644 --- a/components/sceneutil/lightutil.cpp +++ b/components/sceneutil/lightutil.cpp @@ -117,19 +117,23 @@ namespace SceneUtil configureLight(light, radius, isExterior); osg::Vec4f diffuse = esmLight.mColor; + osg::Vec4f specular = esmLight.mColor; // ESM format doesn't provide specular if (esmLight.mNegative) { diffuse *= -1; diffuse.a() = 1; + // Using specular lighting for negative lights is unreasonable + specular = osg::Vec4f(); } light->setDiffuse(diffuse); light->setAmbient(ambient); - light->setSpecular(diffuse); // ESM format doesn't provide specular + light->setSpecular(specular); lightSource->setLight(light); osg::ref_ptr ctrl(new SceneUtil::LightController); ctrl->setDiffuse(light->getDiffuse()); + ctrl->setSpecular(light->getSpecular()); if (esmLight.mFlicker) ctrl->setType(SceneUtil::LightController::LT_Flicker); if (esmLight.mFlickerSlow) From fd9361f62c5ec6e5b857c8a3ab6e8c9c4e7ddcbb Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Fri, 24 May 2024 00:52:49 +0300 Subject: [PATCH 4/4] Some attenuation setup fool-proofing --- components/sceneutil/lightutil.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/components/sceneutil/lightutil.cpp b/components/sceneutil/lightutil.cpp index 8a38ee9b721..08992b1ae32 100644 --- a/components/sceneutil/lightutil.cpp +++ b/components/sceneutil/lightutil.cpp @@ -52,11 +52,15 @@ namespace SceneUtil static const bool useConstant = Fallback::Map::getBool("LightAttenuation_UseConstant"); static const bool useLinear = Fallback::Map::getBool("LightAttenuation_UseLinear"); static const bool useQuadratic = Fallback::Map::getBool("LightAttenuation_UseQuadratic"); - static const float constantValue = Fallback::Map::getFloat("LightAttenuation_ConstantValue"); - static const float linearValue = Fallback::Map::getFloat("LightAttenuation_LinearValue"); - static const float quadraticValue = Fallback::Map::getFloat("LightAttenuation_QuadraticValue"); - static const float linearRadiusMult = Fallback::Map::getFloat("LightAttenuation_LinearRadiusMult"); - static const float quadraticRadiusMult = Fallback::Map::getFloat("LightAttenuation_QuadraticRadiusMult"); + // User file might provide nonsense values + // Clamp these settings to prevent badness (e.g. illegal OpenGL calls) + static const float constantValue = std::max(Fallback::Map::getFloat("LightAttenuation_ConstantValue"), 0.f); + static const float linearValue = std::max(Fallback::Map::getFloat("LightAttenuation_LinearValue"), 0.f); + static const float quadraticValue = std::max(Fallback::Map::getFloat("LightAttenuation_QuadraticValue"), 0.f); + static const float linearRadiusMult + = std::max(Fallback::Map::getFloat("LightAttenuation_LinearRadiusMult"), 0.f); + static const float quadraticRadiusMult + = std::max(Fallback::Map::getFloat("LightAttenuation_QuadraticRadiusMult"), 0.f); static const int linearMethod = Fallback::Map::getInt("LightAttenuation_LinearMethod"); static const int quadraticMethod = Fallback::Map::getInt("LightAttenuation_QuadraticMethod"); static const bool outQuadInLin = Fallback::Map::getBool("LightAttenuation_OutQuadInLin"); @@ -68,7 +72,7 @@ namespace SceneUtil { linearAttenuation = linearMethod == 0 ? linearValue : 0.01f; float r = radius * linearRadiusMult; - if (r && (linearMethod == 1 || linearMethod == 2)) + if (r > 0.f && (linearMethod == 1 || linearMethod == 2)) linearAttenuation = linearValue / std::pow(r, linearMethod); } @@ -76,10 +80,14 @@ namespace SceneUtil { quadraticAttenuation = quadraticMethod == 0 ? quadraticValue : 0.01f; float r = radius * quadraticRadiusMult; - if (r && (quadraticMethod == 1 || quadraticMethod == 2)) + if (r > 0.f && (quadraticMethod == 1 || quadraticMethod == 2)) quadraticAttenuation = quadraticValue / std::pow(r, quadraticMethod); } + // If the values are still nonsense, try to at least prevent UB and disable attenuation + if (constantAttenuation == 0.f && linearAttenuation == 0.f && quadraticAttenuation == 0.f) + constantAttenuation = 1.f; + light->setConstantAttenuation(constantAttenuation); light->setLinearAttenuation(linearAttenuation); light->setQuadraticAttenuation(quadraticAttenuation);