Use settings values for Shaders settings

macos_ci_fix
elsid 1 year ago
parent f5ddf55cdc
commit 08902371b4
No known key found for this signature in database
GPG Key ID: 4DE04C198CBA7625

@ -2,6 +2,8 @@
#include "sdlinit.hpp"
#include <components/settings/values.hpp>
#include <QMessageBox>
#include <QScreen>
@ -144,10 +146,18 @@ bool Launcher::GraphicsPage::loadSettings()
// Lighting
int lightingMethod = 1;
if (Settings::Manager::getString("lighting method", "Shaders") == "legacy")
lightingMethod = 0;
else if (Settings::Manager::getString("lighting method", "Shaders") == "shaders")
lightingMethod = 2;
switch (Settings::shaders().mLightingMethod)
{
case SceneUtil::LightingMethod::FFP:
lightingMethod = 0;
break;
case SceneUtil::LightingMethod::PerObjectUniform:
lightingMethod = 1;
break;
case SceneUtil::LightingMethod::SingleUBO:
lightingMethod = 2;
break;
}
lightingMethodComboBox->setCurrentIndex(lightingMethod);
// Shadows
@ -246,10 +256,12 @@ void Launcher::GraphicsPage::saveSettings()
}
// Lighting
static std::array<std::string, 3> lightingMethodMap = { "legacy", "shaders compatibility", "shaders" };
const std::string& cLightingMethod = lightingMethodMap[lightingMethodComboBox->currentIndex()];
if (cLightingMethod != Settings::Manager::getString("lighting method", "Shaders"))
Settings::Manager::setString("lighting method", "Shaders", cLightingMethod);
static constexpr std::array<SceneUtil::LightingMethod, 3> lightingMethodMap = {
SceneUtil::LightingMethod::FFP,
SceneUtil::LightingMethod::PerObjectUniform,
SceneUtil::LightingMethod::SingleUBO,
};
Settings::shaders().mLightingMethod.set(lightingMethodMap[lightingMethodComboBox->currentIndex()]);
// Shadows
int cShadowDist = shadowDistanceCheckBox->checkState() != Qt::Unchecked ? shadowDistanceSpinBox->value() : 0;

@ -87,10 +87,10 @@ namespace CSVRender
mView->getCamera()->setGraphicsContext(window);
SceneUtil::LightManager* lightMgr = new SceneUtil::LightManager;
osg::ref_ptr<SceneUtil::LightManager> lightMgr = new SceneUtil::LightManager;
lightMgr->setStartLight(1);
lightMgr->setLightingMask(Mask_Lighting);
mRootNode = lightMgr;
mRootNode = std::move(lightMgr);
mView->getCamera()->setViewport(new osg::Viewport(0, 0, width(), height()));

@ -147,7 +147,7 @@ namespace
constexpr int min = 8;
constexpr int max = 32;
constexpr int increment = 8;
int maxLights = Settings::Manager::getInt("max lights", "Shaders");
const int maxLights = Settings::shaders().mMaxLights;
// show increments of 8 in dropdown
if (maxLights >= min && maxLights <= max && !(maxLights % increment))
box->setIndexSelected((maxLights / increment) - 1);
@ -559,7 +559,8 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->interactiveMessageBox(
"#{OMWEngine:ChangeRequiresRestart}", { "#{Interface:OK}" }, true);
Settings::Manager::setString("lighting method", "Shaders", *_sender->getItemDataAt<std::string>(pos));
Settings::shaders().mLightingMethod.set(
Settings::parseLightingMethod(*_sender->getItemDataAt<std::string>(pos)));
apply();
}
@ -630,9 +631,7 @@ namespace MWGui
void SettingsWindow::onMaxLightsChanged(MyGUI::ComboBox* _sender, size_t pos)
{
int count = 8 * (pos + 1);
Settings::Manager::setInt("max lights", "Shaders", count);
Settings::shaders().mMaxLights.set(8 * (pos + 1));
apply();
configureWidgets(mMainWidget, false);
}
@ -653,8 +652,7 @@ namespace MWGui
Settings::shaders().mMaxLights.reset();
Settings::shaders().mLightingMethod.reset();
const SceneUtil::LightingMethod lightingMethod
= SceneUtil::LightManager::getLightingMethodFromString(Settings::shaders().mLightingMethod);
const SceneUtil::LightingMethod lightingMethod = Settings::shaders().mLightingMethod;
const std::size_t lightIndex = mLightingMethodButton->findItemIndexWith(lightingMethodToStr(lightingMethod));
mLightingMethodButton->setIndexSelected(lightIndex);
updateMaxLightsComboBox(mMaxLights);

