From 3d713e8602b71711db609ddc6746e3f3331dd74a Mon Sep 17 00:00:00 2001 From: "glassmancody.info" Date: Wed, 31 Mar 2021 22:35:02 -0700 Subject: [PATCH] Fix incorrect minimum ambient --- AUTHORS.md | 1 + apps/openmw/mwrender/renderingmanager.cpp | 45 +++++++------ components/sceneutil/lightmanager.cpp | 67 +++++++------------ .../reference/modding/settings/shaders.rst | 16 ++--- files/settings-default.cfg | 12 ++-- 5 files changed, 65 insertions(+), 76 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index d2de85747..07aef455c 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -49,6 +49,7 @@ Programmers Cédric Mocquillon Chris Boyce (slothlife) Chris Robinson (KittyCat) + Cody Glassman (Wazabear) Coleman Smith (olcoal) Cory F. Cohen (cfcohen) Cris Mihalache (Mirceam) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 865bae2f1..c14431518 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -537,7 +537,32 @@ namespace MWRender void RenderingManager::configureAmbient(const ESM::Cell *cell) { - setAmbientColour(SceneUtil::colourFromRGB(cell->mAmbi.mAmbient)); + bool needsAdjusting = false; + if (mResourceSystem->getSceneManager()->getLightingMethod() != SceneUtil::LightingMethod::FFP) + needsAdjusting = !cell->isExterior() && !(cell->mData.mFlags & ESM::Cell::QuasiEx); + + auto ambient = SceneUtil::colourFromRGB(cell->mAmbi.mAmbient); + + if (needsAdjusting) + { + static constexpr float pR = 0.2126; + static constexpr float pG = 0.7152; + static constexpr float pB = 0.0722; + + // we already work in linear RGB so no conversions are needed for the luminosity function + float relativeLuminance = pR*ambient.r() + pG*ambient.g() + pB*ambient.b(); + if (relativeLuminance < mMinimumAmbientLuminance) + { + // brighten ambient so it reaches the minimum threshold but no more, we want to mess with content data as least we can + float targetBrightnessIncreaseFactor = mMinimumAmbientLuminance / relativeLuminance; + if (ambient.r() == 0.f && ambient.g() == 0.f && ambient.b() == 0.f) + ambient = osg::Vec4(targetBrightnessIncreaseFactor, targetBrightnessIncreaseFactor, targetBrightnessIncreaseFactor, ambient.a()); + else + ambient *= targetBrightnessIncreaseFactor; + } + } + + setAmbientColour(ambient); osg::Vec4f diffuse = SceneUtil::colourFromRGB(cell->mAmbi.mSunlight); mSunLight->setDiffuse(diffuse); @@ -1076,25 +1101,7 @@ namespace MWRender osg::Vec4f color = mAmbientColor; if (mNightEyeFactor > 0.f) - { color += osg::Vec4f(0.7, 0.7, 0.7, 0.0) * mNightEyeFactor; - } - // optionally brighten up ambient interiors when using a non-FFP emulated lighting method - else if (mResourceSystem->getSceneManager()->getLightingMethod() != SceneUtil::LightingMethod::FFP) - { - static constexpr float pR = 0.2126; - static constexpr float pG = 0.7152; - static constexpr float pB = 0.0722; - - // we already work in linear RGB so no conversions are needed for the luminosity function - float relativeLuminance = pR*color.r() + pG*color.g() + pB*color.b(); - if (relativeLuminance < mMinimumAmbientLuminance) - { - // brighten ambient so it reaches the minimum threshold but no more, we want to mess with content data as least we can - float targetBrightnessIncreaseFactor = mMinimumAmbientLuminance / relativeLuminance; - color *= targetBrightnessIncreaseFactor; - } - } mStateUpdater->setAmbientColor(color); } diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index c7a483429..f20e28a7e 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -381,27 +381,14 @@ namespace SceneUtil void apply(osg::State &state) const override { - osg::Matrix modelViewMatrix = state.getModelViewMatrix(); - - state.applyModelViewMatrix(state.getInitialViewMatrix()); - - LightStateCache* cache = getLightStateCache(state.getContextID(), mLightManager->getMaxLights()); for (size_t i = 0; i < mLights.size(); ++i) { - osg::Light* current = cache->lastAppliedLight[i]; auto light = mLights[i]; - if (current != light.get()) - { - mLightManager->getLightUniform(i+1, LightManager::UniformKey::Diffuse)->set(light->getDiffuse()); - mLightManager->getLightUniform(i+1, LightManager::UniformKey::Ambient)->set(light->getAmbient()); - mLightManager->getLightUniform(i+1, LightManager::UniformKey::Attenuation)->set(osg::Vec4(light->getConstantAttenuation(), light->getLinearAttenuation(), light->getQuadraticAttenuation(), getLightRadius(light))); - mLightManager->getLightUniform(i+1, LightManager::UniformKey::Position)->set(light->getPosition() * state.getModelViewMatrix()); - - cache->lastAppliedLight[i] = mLights[i]; - } + mLightManager->getLightUniform(i+1, LightManager::UniformKey::Diffuse)->set(light->getDiffuse()); + mLightManager->getLightUniform(i+1, LightManager::UniformKey::Ambient)->set(light->getAmbient()); + mLightManager->getLightUniform(i+1, LightManager::UniformKey::Attenuation)->set(osg::Vec4(light->getConstantAttenuation(), light->getLinearAttenuation(), light->getQuadraticAttenuation(), getLightRadius(light))); + mLightManager->getLightUniform(i+1, LightManager::UniformKey::Position)->set(light->getPosition() * state.getInitialViewMatrix()); } - - state.applyModelViewMatrix(modelViewMatrix); } private: @@ -643,7 +630,7 @@ namespace SceneUtil mDummyProgram->addBindUniformBlock("LightBufferBinding", static_cast(Shader::UBOBinding::LightBuffer)); // Needed to query the layout of the buffer object. The layout specifier needed to use the std140 layout is not reliably // available, regardless of extensions, until GLSL 140. - mLightManager->getOrCreateStateSet()->setAttributeAndModes(mDummyProgram, osg::StateAttribute::ON|osg::StateAttribute::PROTECTED); + mLightManager->getOrCreateStateSet()->setAttributeAndModes(mDummyProgram, osg::StateAttribute::ON); } LightManagerStateAttribute(const LightManagerStateAttribute& copy, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY) @@ -756,9 +743,10 @@ namespace SceneUtil , mPointLightFadeEnd(0.f) , mPointLightFadeStart(0.f) { + setUpdateCallback(new LightManagerUpdateCallback); + if (ffp) { - setLightingMethod(LightingMethod::FFP); initFFP(LightManager::mFFPMaxLights); return; } @@ -769,11 +757,7 @@ namespace SceneUtil { Log(Debug::Error) << "Invalid option for 'lighting method': got '" << lightingMethodString << "', expected legacy, shaders compatible, or shaders. Falling back to 'shaders compatible'."; - setLightingMethod(LightingMethod::PerObjectUniform); - } - else - { - setLightingMethod(lightingMethod); + lightingMethod = LightingMethod::PerObjectUniform; } mPointLightRadiusMultiplier = std::clamp(Settings::Manager::getFloat("light bounds multiplier", "Shaders"), 0.f, 10.f); @@ -791,7 +775,7 @@ namespace SceneUtil static bool hasLoggedWarnings = false; - if (getLightingMethod() == LightingMethod::SingleUBO && !hasLoggedWarnings) + if (lightingMethod == LightingMethod::SingleUBO && !hasLoggedWarnings) { if (!supportsUBO) Log(Debug::Warning) << "GL_ARB_uniform_buffer_object not supported: switching to shader compatibility lighting mode"; @@ -802,19 +786,13 @@ namespace SceneUtil int targetLights = Settings::Manager::getInt("max lights", "Shaders"); - if (!supportsUBO || !supportsGPU4 || getLightingMethod() == LightingMethod::PerObjectUniform) - { - setLightingMethod(LightingMethod::PerObjectUniform); + if (!supportsUBO || !supportsGPU4 || lightingMethod == LightingMethod::PerObjectUniform) initPerObjectUniform(targetLights); - } else - { initSingleUBO(targetLights); - } getOrCreateStateSet()->addUniform(new osg::Uniform("PointLightCount", 0)); - setUpdateCallback(new LightManagerUpdateCallback); addCullCallback(new LightManagerCullCallback(this)); } @@ -876,18 +854,18 @@ namespace SceneUtil void LightManager::initFFP(int targetLights) { + setLightingMethod(LightingMethod::FFP); setMaxLights(targetLights); for (int i = 0; i < getMaxLights(); ++i) mDummies.push_back(new FFPLightStateAttribute(i, std::vector>())); - - setUpdateCallback(new LightManagerUpdateCallback); } void LightManager::initPerObjectUniform(int targetLights) { auto* stateset = getOrCreateStateSet(); + setLightingMethod(LightingMethod::PerObjectUniform); setMaxLights(std::max(2, targetLights)); mLightUniforms.resize(getMaxLights()+1); @@ -918,6 +896,7 @@ namespace SceneUtil void LightManager::initSingleUBO(int targetLights) { + setLightingMethod(LightingMethod::SingleUBO); setMaxLights(std::clamp(targetLights, 2, getMaxLightsInScene() / 2)); for (int i = 0; i < 2; ++i) @@ -1059,6 +1038,7 @@ namespace SceneUtil const std::vector& LightManager::getLightsInViewSpace(osg::Camera *camera, const osg::RefMatrix* viewMatrix, size_t frameNum) { + bool isReflectionCamera = camera->getName() == "ReflectionCamera"; osg::observer_ptr camPtr (camera); auto it = mLightsInViewSpace.find(camPtr); @@ -1075,17 +1055,18 @@ namespace SceneUtil osg::BoundingSphere viewBound = osg::BoundingSphere(osg::Vec3f(0,0,0), radius * mPointLightRadiusMultiplier); transformBoundingSphere(worldViewMat, viewBound); - static const float fadeDelta = mPointLightFadeEnd - mPointLightFadeStart; - - if (mPointLightFadeEnd != 0.f) + if (!isReflectionCamera) { - float fade = 1 - std::clamp((viewBound.center().length() - mPointLightFadeStart) / fadeDelta, 0.f, 1.f); + static const float fadeDelta = mPointLightFadeEnd - mPointLightFadeStart; + if (mPointLightFadeEnd != 0.f) + { + float fade = 1 - std::clamp((viewBound.center().length() - mPointLightFadeStart) / fadeDelta, 0.f, 1.f); + if (fade == 0.f) + continue; - if (fade == 0.f) - continue; - - auto* light = transform.mLightSource->getLight(frameNum); - light->setDiffuse(light->getDiffuse() * fade); + auto* light = transform.mLightSource->getLight(frameNum); + light->setDiffuse(light->getDiffuse() * fade); + } } LightSourceViewBound l; diff --git a/docs/source/reference/modding/settings/shaders.rst b/docs/source/reference/modding/settings/shaders.rst index 3b0f6df5a..be38bd3ec 100644 --- a/docs/source/reference/modding/settings/shaders.rst +++ b/docs/source/reference/modding/settings/shaders.rst @@ -160,12 +160,12 @@ Sets the internal handling of light sources. 'legacy' is restricted to 8 lights per object and emulates fixed function pipeline compatible lighting. -'shaders compatibility' removes the light limit via :ref:`max lights` and -follows a modifed attenuation formula which can drastically reduce light popping -and seams. This mode also enables lighting on groundcover and a configurable -light fade. It is recommended to use this with older hardware and a light limit -closer to 8. Because of its wide range of compatibility it is set as the -default. +'shaders compatibility' removes the light limit controllable through :ref:`max +lights` and follows a modifed attenuation formula which can drastically reduce +light popping and seams. This mode also enables lighting on groundcover and a +configurable light fade. It is recommended to use this with older hardware and a +light limit closer to 8. Because of its wide range of compatibility it is set as +the default. 'shaders' carries all of the benefits that 'shaders compatibility' does, but uses a modern approach that allows for a higher :ref:`max lights` count with @@ -174,9 +174,9 @@ this mode when supported and where the GPU is not a bottleneck. On some weaker devices, using this mode along with :ref:`force per pixel lighting` can carry performance penalties. -Note that when enabled, groundcover lighting is forced to be vertex lighting, +Note that when enabled groundcover lighting is forced to be vertex lighting, unless normal maps are provided. This is due to some groundcover mods using the -Z-Up Normals technique to avoid some common issues with shading. As a +Z-Up normals technique to avoid some common issues with shading. As a consequence, per pixel lighting would give undesirable results. This setting has no effect if :ref:`force shaders` is 'false'. diff --git a/files/settings-default.cfg b/files/settings-default.cfg index c93178906..de2c237e8 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -451,11 +451,11 @@ radial fog = false # 'force per pixel lighting' is enabled. lighting method = shaders compatibility -# Sets the bounding sphere multiplier of light sources, which are used to -# determine if an object should receive lighting. Higher values will allow for -# smoother transitions of light sources, but may carry a performance cost and -# requires a higher number of 'max lights' set. It is recommended to keep this -# at 1.0 with 'legacy' lighting enabled. +# Sets the bounding sphere multiplier of light sources if 'lighting method' is +# not 'legacy'. These are used to determine if an object should receive +# lighting. Higher values will allow for smoother transitions of light sources, +# but may carry a performance cost and requires a higher number of 'max lights' +# set. light bounds multiplier = 1.75 # The distance from the camera at which lights fade away completely. @@ -470,7 +470,7 @@ light fade start = 0.85 max lights = 8 # Sets minimum ambient brightness of interior cells. Levels below this threshold will have their -# ambient values adjusted to balance the darker interiors. +# ambient values adjusted to balance the darker interiors. # When 'lighting method' is set to 'legacy', this setting will have no effect. minimum interior brightness = 0.1