Fix incorrect minimum ambient

pull/593/head
glassmancody.info 4 years ago
parent 280fd2b162
commit 3d713e8602

@ -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)

@ -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);
}

@ -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<int>(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<osg::ref_ptr<osg::Light>>()));
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::LightSourceViewBound>& LightManager::getLightsInViewSpace(osg::Camera *camera, const osg::RefMatrix* viewMatrix, size_t frameNum)
{
bool isReflectionCamera = camera->getName() == "ReflectionCamera";
osg::observer_ptr<osg::Camera> 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);
if (fade == 0.f)
continue;
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;
auto* light = transform.mLightSource->getLight(frameNum);
light->setDiffuse(light->getDiffuse() * fade);
auto* light = transform.mLightSource->getLight(frameNum);
light->setDiffuse(light->getDiffuse() * fade);
}
}
LightSourceViewBound l;

@ -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'.

@ -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

Loading…
Cancel
Save