@ -24,7 +24,7 @@
#include <components/sceneutil/nodecallback.hpp>
#include <components/sceneutil/rtt.hpp>
#include <components/sceneutil/shadow.hpp>
#include <components/settings/settings.hpp>
#include <components/settings/values.hpp>
#include <components/stereo/multiview.hpp>
#include "../mwworld/class.hpp"
@ -34,6 +34,7 @@
#include "../mwmechanics/weapontype.hpp"
#include "npcanimation.hpp"
#include "util.hpp"
#include "vismask.hpp"
namespace MWRender
@ -154,7 +155,7 @@ namespace MWRender
public:
CharacterPreviewRTTNode(uint32_t sizeX, uint32_t sizeY)
: RTTNode(sizeX, sizeY, Settings::Manager::getInt("antialiasing", "Video"), false, 0,
StereoAwareness::Unaware_MultiViewShaders)
StereoAwareness::Unaware_MultiViewShaders, shouldAddMSAAIntermediateTarget())
, mAspectRatio(static_cast<float>(sizeX) / static_cast<float>(sizeY))
{
if (SceneUtil::AutoDepth::isReversed())
@ -226,9 +227,13 @@ namespace MWRender
mRTTNode = new CharacterPreviewRTTNode(sizeX, sizeY);
mRTTNode->setNodeMask(Mask_RenderToTexture);
bool ffp = mResourceSystem->getSceneManager()->getLightingMethod() == SceneUtil::LightingMethod::FFP;
osg::ref_ptr<SceneUtil::LightManager> lightManager = new SceneUtil::LightManager(ffp);
osg::ref_ptr<SceneUtil::LightManager> lightManager = new SceneUtil::LightManager(SceneUtil::LightSettings{
.mLightingMethod = mResourceSystem->getSceneManager()->getLightingMethod(),
.mMaxLights = Settings::shaders().mMaxLights,
.mMaximumLightDistance = Settings::shaders().mMaximumLightDistance,
.mLightFadeStart = Settings::shaders().mLightFadeStart,
.mLightBoundsMultiplier = Settings::shaders().mLightBoundsMultiplier,
});
lightManager->setStartLight(1);
osg::ref_ptr<osg::StateSet> stateset = lightManager->getOrCreateStateSet();
stateset->setDefine("FORCE_OPAQUE", "1", osg::StateAttribute::ON);

@ -30,6 +30,7 @@
#include "../mwworld/cellstore.hpp"
#include "util.hpp"
#include "vismask.hpp"
namespace
@ -679,7 +680,7 @@ namespace MWRender
LocalMapRenderToTexture::LocalMapRenderToTexture(osg::Node* sceneRoot, int res, int mapWorldSize, float x, float y,
const osg::Vec3d& upVector, float zmin, float zmax)
: RTTNode(res, res, 0, false, 0, StereoAwareness::Unaware_MultiViewShaders)
: RTTNode(res, res, 0, false, 0, StereoAwareness::Unaware_MultiViewShaders, shouldAddMSAAIntermediateTarget())
, mSceneRoot(sceneRoot)
, mActive(true)
{

@ -122,7 +122,6 @@ namespace MWRender
, mReload(false)
, mEnabled(false)
, mUsePostProcessing(Settings::postProcessing().mEnabled)
, mSoftParticles(false)
, mDisableDepthPasses(false)
, mLastFrameNumber(0)
, mLastSimulationTime(0.f)
@ -135,8 +134,6 @@ namespace MWRender
, mPassLights(false)
, mPrevPassLights(false)
{
mSoftParticles = Settings::Manager::getBool("soft particles", "Shaders");
osg::GraphicsContext* gc = viewer->getCamera()->getGraphicsContext();
osg::GLExtensions* ext = gc->getState()->get<osg::GLExtensions>();
@ -155,7 +152,7 @@ namespace MWRender
else
Log(Debug::Error) << "'glDisablei' unsupported, pass normals will not be available to shaders.";
if (mSoftParticles)
if (Settings::shaders().mSoftParticles)
{
for (int i = 0; i < 2; ++i)
{
@ -172,7 +169,8 @@ namespace MWRender
mUBO = ext->isUniformBufferObjectSupported && mGLSLVersion >= 330;
mStateUpdater = new fx::StateUpdater(mUBO);
if (!Stereo::getStereo() && !SceneUtil::AutoDepth::isReversed() && !mSoftParticles && !mUsePostProcessing)
if (!Stereo::getStereo() && !SceneUtil::AutoDepth::isReversed() && !Settings::shaders().mSoftParticles
&& !mUsePostProcessing)
return;
enable(mUsePostProcessing);
@ -239,7 +237,7 @@ namespace MWRender
const bool postPass = Settings::postProcessing().mTransparentPostpass;
mUsePostProcessing = usePostProcessing;
mDisableDepthPasses = !mSoftParticles && !postPass;
mDisableDepthPasses = !Settings::shaders().mSoftParticles && !postPass;
#ifdef ANDROID
mDisableDepthPasses = true;
@ -276,10 +274,10 @@ namespace MWRender
void PostProcessor::disable()
{
if (!mSoftParticles)
if (!Settings::shaders().mSoftParticles)
osgUtil::RenderBin::getRenderBinPrototype("DepthSortedBin")->setDrawCallback(nullptr);
if (!SceneUtil::AutoDepth::isReversed() && !mSoftParticles)
if (!SceneUtil::AutoDepth::isReversed() && !Settings::shaders().mSoftParticles)
{
removeChild(mHUDCamera);
setCullCallback(nullptr);

@ -175,8 +175,6 @@ namespace MWRender
bool isEnabled() const { return mUsePostProcessing && mEnabled; }
bool softParticlesEnabled() const { return mSoftParticles; }
bool getHDR() const { return mHDR; }
void disable();
@ -247,7 +245,6 @@ namespace MWRender
bool mReload;
bool mEnabled;
bool mUsePostProcessing;
bool mSoftParticles;
bool mDisableDepthPasses;
size_t mLastFrameNumber;

@ -8,6 +8,7 @@
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
#include <components/sceneutil/util.hpp>
#include <components/settings/values.hpp>
#include <components/shader/shadermanager.hpp>
#include "../mwbase/environment.hpp"
@ -112,7 +113,7 @@ namespace MWRender
mCamera->attach(osg::Camera::DEPTH_BUFFER, mDepthTexture);
mCamera->addChild(mSceneNode);
mCamera->setSmallFeatureCullingPixelSize(
Settings::Manager::getFloat("weather particle occlusion small feature culling pixel size", "Shaders"));
Settings::shaders().mWeatherParticleOcclusionSmallFeatureCullingPixelSize);
SceneUtil::setCameraClearDepth(mCamera);
}

@ -82,6 +82,7 @@
#include "screenshotmanager.hpp"
#include "sky.hpp"
#include "terrainstorage.hpp"
#include "util.hpp"
#include "vismask.hpp"
#include "water.hpp"
@ -312,7 +313,6 @@ namespace MWRender
, mResourceSystem(resourceSystem)
, mWorkQueue(workQueue)
, mNavigator(navigator)
, mMinimumAmbientLuminance(0.f)
, mNightEyeFactor(0.f)
// TODO: Near clip should not need to be bounded like this, but too small values break OSG shadow calculations
// CPU-side. See issue: #6072
@ -325,46 +325,40 @@ namespace MWRender
, mGroundCoverStore(groundcoverStore)
{
bool reverseZ = SceneUtil::AutoDepth::isReversed();
auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString(
Settings::Manager::getString("lighting method", "Shaders"));
const SceneUtil::LightingMethod lightingMethod = Settings::shaders().mLightingMethod;
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
// Shadows and radial fog have problems with fixed-function mode.
bool forceShaders = Settings::fog().mRadialFog || Settings::fog().mExponentialFog
|| Settings::Manager::getBool("soft particles", "Shaders")
|| Settings::Manager::getBool("force shaders", "Shaders")
|| Settings::shaders().mSoftParticles || Settings::shaders().mForceShaders
|| Settings::Manager::getBool("enable shadows", "Shadows")
|| lightingMethod != SceneUtil::LightingMethod::FFP || reverseZ || mSkyBlending || Stereo::getMultiview();
resourceSystem->getSceneManager()->setForceShaders(forceShaders);
// FIXME: calling dummy method because terrain needs to know whether lighting is clamped
resourceSystem->getSceneManager()->setClampLighting(Settings::Manager::getBool("clamp lighting", "Shaders"));
resourceSystem->getSceneManager()->setAutoUseNormalMaps(
Settings::Manager::getBool("auto use object normal maps", "Shaders"));
resourceSystem->getSceneManager()->setNormalMapPattern(
Settings::Manager::getString("normal map pattern", "Shaders"));
resourceSystem->getSceneManager()->setNormalHeightMapPattern(
Settings::Manager::getString("normal height map pattern", "Shaders"));
resourceSystem->getSceneManager()->setAutoUseSpecularMaps(
Settings::Manager::getBool("auto use object specular maps", "Shaders"));
resourceSystem->getSceneManager()->setSpecularMapPattern(
Settings::Manager::getString("specular map pattern", "Shaders"));
resourceSystem->getSceneManager()->setClampLighting(Settings::shaders().mClampLighting);
resourceSystem->getSceneManager()->setAutoUseNormalMaps(Settings::shaders().mAutoUseObjectNormalMaps);
resourceSystem->getSceneManager()->setNormalMapPattern(Settings::shaders().mNormalMapPattern);
resourceSystem->getSceneManager()->setNormalHeightMapPattern(Settings::shaders().mNormalHeightMapPattern);
resourceSystem->getSceneManager()->setAutoUseSpecularMaps(Settings::shaders().mAutoUseObjectSpecularMaps);
resourceSystem->getSceneManager()->setSpecularMapPattern(Settings::shaders().mSpecularMapPattern);
resourceSystem->getSceneManager()->setApplyLightingToEnvMaps(
Settings::Manager::getBool("apply lighting to environment maps", "Shaders"));
resourceSystem->getSceneManager()->setConvertAlphaTestToAlphaToCoverage(
Settings::Manager::getBool("antialias alpha test", "Shaders")
&& Settings::Manager::getInt("antialiasing", "Video") > 1);
Settings::shaders().mApplyLightingToEnvironmentMaps);
resourceSystem->getSceneManager()->setConvertAlphaTestToAlphaToCoverage(shouldAddMSAAIntermediateTarget());
resourceSystem->getSceneManager()->setAdjustCoverageForAlphaTest(
Settings::Manager::getBool("adjust coverage for alpha test", "Shaders"));
Settings::shaders().mAdjustCoverageForAlphaTest);
// Let LightManager choose which backend to use based on our hint. For methods besides legacy lighting, this
// depends on support for various OpenGL extensions.
osg::ref_ptr<SceneUtil::LightManager> sceneRoot
= new SceneUtil::LightManager(lightingMethod == SceneUtil::LightingMethod::FFP);
osg::ref_ptr<SceneUtil::LightManager> sceneRoot = new SceneUtil::LightManager(SceneUtil::LightSettings{
.mLightingMethod = lightingMethod,
.mMaxLights = Settings::shaders().mMaxLights,
.mMaximumLightDistance = Settings::shaders().mMaximumLightDistance,
.mLightFadeStart = Settings::shaders().mLightFadeStart,
.mLightBoundsMultiplier = Settings::shaders().mLightBoundsMultiplier,
});
resourceSystem->getSceneManager()->setLightingMethod(sceneRoot->getLightingMethod());
resourceSystem->getSceneManager()->setSupportedLightingMethods(sceneRoot->getSupportedLightingMethods());
mMinimumAmbientLuminance
= std::clamp(Settings::Manager::getFloat("minimum interior brightness", "Shaders"), 0.f, 1.f);
sceneRoot->setLightingMask(Mask_Lighting);
mSceneRoot = sceneRoot;
@ -396,10 +390,9 @@ namespace MWRender
for (auto itr = shadowDefines.begin(); itr != shadowDefines.end(); itr++)
globalDefines[itr->first] = itr->second;
globalDefines["forcePPL"] = Settings::Manager::getBool("force per pixel lighting", "Shaders") ? "1" : "0";
globalDefines["clamp"] = Settings::Manager::getBool("clamp lighting", "Shaders") ? "1" : "0";
globalDefines["preLightEnv"]
= Settings::Manager::getBool("apply lighting to environment maps", "Shaders") ? "1" : "0";
globalDefines["forcePPL"] = Settings::shaders().mForcePerPixelLighting ? "1" : "0";
globalDefines["clamp"] = Settings::shaders().mClampLighting ? "1" : "0";
globalDefines["preLightEnv"] = Settings::shaders().mApplyLightingToEnvironmentMaps ? "1" : "0";
const bool exponentialFog = Settings::fog().mExponentialFog;
globalDefines["radialFog"] = (exponentialFog || Settings::fog().mRadialFog) ? "1" : "0";
globalDefines["exponentialFog"] = exponentialFog ? "1" : "0";
@ -445,11 +438,11 @@ namespace MWRender
mEffectManager = std::make_unique<EffectManager>(sceneRoot, mResourceSystem);
const std::string& normalMapPattern = Settings::Manager::getString("normal map pattern", "Shaders");
const std::string& heightMapPattern = Settings::Manager::getString("normal height map pattern", "Shaders");
const std::string& specularMapPattern = Settings::Manager::getString("terrain specular map pattern", "Shaders");
const bool useTerrainNormalMaps = Settings::Manager::getBool("auto use terrain normal maps", "Shaders");
const bool useTerrainSpecularMaps = Settings::Manager::getBool("auto use terrain specular maps", "Shaders");
const std::string& normalMapPattern = Settings::shaders().mNormalMapPattern;
const std::string& heightMapPattern = Settings::shaders().mNormalHeightMapPattern;
const std::string& specularMapPattern = Settings::shaders().mTerrainSpecularMapPattern;
const bool useTerrainNormalMaps = Settings::shaders().mAutoUseTerrainNormalMaps;
const bool useTerrainSpecularMaps = Settings::shaders().mAutoUseTerrainSpecularMaps;
mTerrainStorage = std::make_unique<TerrainStorage>(mResourceSystem, normalMapPattern, heightMapPattern,
useTerrainNormalMaps, specularMapPattern, useTerrainSpecularMaps);
@ -472,8 +465,9 @@ namespace MWRender
resourceSystem->getSceneManager()->setOpaqueDepthTex(
mPostProcessor->getTexture(PostProcessor::Tex_OpaqueDepth, 0),
mPostProcessor->getTexture(PostProcessor::Tex_OpaqueDepth, 1));
resourceSystem->getSceneManager()->setSoftParticles(mPostProcessor->softParticlesEnabled());
resourceSystem->getSceneManager()->setSoftParticles(Settings::shaders().mSoftParticles);
resourceSystem->getSceneManager()->setSupportsNormalsRT(mPostProcessor->getSupportsNormalsRT());
resourceSystem->getSceneManager()->setWeatherParticleOcclusion(Settings::shaders().mWeatherParticleOcclusion);
// water goes after terrain for correct waterculling order
mWater = std::make_unique<Water>(
@ -680,15 +674,16 @@ namespace MWRender
// 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)
const float minimumAmbientLuminance = Settings::shaders().mMinimumInteriorBrightness;
if (relativeLuminance < minimumAmbientLuminance)
{
// brighten ambient so it reaches the minimum threshold but no more, we want to mess with content data
// as least we can
if (ambient.r() == 0.f && ambient.g() == 0.f && ambient.b() == 0.f)
ambient = osg::Vec4(
mMinimumAmbientLuminance, mMinimumAmbientLuminance, mMinimumAmbientLuminance, ambient.a());
minimumAmbientLuminance, minimumAmbientLuminance, minimumAmbientLuminance, ambient.a());
else
ambient *= mMinimumAmbientLuminance / relativeLuminance;
ambient *= minimumAmbientLuminance / relativeLuminance;
}
}
@ -1408,8 +1403,6 @@ namespace MWRender
}
else if (it->first == "Shaders" && it->second == "minimum interior brightness")
{
mMinimumAmbientLuminance
= std::clamp(Settings::Manager::getFloat("minimum interior brightness", "Shaders"), 0.f, 1.f);
if (MWMechanics::getPlayer().isInCell())
configureAmbient(*MWMechanics::getPlayer().getCell()->getCell());
}
@ -1418,13 +1411,15 @@ namespace MWRender
|| it->second == "light fade start" || it->second == "max lights"))
{
auto* lightManager = getLightRoot();
lightManager->processChangedSettings(changed);
lightManager->processChangedSettings(Settings::shaders().mLightBoundsMultiplier,
Settings::shaders().mMaximumLightDistance, Settings::shaders().mLightFadeStart);
if (it->second == "max lights" && !lightManager->usingFFP())
{
mViewer->stopThreading();
lightManager->updateMaxLights();
lightManager->updateMaxLights(Settings::shaders().mMaxLights);
auto defines = mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines();
for (const auto& [name, key] : lightManager->getLightDefines())

@ -342,7 +342,6 @@ namespace MWRender
osg::ref_ptr<PerViewUniformStateUpdater> mPerViewUniformStateUpdater;
osg::Vec4f mAmbientColor;
float mMinimumAmbientLuminance;
float mNightEyeFactor;
float mNearClip;

@ -35,6 +35,7 @@
#include "renderbin.hpp"
#include "skyutil.hpp"
#include "util.hpp"
#include "vismask.hpp"
namespace
@ -205,7 +206,8 @@ namespace
{
public:
SkyRTT(osg::Vec2f size, osg::Group* earlyRenderBinRoot)
: RTTNode(static_cast<int>(size.x()), static_cast<int>(size.y()), 0, false, 1, StereoAwareness::Aware)
: RTTNode(static_cast<int>(size.x()), static_cast<int>(size.y()), 0, false, 1, StereoAwareness::Aware,
MWRender::shouldAddMSAAIntermediateTarget())
, mEarlyRenderBinRoot(earlyRenderBinRoot)
{
setDepthBufferInternalFormat(GL_DEPTH24_STENCIL8);
@ -292,7 +294,7 @@ namespace MWRender
mRootNode->addChild(mEarlyRenderBinRoot);
mUnderwaterSwitch = new UnderwaterSwitchCallback(skyroot);
mPrecipitationOcclusion = Settings::Manager::getBool("weather particle occlusion", "Shaders");
mPrecipitationOcclusion = Settings::shaders().mWeatherParticleOcclusion;
mPrecipitationOccluder = std::make_unique<PrecipitationOccluder>(skyroot, parentNode, rootNode, camera);
}

@ -7,6 +7,7 @@
#include <components/resource/imagemanager.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/sceneutil/visitor.hpp>
#include <components/settings/values.hpp>
namespace MWRender
{
@ -67,4 +68,9 @@ namespace MWRender
node->setStateSet(stateset);
}
bool shouldAddMSAAIntermediateTarget()
{
return Settings::shaders().mAntialiasAlphaTest && Settings::Manager::getInt("antialiasing", "Video") > 1;
}
}

@ -3,6 +3,7 @@
#include <osg/NodeCallback>
#include <osg/ref_ptr>
#include <string>
namespace osg
@ -35,6 +36,8 @@ namespace MWRender
// no traverse()
}
};
bool shouldAddMSAAIntermediateTarget();
}
#endif

@ -35,11 +35,14 @@
#include <components/fallback/fallback.hpp>
#include <components/settings/values.hpp>
#include "../mwworld/cellstore.hpp"
#include "renderbin.hpp"
#include "ripples.hpp"
#include "ripplesimulation.hpp"
#include "util.hpp"
#include "vismask.hpp"
namespace MWRender
@ -234,7 +237,7 @@ namespace MWRender
{
public:
Refraction(uint32_t rttSize)
: RTTNode(rttSize, rttSize, 0, false, 1, StereoAwareness::Aware)
: RTTNode(rttSize, rttSize, 0, false, 1, StereoAwareness::Aware, shouldAddMSAAIntermediateTarget())
, mNodeMask(Refraction::sDefaultCullMask)
{
setDepthBufferInternalFormat(GL_DEPTH24_STENCIL8);
@ -315,7 +318,7 @@ namespace MWRender
{
public:
Reflection(uint32_t rttSize, bool isInterior)
: RTTNode(rttSize, rttSize, 0, false, 0, StereoAwareness::Aware)
: RTTNode(rttSize, rttSize, 0, false, 0, StereoAwareness::Aware, shouldAddMSAAIntermediateTarget())
{
setInterior(isInterior);
setDepthBufferInternalFormat(GL_DEPTH24_STENCIL8);

@ -107,7 +107,7 @@ add_component_dir (sceneutil
clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller
lightmanager lightutil positionattitudetransform workqueue pathgridutil waterutil writescene serialize optimizer
detourdebugdraw navmesh agentpath shadow mwshadowtechnique recastmesh shadowsbin osgacontroller rtt
screencapture depth color riggeometryosgaextension extradata unrefqueue lightcommon
screencapture depth color riggeometryosgaextension extradata unrefqueue lightcommon lightingmethod
)
add_component_dir (nif

@ -1118,10 +1118,10 @@ namespace Resource
stats->setAttribute(frameNumber, "Node", mCache->getCacheSize());
}
Shader::ShaderVisitor* SceneManager::createShaderVisitor(const std::string& shaderPrefix)
osg::ref_ptr<Shader::ShaderVisitor> SceneManager::createShaderVisitor(const std::string& shaderPrefix)
{
Shader::ShaderVisitor* shaderVisitor
= new Shader::ShaderVisitor(*mShaderManager.get(), *mImageManager, shaderPrefix);
osg::ref_ptr<Shader::ShaderVisitor> shaderVisitor(
new Shader::ShaderVisitor(*mShaderManager.get(), *mImageManager, shaderPrefix));
shaderVisitor->setForceShaders(mForceShaders);
shaderVisitor->setAutoUseNormalMaps(mAutoUseNormalMaps);
shaderVisitor->setNormalMapPattern(mNormalMapPattern);
@ -1132,6 +1132,7 @@ namespace Resource
shaderVisitor->setConvertAlphaTestToAlphaToCoverage(mConvertAlphaTestToAlphaToCoverage);
shaderVisitor->setAdjustCoverageForAlphaTest(mAdjustCoverageForAlphaTest);
shaderVisitor->setSupportsNormalsRT(mSupportsNormalsRT);
shaderVisitor->setWeatherParticleOcclusion(mWeatherParticleOcclusion);
return shaderVisitor;
}
}

@ -227,8 +227,10 @@ namespace Resource
void setSoftParticles(bool enabled) { mSoftParticles = enabled; }
bool getSoftParticles() const { return mSoftParticles; }
void setWeatherParticleOcclusion(bool value) { mWeatherParticleOcclusion = value; }
private:
Shader::ShaderVisitor* createShaderVisitor(const std::string& shaderPrefix = "objects");
osg::ref_ptr<Shader::ShaderVisitor> createShaderVisitor(const std::string& shaderPrefix = "objects");
osg::ref_ptr<osg::Node> loadErrorMarker();
osg::ref_ptr<osg::Node> cloneErrorMarker();
@ -248,6 +250,7 @@ namespace Resource
bool mSupportsNormalsRT;
std::array<osg::ref_ptr<osg::Texture>, 2> mOpaqueDepthTex;
bool mSoftParticles = false;
bool mWeatherParticleOcclusion = false;
osg::ref_ptr<Resource::SharedStateManager> mSharedStateManager;
mutable std::mutex mSharedStateMutex;

@ -0,0 +1,14 @@
#ifndef OPENMW_COMPONENTS_SCENEUTIL_LIGHTINGMETHOD_H
#define OPENMW_COMPONENTS_SCENEUTIL_LIGHTINGMETHOD_H
namespace SceneUtil
{
enum class LightingMethod
{
FFP,
PerObjectUniform,
SingleUBO,
};
}
#endif

@ -23,8 +23,6 @@
namespace
{
constexpr int maxLightsLowerLimit = 2;
constexpr int maxLightsUpperLimit = 64;
constexpr int ffpMaxLights = 8;
bool sortLights(const SceneUtil::LightManager::LightSourceViewBound* left,
@ -817,7 +815,7 @@ namespace SceneUtil
return "";
}
LightManager::LightManager(bool ffp)
LightManager::LightManager(const LightSettings& settings)
: mStartLight(0)
, mLightingMask(~0u)
, mSun(nullptr)
@ -835,18 +833,15 @@ namespace SceneUtil
setUpdateCallback(new LightManagerUpdateCallback);
if (ffp)
if (settings.mLightingMethod == LightingMethod::FFP)
{
initFFP(ffpMaxLights);
return;
}
const std::string& lightingMethodString = Settings::Manager::getString("lighting method", "Shaders");
auto lightingMethod = LightManager::getLightingMethodFromString(lightingMethodString);
static bool hasLoggedWarnings = false;
if (lightingMethod == LightingMethod::SingleUBO && !hasLoggedWarnings)
if (settings.mLightingMethod == LightingMethod::SingleUBO && !hasLoggedWarnings)
{
if (!supportsUBO)
Log(Debug::Warning)
@ -857,15 +852,12 @@ namespace SceneUtil
hasLoggedWarnings = true;
}
const int targetLights
= std::clamp(Settings::Manager::getInt("max lights", "Shaders"), maxLightsLowerLimit, maxLightsUpperLimit);
if (!supportsUBO || !supportsGPU4 || lightingMethod == LightingMethod::PerObjectUniform)
initPerObjectUniform(targetLights);
if (!supportsUBO || !supportsGPU4 || settings.mLightingMethod == LightingMethod::PerObjectUniform)
initPerObjectUniform(settings.mMaxLights);
else
initSingleUBO(targetLights);
initSingleUBO(settings.mMaxLights);
updateSettings();
updateSettings(settings.mLightBoundsMultiplier, settings.mMaximumLightDistance, settings.mLightFadeStart);
getOrCreateStateSet()->addUniform(new osg::Uniform("PointLightCount", 0));
@ -931,18 +923,18 @@ namespace SceneUtil
return defines;
}
void LightManager::processChangedSettings(const Settings::CategorySettingVector& changed)
void LightManager::processChangedSettings(
float lightBoundsMultiplier, float maximumLightDistance, float lightFadeStart)
{
updateSettings();
updateSettings(lightBoundsMultiplier, maximumLightDistance, lightFadeStart);
}
void LightManager::updateMaxLights()
void LightManager::updateMaxLights(int maxLights)
{
if (usingFFP())
return;
setMaxLights(
std::clamp(Settings::Manager::getInt("max lights", "Shaders"), maxLightsLowerLimit, maxLightsUpperLimit));
setMaxLights(maxLights);
if (getLightingMethod() == LightingMethod::PerObjectUniform)
{
@ -954,20 +946,15 @@ namespace SceneUtil
cache.clear();
}
void LightManager::updateSettings()
void LightManager::updateSettings(float lightBoundsMultiplier, float maximumLightDistance, float lightFadeStart)
{
if (getLightingMethod() == LightingMethod::FFP)
return;
mPointLightRadiusMultiplier
= std::clamp(Settings::Manager::getFloat("light bounds multiplier", "Shaders"), 0.f, 5.f);
mPointLightFadeEnd = std::max(0.f, Settings::Manager::getFloat("maximum light distance", "Shaders"));
mPointLightRadiusMultiplier = lightBoundsMultiplier;
mPointLightFadeEnd = maximumLightDistance;
if (mPointLightFadeEnd > 0)
{
mPointLightFadeStart = std::clamp(Settings::Manager::getFloat("light fade start", "Shaders"), 0.f, 1.f);
mPointLightFadeStart = mPointLightFadeEnd * mPointLightFadeStart;
}
mPointLightFadeStart = mPointLightFadeEnd * lightFadeStart;
}
void LightManager::initFFP(int targetLights)

@ -12,7 +12,8 @@
#include <osg/observer_ptr>
#include <components/sceneutil/nodecallback.hpp>
#include <components/settings/settings.hpp>
#include "lightingmethod.hpp"
namespace SceneUtil
{
@ -82,13 +83,6 @@ namespace SceneUtil
std::array<osg::ref_ptr<osg::Uniform>, 2> mUniformCount;
};
enum class LightingMethod
{
FFP,
PerObjectUniform,
SingleUBO,
};
/// LightSource managed by a LightManager.
/// @par Typically used for point lights. Spot lights are not supported yet. Directional lights affect the whole
/// scene
@ -186,6 +180,15 @@ namespace SceneUtil
osg::ref_ptr<LightBuffer> mTemplate;
};
struct LightSettings
{
LightingMethod mLightingMethod = LightingMethod::FFP;
int mMaxLights = 0;
float mMaximumLightDistance = 0;
float mLightFadeStart = 0;
float mLightBoundsMultiplier = 0;
};
/// @brief Decorator node implementing the rendering of any number of LightSources that can be anywhere in the
/// subgraph.
class LightManager : public osg::Group
@ -212,7 +215,7 @@ namespace SceneUtil
META_Node(SceneUtil, LightManager)
LightManager(bool ffp = true);
explicit LightManager(const LightSettings& settings = LightSettings{});
LightManager(const LightManager& copy, const osg::CopyOp& copyop);
@ -264,10 +267,10 @@ namespace SceneUtil
std::map<std::string, std::string> getLightDefines() const;
void processChangedSettings(const Settings::CategorySettingVector& changed);
void processChangedSettings(float lightBoundsMultiplier, float maximumLightDistance, float lightFadeStart);
/// Not thread safe, it is the responsibility of the caller to stop/start threading on the viewer
void updateMaxLights();
void updateMaxLights(int maxLights);
osg::ref_ptr<osg::Uniform> generateLightBufferUniform(const osg::Matrixf& sun);
@ -281,7 +284,7 @@ namespace SceneUtil
void initPerObjectUniform(int targetLights);
void initSingleUBO(int targetLights);
void updateSettings();
void updateSettings(float lightBoundsMultiplier, float maximumLightDistance, float lightFadeStart);
void setLightingMethod(LightingMethod method);
void setMaxLights(int value);

@ -20,7 +20,7 @@ namespace SceneUtil
};
RTTNode::RTTNode(uint32_t textureWidth, uint32_t textureHeight, uint32_t samples, bool generateMipmaps,
int renderOrderNum, StereoAwareness stereoAwareness)
int renderOrderNum, StereoAwareness stereoAwareness, bool addMSAAIntermediateTarget)
: mTextureWidth(textureWidth)
, mTextureHeight(textureHeight)
, mSamples(samples)
@ -29,6 +29,7 @@ namespace SceneUtil
, mDepthBufferInternalFormat(SceneUtil::AutoDepth::depthInternalFormat())
, mRenderOrderNum(renderOrderNum)
, mStereoAwareness(stereoAwareness)
, mAddMSAAIntermediateTarget(addMSAAIntermediateTarget)
{
addCullCallback(new CullCallback);
setCullingActive(false);
@ -206,7 +207,8 @@ namespace SceneUtil
camera->attach(osg::Camera::COLOR_BUFFER, vdd->mColorTexture, 0,
Stereo::osgFaceControlledByMultiviewShader(), mGenerateMipmaps, mSamples);
SceneUtil::attachAlphaToCoverageFriendlyFramebufferToCamera(camera, osg::Camera::COLOR_BUFFER,
vdd->mColorTexture, 0, Stereo::osgFaceControlledByMultiviewShader(), mGenerateMipmaps);
vdd->mColorTexture, 0, Stereo::osgFaceControlledByMultiviewShader(), mGenerateMipmaps,
mAddMSAAIntermediateTarget);
}
if (camera->getBufferAttachmentMap().count(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER) == 0)
@ -234,8 +236,8 @@ namespace SceneUtil
{
vdd->mColorTexture = createTexture(mColorBufferInternalFormat);
camera->attach(osg::Camera::COLOR_BUFFER, vdd->mColorTexture, 0, 0, mGenerateMipmaps, mSamples);
SceneUtil::attachAlphaToCoverageFriendlyFramebufferToCamera(
camera, osg::Camera::COLOR_BUFFER, vdd->mColorTexture, 0, 0, mGenerateMipmaps);
SceneUtil::attachAlphaToCoverageFriendlyFramebufferToCamera(camera, osg::Camera::COLOR_BUFFER,
vdd->mColorTexture, 0, 0, mGenerateMipmaps, mAddMSAAIntermediateTarget);
}
if (camera->getBufferAttachmentMap().count(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER) == 0)

@ -49,7 +49,7 @@ namespace SceneUtil
};
RTTNode(uint32_t textureWidth, uint32_t textureHeight, uint32_t samples, bool generateMipmaps,
int renderOrderNum, StereoAwareness stereoAwareness);
int renderOrderNum, StereoAwareness stereoAwareness, bool addMSAAIntermediateTarget);
~RTTNode();
osg::Texture* getColorTexture(osgUtil::CullVisitor* cv);
@ -110,6 +110,7 @@ namespace SceneUtil
GLint mDepthBufferInternalFormat;
int mRenderOrderNum;
StereoAwareness mStereoAwareness;
bool mAddMSAAIntermediateTarget;
};
}
#endif

@ -239,13 +239,12 @@ namespace SceneUtil
return glowUpdater;
}
bool attachAlphaToCoverageFriendlyFramebufferToCamera(osg::Camera* camera, osg::Camera::BufferComponent buffer,
osg::Texture* texture, unsigned int level, unsigned int face, bool mipMapGeneration)
void attachAlphaToCoverageFriendlyFramebufferToCamera(osg::Camera* camera, osg::Camera::BufferComponent buffer,
osg::Texture* texture, unsigned int level, unsigned int face, bool mipMapGeneration,
bool addMSAAIntermediateTarget)
{
unsigned int samples = 0;
unsigned int colourSamples = 0;
bool addMSAAIntermediateTarget = Settings::Manager::getBool("antialias alpha test", "Shaders")
&& Settings::Manager::getInt("antialiasing", "Video") > 1;
if (addMSAAIntermediateTarget)
{
// Alpha-to-coverage requires a multisampled framebuffer.
@ -255,7 +254,6 @@ namespace SceneUtil
colourSamples = 1;
}
camera->attach(buffer, texture, level, face, mipMapGeneration, samples, colourSamples);
return addMSAAIntermediateTarget;
}
OperationSequence::OperationSequence(bool keep)

@ -96,8 +96,9 @@ namespace SceneUtil
const osg::Vec4f& glowColor, float glowDuration = -1);
// Alpha-to-coverage requires a multisampled framebuffer, so we need to set that up for RTTs
bool attachAlphaToCoverageFriendlyFramebufferToCamera(osg::Camera* camera, osg::Camera::BufferComponent buffer,
osg::Texture* texture, unsigned int level = 0, unsigned int face = 0, bool mipMapGeneration = false);
void attachAlphaToCoverageFriendlyFramebufferToCamera(osg::Camera* camera, osg::Camera::BufferComponent buffer,
osg::Texture* texture, unsigned int level, unsigned int face, bool mipMapGeneration,
bool addMSAAIntermediateTarget);
class OperationSequence : public osg::Operation
{

@ -1,6 +1,7 @@
#ifndef OPENMW_COMPONENTS_SETTINGS_CATEGORIES_SHADERS_H
#define OPENMW_COMPONENTS_SETTINGS_CATEGORIES_SHADERS_H
#include "components/sceneutil/lightingmethod.hpp"
#include "components/settings/sanitizerimpl.hpp"
#include "components/settings/settingvalue.hpp"
@ -30,11 +31,11 @@ namespace Settings
SettingValue<std::string> mSpecularMapPattern{ mIndex, "Shaders", "specular map pattern" };
SettingValue<std::string> mTerrainSpecularMapPattern{ mIndex, "Shaders", "terrain specular map pattern" };
SettingValue<bool> mApplyLightingToEnvironmentMaps{ mIndex, "Shaders", "apply lighting to environment maps" };
SettingValue<std::string> mLightingMethod{ mIndex, "Shaders", "lighting method",
makeEnumSanitizerString({ "legacy", "shaders compatibility", "shaders" }) };
SettingValue<SceneUtil::LightingMethod> mLightingMethod{ mIndex, "Shaders", "lighting method" };
SettingValue<float> mLightBoundsMultiplier{ mIndex, "Shaders", "light bounds multiplier",
makeClampSanitizerFloat(0, 5) };
SettingValue<float> mMaximumLightDistance{ mIndex, "Shaders", "maximum light distance" };
SettingValue<float> mMaximumLightDistance{ mIndex, "Shaders", "maximum light distance",
makeMaxSanitizerFloat(0) };
SettingValue<float> mLightFadeStart{ mIndex, "Shaders", "light fade start", makeClampSanitizerFloat(0, 1) };
SettingValue<int> mMaxLights{ mIndex, "Shaders", "max lights", makeClampSanitizerInt(2, 64) };
SettingValue<float> mMinimumInteriorBrightness{ mIndex, "Shaders", "minimum interior brightness",

@ -16,6 +16,7 @@
#endif
#include <components/debug/debuglog.hpp>
#include <components/files/configurationmanager.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/conversion.hpp>
@ -87,6 +88,21 @@ namespace Settings
stream << value;
return stream.str();
}
std::string toString(SceneUtil::LightingMethod value)
{
switch (value)
{
case SceneUtil::LightingMethod::FFP:
return "legacy";
case SceneUtil::LightingMethod::PerObjectUniform:
return "shaders compatibility";
case SceneUtil::LightingMethod::SingleUBO:
return "shaders";
}
throw std::invalid_argument("Invalid LightingMethod value: " + std::to_string(static_cast<int>(value)));
}
}
CategorySettingValueMap Manager::mDefaultSettings = CategorySettingValueMap();
@ -459,6 +475,11 @@ namespace Settings
setString(setting, category, value.print());
}
void Manager::set(std::string_view setting, std::string_view category, SceneUtil::LightingMethod value)
{
setString(setting, category, toString(value));
}
void Manager::recordInit(std::string_view setting, std::string_view category)
{
sInitialized.emplace(category, setting);
@ -491,4 +512,18 @@ namespace Settings
throw std::invalid_argument("Invalid navigation mesh rendering mode: " + std::string(value));
}
SceneUtil::LightingMethod parseLightingMethod(std::string_view value)
{
if (value == "legacy")
return SceneUtil::LightingMethod::FFP;
if (value == "shaders compatibility")
return SceneUtil::LightingMethod::PerObjectUniform;
if (value == "shaders")
return SceneUtil::LightingMethod::SingleUBO;
constexpr const char* fallback = "shaders compatibility";
Log(Debug::Warning) << "Unknown lighting method '" << value << "', returning fallback '" << fallback << "'";
return SceneUtil::LightingMethod::PerObjectUniform;
}
}

@ -5,7 +5,8 @@
#include "gyroscopeaxis.hpp"
#include "navmeshrendermode.hpp"
#include "components/detournavigator/collisionshapetype.hpp"
#include <components/detournavigator/collisionshapetype.hpp>
#include <components/sceneutil/lightingmethod.hpp>
#include <filesystem>
#include <set>
@ -110,6 +111,7 @@ namespace Settings
static void set(std::string_view setting, std::string_view category, DetourNavigator::CollisionShapeType value);
static void set(std::string_view setting, std::string_view category, const std::vector<std::string>& value);
static void set(std::string_view setting, std::string_view category, const MyGUI::Colour& value);
static void set(std::string_view setting, std::string_view category, SceneUtil::LightingMethod value);
private:
static std::set<std::pair<std::string_view, std::string_view>> sInitialized;
@ -215,6 +217,15 @@ namespace Settings
{
return parseNavMeshRenderMode(getString(setting, category));
}
SceneUtil::LightingMethod parseLightingMethod(std::string_view value);
template <>
inline SceneUtil::LightingMethod Manager::getImpl<SceneUtil::LightingMethod>(
std::string_view setting, std::string_view category)
{
return parseLightingMethod(getString(setting, category));
}
}
#endif // COMPONENTS_SETTINGS_H

@ -40,6 +40,7 @@ namespace Settings
MyGuiColour,
GyroscopeAxis,
NavMeshRenderMode,
LightingMethod,
};
template <class T>
@ -147,6 +148,12 @@ namespace Settings
return SettingValueType::NavMeshRenderMode;
}
template <>
inline constexpr SettingValueType getSettingValueType<SceneUtil::LightingMethod>()
{
return SettingValueType::LightingMethod;
}
inline constexpr std::string_view getSettingValueTypeName(SettingValueType type)
{
switch (type)
@ -185,6 +192,8 @@ namespace Settings
return "gyroscope axis";
case SettingValueType::NavMeshRenderMode:
return "navmesh render mode";
case SettingValueType::LightingMethod:
return "lighting method";
}
return "unsupported";
}

@ -680,8 +680,7 @@ namespace Shader
bool particleOcclusion = false;
node.getUserValue("particleOcclusion", particleOcclusion);
defineMap["particleOcclusion"]
= particleOcclusion && Settings::Manager::getBool("weather particle occlusion", "Shaders") ? "1" : "0";
defineMap["particleOcclusion"] = particleOcclusion && mWeatherParticleOcclusion ? "1" : "0";
if (reqs.mAlphaBlend && mSupportsNormalsRT)
{

@ -51,6 +51,8 @@ namespace Shader
void setSupportsNormalsRT(bool supports) { mSupportsNormalsRT = supports; }
void setWeatherParticleOcclusion(bool value) { mWeatherParticleOcclusion = value; }
void apply(osg::Node& node) override;
void apply(osg::Drawable& drawable) override;
@ -78,6 +80,7 @@ namespace Shader
bool mAdjustCoverageForAlphaTest;
bool mSupportsNormalsRT;
bool mWeatherParticleOcclusion = false;
ShaderManager& mShaderManager;
Resource::ImageManager& mImageManager;

Loading…
Cancel
Save