clear up force shaders and make it less convoluted

pull/3065/head
glassmancody.info 4 years ago
parent 8ce65232ff
commit 9e80091aff

@ -1,6 +1,6 @@
#include "advancedpage.hpp" #include "advancedpage.hpp"
#include <unordered_map> #include <array>
#include <components/config/gamesettings.hpp> #include <components/config/gamesettings.hpp>
#include <components/config/launchersettings.hpp> #include <components/config/launchersettings.hpp>
@ -256,7 +256,7 @@ void Launcher::AdvancedPage::saveSettings()
mEngineSettings.setInt("viewing distance", "Camera", convertToUnits(viewingDistance)); mEngineSettings.setInt("viewing distance", "Camera", convertToUnits(viewingDistance));
} }
static std::unordered_map<int, std::string> lightingMethodMap = {{0, "legacy"}, {1, "shaders compatibility"}, {2, "shaders"}}; static std::array<std::string, 3> lightingMethodMap = {"legacy", "shaders compatibility", "shaders"};
mEngineSettings.setString("lighting method", "Shaders", lightingMethodMap[lightingMethodComboBox->currentIndex()]); mEngineSettings.setString("lighting method", "Shaders", lightingMethodMap[lightingMethodComboBox->currentIndex()]);
} }

@ -11,12 +11,15 @@
#include <iomanip> #include <iomanip>
#include <numeric> #include <numeric>
#include <array>
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <components/misc/constants.hpp> #include <components/misc/constants.hpp>
#include <components/widgets/sharedstatebutton.hpp> #include <components/widgets/sharedstatebutton.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/lightmanager.hpp> #include <components/sceneutil/lightmanager.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -104,6 +107,22 @@ namespace
if (!widget->getUserString(settingMax).empty()) if (!widget->getUserString(settingMax).empty())
max = MyGUI::utility::parseFloat(widget->getUserString(settingMax)); max = MyGUI::utility::parseFloat(widget->getUserString(settingMax));
} }
const char* getLightingMethodCaptionText(SceneUtil::LightingMethod lightingMethod)
{
switch (lightingMethod)
{
case SceneUtil::LightingMethod::FFP:
return "Emulates fixed function pipeline lighting, advanced light settings are disabled when this mode is active";
case SceneUtil::LightingMethod::PerObjectUniform:
return "Removes limit of 8 lights per object, fixes lighting attenuation, and enables groundcover lighting and light fade."
"\n\nDesigned for compatibility across hardware, and is not meant for large max light counts.";
case SceneUtil::LightingMethod::SingleUBO:
return "Removes limit of 8 lights per object, fixes lighting attenuation, and enables groundcover lighting and light fade."
"\n\nDesigned for more modern hardware and large max light counts.";
}
return "";
}
} }
namespace MWGui namespace MWGui
@ -286,36 +305,6 @@ namespace MWGui
waterReflectionDetail = std::min(5, std::max(0, waterReflectionDetail)); waterReflectionDetail = std::min(5, std::max(0, waterReflectionDetail));
mWaterReflectionDetail->setIndexSelected(waterReflectionDetail); mWaterReflectionDetail->setIndexSelected(waterReflectionDetail);
auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString(Settings::Manager::getString("lighting method", "Shaders"));
mLightingMethodText->setCaption(SceneUtil::LightManager::getLightingMethodString(lightingMethod));
if (lightingMethod == SceneUtil::LightingMethod::FFP || !Settings::Manager::getBool("force shaders", "Shaders"))
{
MyGUI::Widget* parent = mLightSettingOverlay->getParent();
mLightSettingOverlay->setEnabled(false);
mLightSettingOverlay->setAlpha(0.8);
parent->setUserString("ToolTipType", "Layout");
parent->setUserString("ToolTipLayout", "TextToolTip");
parent->setUserString("Caption_Text", "Unavailable with current settings.");
parent->setEnabled(true);
}
else
{
std::string captionText;
if (lightingMethod == SceneUtil::LightingMethod::FFP)
captionText =
"Emulates fixed function pipeline lighting, advanced light settings are disabled when this mode is active";
else if (lightingMethod == SceneUtil::LightingMethod::PerObjectUniform)
captionText =
"Removes limit of 8 lights per object, fixes lighting attenuation, and enables groundcover lighting and light fade."
"\n\nDesigned for compatibility across hardware, and is not meant for large max light counts.";
else if (lightingMethod == SceneUtil::LightingMethod::SingleUBO)
captionText =
"Removes limit of 8 lights per object, fixes lighting attenuation, and enables groundcover lighting and light fade."
"\n\nDesigned for more modern hardware and large max light counts.";
mLightingMethodText->setUserString("Caption_Text", captionText);
}
mWindowBorderButton->setEnabled(!Settings::Manager::getBool("fullscreen", "Video")); mWindowBorderButton->setEnabled(!Settings::Manager::getBool("fullscreen", "Video"));
mKeyboardSwitch->setStateSelected(true); mKeyboardSwitch->setStateSelected(true);
@ -411,7 +400,7 @@ namespace MWGui
if (selectedButton == 1 || selectedButton == -1) if (selectedButton == 1 || selectedButton == -1)
return; return;
const std::vector<std::string> settings = {"light bounds multiplier", "maximum light distance", "light fade start", "minimum interior brightness", "max lights"}; constexpr std::array<const char*, 5> settings = {"light bounds multiplier", "maximum light distance", "light fade start", "minimum interior brightness", "max lights"};
for (const auto& setting : settings) for (const auto& setting : settings)
Settings::Manager::setString(setting, "Shaders", Settings::Manager::mDefaultSettings[{"Shaders", setting}]); Settings::Manager::setString(setting, "Shaders", Settings::Manager::mDefaultSettings[{"Shaders", setting}]);
@ -617,6 +606,25 @@ namespace MWGui
layoutControlsBox(); layoutControlsBox();
} }
void SettingsWindow::updateLightSettings()
{
auto lightingMethod = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getLightingMethod();
mLightingMethodText->setCaption(SceneUtil::LightManager::getLightingMethodString(lightingMethod));
if (lightingMethod == SceneUtil::LightingMethod::FFP || !Settings::Manager::getBool("force shaders", "Shaders"))
{
MyGUI::Widget* parent = mLightSettingOverlay->getParent();
mLightSettingOverlay->setEnabled(false);
mLightSettingOverlay->setAlpha(0.8);
parent->setUserString("ToolTipType", "Layout");
parent->setUserString("ToolTipLayout", "TextToolTip");
parent->setUserString("Caption_Text", "Unavailable with current settings.");
parent->setEnabled(true);
}
mLightingMethodText->setUserString("Caption_Text", getLightingMethodCaptionText(lightingMethod));
}
void SettingsWindow::layoutControlsBox() void SettingsWindow::layoutControlsBox()
{ {
const int h = 18; const int h = 18;
@ -679,6 +687,7 @@ namespace MWGui
{ {
highlightCurrentResolution(); highlightCurrentResolution();
updateControlsBox(); updateControlsBox();
updateLightSettings();
resetScrollbars(); resetScrollbars();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton); MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton);
} }

@ -19,6 +19,8 @@ namespace MWGui
void updateControlsBox(); void updateControlsBox();
void updateLightSettings();
void onResChange(int, int) override { center(); } void onResChange(int, int) override { center(); }
protected: protected:

@ -522,7 +522,7 @@ namespace MWRender
stateset->addUniform(new osg::Uniform("colorMode", 0), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); stateset->addUniform(new osg::Uniform("colorMode", 0), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
} }
void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/) override
{ {
osg::Material* material = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL)); osg::Material* material = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
material->setAlpha(osg::Material::FRONT_AND_BACK, mAlpha); material->setAlpha(osg::Material::FRONT_AND_BACK, mAlpha);

@ -201,17 +201,14 @@ namespace MWRender
, mFieldOfViewOverridden(false) , mFieldOfViewOverridden(false)
, mFieldOfViewOverride(0.f) , mFieldOfViewOverride(0.f)
{ {
auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString(Settings::Manager::getString("lighting method", "Shaders"));
bool usingFFPLighting = lightingMethod == SceneUtil::LightingMethod::FFP;
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem); resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders"); resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders");
bool explicitlyForceShaders = Settings::Manager::getBool("force shaders", "Shaders");
// Shadows and radial fog have problems with fixed-function mode // Shadows and radial fog have problems with fixed-function mode
bool forceShaders = Settings::Manager::getBool("radial fog", "Shaders") || Settings::Manager::getBool("force shaders", "Shaders") || Settings::Manager::getBool("enable shadows", "Shadows") || usingFFPLighting; bool forceShaders = Settings::Manager::getBool("radial fog", "Shaders") || explicitlyForceShaders || Settings::Manager::getBool("enable shadows", "Shadows");
bool clampLighting = Settings::Manager::getBool("clamp lighting", "Shaders");
resourceSystem->getSceneManager()->setForceShaders(forceShaders); resourceSystem->getSceneManager()->setForceShaders(forceShaders);
// FIXME: calling dummy method because terrain needs to know whether lighting is clamped // FIXME: calling dummy method because terrain needs to know whether lighting is clamped
resourceSystem->getSceneManager()->setClampLighting(clampLighting); resourceSystem->getSceneManager()->setClampLighting(Settings::Manager::getBool("clamp lighting", "Shaders"));
resourceSystem->getSceneManager()->setAutoUseNormalMaps(Settings::Manager::getBool("auto use object normal maps", "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()->setNormalMapPattern(Settings::Manager::getString("normal map pattern", "Shaders"));
resourceSystem->getSceneManager()->setNormalHeightMapPattern(Settings::Manager::getString("normal height map pattern", "Shaders")); resourceSystem->getSceneManager()->setNormalHeightMapPattern(Settings::Manager::getString("normal height map pattern", "Shaders"));
@ -220,11 +217,11 @@ namespace MWRender
resourceSystem->getSceneManager()->setApplyLightingToEnvMaps(Settings::Manager::getBool("apply lighting to environment maps", "Shaders")); 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); resourceSystem->getSceneManager()->setConvertAlphaTestToAlphaToCoverage(Settings::Manager::getBool("antialias alpha test", "Shaders") && Settings::Manager::getInt("antialiasing", "Video") > 1);
osg::ref_ptr<SceneUtil::LightManager> sceneRoot = new SceneUtil::LightManager(!forceShaders || usingFFPLighting); auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString(Settings::Manager::getString("lighting method", "Shaders"));
// Let LightManager choose which backend to use based on our hint, mostly depends on support for UBOs // 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(!explicitlyForceShaders || lightingMethod == SceneUtil::LightingMethod::FFP);
resourceSystem->getSceneManager()->getShaderManager().setLightingMethod(sceneRoot->getLightingMethod()); resourceSystem->getSceneManager()->getShaderManager().setLightingMethod(sceneRoot->getLightingMethod());
resourceSystem->getSceneManager()->setLightingMethod(sceneRoot->getLightingMethod()); resourceSystem->getSceneManager()->setLightingMethod(sceneRoot->getLightingMethod());
Settings::Manager::setString("lighting method", "Shaders", SceneUtil::LightManager::getLightingMethodString(sceneRoot->getLightingMethod()));
mMinimumAmbientLuminance = std::clamp(Settings::Manager::getFloat("minimum interior brightness", "Shaders"), 0.f, 1.f); mMinimumAmbientLuminance = std::clamp(Settings::Manager::getFloat("minimum interior brightness", "Shaders"), 0.f, 1.f);
@ -546,9 +543,9 @@ namespace MWRender
if (needsAdjusting) if (needsAdjusting)
{ {
static constexpr float pR = 0.2126; constexpr float pR = 0.2126;
static constexpr float pG = 0.7152; constexpr float pG = 0.7152;
static constexpr float pB = 0.0722; constexpr float pB = 0.0722;
// we already work in linear RGB so no conversions are needed for the luminosity function // 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(); float relativeLuminance = pR*ambient.r() + pG*ambient.g() + pB*ambient.b();

@ -0,0 +1,15 @@
#ifndef MISC_HASH_H
#define MISC_HASH_H
namespace Misc
{
/// Implemented similar to the boost::hash_combine
template <class T>
inline void hashCombine(std::size_t& seed, const T& v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
}
#endif

@ -1,5 +1,7 @@
#include "lightmanager.hpp" #include "lightmanager.hpp"
#include <array>
#include <osg/BufferObject> #include <osg/BufferObject>
#include <osg/BufferIndexBinding> #include <osg/BufferIndexBinding>
#include <osg/Endian> #include <osg/Endian>
@ -8,20 +10,13 @@
#include <components/sceneutil/util.hpp> #include <components/sceneutil/util.hpp>
#include <components/misc/hash.hpp>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
namespace namespace
{ {
/* similar to the boost::hash_combine */
template <class T>
inline void hash_combine(std::size_t& seed, const T& v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
bool sortLights(const SceneUtil::LightManager::LightSourceViewBound* left, const SceneUtil::LightManager::LightSourceViewBound* right) bool sortLights(const SceneUtil::LightManager::LightSourceViewBound* left, const SceneUtil::LightManager::LightSourceViewBound* right)
{ {
static auto constexpr illuminationBias = 81.f; static auto constexpr illuminationBias = 81.f;
@ -124,39 +119,37 @@ namespace SceneUtil
{ {
// Deal with negative lights (negative diffuse) by passing a sign bit in the unused alpha component // Deal with negative lights (negative diffuse) by passing a sign bit in the unused alpha component
auto positiveColor = value; auto positiveColor = value;
float signBit = 1.0; unsigned int signBit = 1;
if (value[0] < 0) if (value[0] < 0)
{ {
positiveColor *= -1.0; positiveColor *= -1.0;
signBit = -1.0; signBit = -1;
} }
*(unsigned int*)(&(*mData)[getOffset(index, Diffuse)]) = asRGBA(positiveColor); unsigned int packedColor = asRGBA(positiveColor);
*(int*)(&(*mData)[getOffset(index, DiffuseSign)]) = signBit; std::memcpy(&(*mData)[getOffset(index, Diffuse)], &packedColor, sizeof(unsigned int));
std::memcpy(&(*mData)[getOffset(index, DiffuseSign)], &signBit, sizeof(unsigned int));
} }
void setAmbient(int index, const osg::Vec4& value) void setAmbient(int index, const osg::Vec4& value)
{ {
*(unsigned int*)(&(*mData)[getOffset(index, Ambient)]) = asRGBA(value); unsigned int packed = asRGBA(value);
std::memcpy(&(*mData)[getOffset(index, Ambient)], &packed, sizeof(unsigned int));
} }
void setSpecular(int index, const osg::Vec4& value) void setSpecular(int index, const osg::Vec4& value)
{ {
*(unsigned int*)(&(*mData)[getOffset(index, Specular)]) = asRGBA(value); unsigned int packed = asRGBA(value);
std::memcpy(&(*mData)[getOffset(index, Specular)], &packed, sizeof(unsigned int));
} }
void setPosition(int index, const osg::Vec4& value) void setPosition(int index, const osg::Vec4& value)
{ {
*(osg::Vec4*)(&(*mData)[getOffset(index, Position)]) = value; std::memcpy(&(*mData)[getOffset(index, Position)], value.ptr(), sizeof(osg::Vec4f));
} }
void setAttenuationRadius(int index, const osg::Vec4& value) void setAttenuationRadius(int index, const osg::Vec4& value)
{ {
*(osg::Vec4*)(&(*mData)[getOffset(index, AttenuationRadius)]) = value; std::memcpy(&(*mData)[getOffset(index, AttenuationRadius)], value.ptr(), sizeof(osg::Vec4f));
}
auto getPosition(int index)
{
return *(osg::Vec4*)(&(*mData)[getOffset(index, Position)]);
} }
auto& getData() auto& getData()
@ -186,8 +179,8 @@ namespace SceneUtil
void configureLayout(int offsetColors, int offsetPosition, int offsetAttenuationRadius, int size, int stride) void configureLayout(int offsetColors, int offsetPosition, int offsetAttenuationRadius, int size, int stride)
{ {
static constexpr auto sizeofVec4 = sizeof(GL_FLOAT) * osg::Vec4::num_components; constexpr auto sizeofVec4 = sizeof(GL_FLOAT) * osg::Vec4::num_components;
static constexpr auto sizeofFloat = sizeof(GL_FLOAT); constexpr auto sizeofFloat = sizeof(GL_FLOAT);
mOffsets[Diffuse] = offsetColors / sizeofFloat; mOffsets[Diffuse] = offsetColors / sizeofFloat;
mOffsets[Ambient] = mOffsets[Diffuse] + 1; mOffsets[Ambient] = mOffsets[Diffuse] + 1;
@ -201,9 +194,9 @@ namespace SceneUtil
LightBuffer oldBuffer = LightBuffer(*this); LightBuffer oldBuffer = LightBuffer(*this);
for (int i = 0; i < oldBuffer.mCount; ++i) for (int i = 0; i < oldBuffer.mCount; ++i)
{ {
*(osg::Vec4*)(&(*mData)[getOffset(i, Diffuse)]) = *(osg::Vec4*)(&(*mData)[oldBuffer.getOffset(i, Diffuse)]); std::memcpy(&(*mData)[getOffset(i, Diffuse)], &(*mData)[oldBuffer.getOffset(i, Diffuse)], sizeof(osg::Vec4f));
*(osg::Vec4*)(&(*mData)[getOffset(i, Position)]) = *(osg::Vec4*)(&(*mData)[oldBuffer.getOffset(i, Position)]); std::memcpy(&(*mData)[getOffset(i, Position)], &(*mData)[oldBuffer.getOffset(i, Position)], sizeof(osg::Vec4f));
*(osg::Vec4*)(&(*mData)[getOffset(i, AttenuationRadius)]) = *(osg::Vec4*)(&(*mData)[oldBuffer.getOffset(i, AttenuationRadius)]); std::memcpy(&(*mData)[getOffset(i, AttenuationRadius)], &(*mData)[oldBuffer.getOffset(i, AttenuationRadius)], sizeof(osg::Vec4f));
} }
} }
@ -212,7 +205,7 @@ namespace SceneUtil
osg::Endian mEndian; osg::Endian mEndian;
int mCount; int mCount;
int mStride; int mStride;
std::unordered_map<LayoutOffset, int> mOffsets; std::array<std::size_t, 6> mOffsets;
}; };
class LightStateCache class LightStateCache
@ -234,7 +227,6 @@ namespace SceneUtil
{ {
switch (method) switch (method)
{ {
case LightingMethod::Undefined:
case LightingMethod::FFP: case LightingMethod::FFP:
{ {
break; break;
@ -304,9 +296,9 @@ namespace SceneUtil
void apply(osg::State& state) const override void apply(osg::State& state) const override
{ {
int lightNum = GL_LIGHT0 + mIndex; int lightNum = GL_LIGHT0 + mIndex;
glLightfv(lightNum, GL_AMBIENT, mnullptr.ptr()); glLightfv(lightNum, GL_AMBIENT, mNullptr.ptr());
glLightfv(lightNum, GL_DIFFUSE, mnullptr.ptr()); glLightfv(lightNum, GL_DIFFUSE, mNullptr.ptr());
glLightfv(lightNum, GL_SPECULAR, mnullptr.ptr()); glLightfv(lightNum, GL_SPECULAR, mNullptr.ptr());
LightStateCache* cache = getLightStateCache(state.getContextID()); LightStateCache* cache = getLightStateCache(state.getContextID());
cache->lastAppliedLight[mIndex] = nullptr; cache->lastAppliedLight[mIndex] = nullptr;
@ -314,7 +306,7 @@ namespace SceneUtil
private: private:
size_t mIndex; size_t mIndex;
osg::Vec4f mnullptr; osg::Vec4f mNullptr;
}; };
class FFPLightStateAttribute : public osg::StateAttribute class FFPLightStateAttribute : public osg::StateAttribute
@ -697,17 +689,17 @@ namespace SceneUtil
void initSharedLayout(osg::GLExtensions* ext, int handle) const void initSharedLayout(osg::GLExtensions* ext, int handle) const
{ {
std::vector<unsigned int> index = { static_cast<int>(Shader::UBOBinding::LightBuffer) }; constexpr std::array<unsigned int, 1> index = { static_cast<unsigned int>(Shader::UBOBinding::LightBuffer) };
int totalBlockSize = -1; int totalBlockSize = -1;
int stride = -1; int stride = -1;
ext->glGetActiveUniformBlockiv(handle, 0, GL_UNIFORM_BLOCK_DATA_SIZE, &totalBlockSize); ext->glGetActiveUniformBlockiv(handle, 0, GL_UNIFORM_BLOCK_DATA_SIZE, &totalBlockSize);
ext->glGetActiveUniformsiv(handle, index.size(), index.data(), GL_UNIFORM_ARRAY_STRIDE, &stride); ext->glGetActiveUniformsiv(handle, index.size(), index.data(), GL_UNIFORM_ARRAY_STRIDE, &stride);
std::vector<const char*> names = { std::array<const char*, 3> names = {
"LightBuffer[0].packedColors" "LightBuffer[0].packedColors",
,"LightBuffer[0].position" "LightBuffer[0].position",
,"LightBuffer[0].attenuation" "LightBuffer[0].attenuation",
}; };
std::vector<unsigned int> indices(names.size()); std::vector<unsigned int> indices(names.size());
std::vector<int> offsets(names.size()); std::vector<int> offsets(names.size());
@ -803,18 +795,15 @@ namespace SceneUtil
,{"shaders", LightingMethod::SingleUBO} ,{"shaders", LightingMethod::SingleUBO}
}; };
bool LightManager::isValidLightingModelString(const std::string& value)
{
return LightManager::mLightingMethodSettingMap.find(value) != LightManager::mLightingMethodSettingMap.end();
}
LightingMethod LightManager::getLightingMethodFromString(const std::string& value) LightingMethod LightManager::getLightingMethodFromString(const std::string& value)
{ {
auto it = LightManager::mLightingMethodSettingMap.find(value); auto it = LightManager::mLightingMethodSettingMap.find(value);
if (it != LightManager::mLightingMethodSettingMap.end()) if (it != LightManager::mLightingMethodSettingMap.end())
return it->second; return it->second;
else
return LightingMethod::Undefined; constexpr const char* fallback = "shaders compatibility";
Log(Debug::Warning) << "Unknown lighting method '" << value << "', returning fallback '" << fallback << "'";
return LightingMethod::PerObjectUniform;
} }
std::string LightManager::getLightingMethodString(LightingMethod method) std::string LightManager::getLightingMethodString(LightingMethod method)
@ -843,12 +832,6 @@ namespace SceneUtil
std::string lightingMethodString = Settings::Manager::getString("lighting method", "Shaders"); std::string lightingMethodString = Settings::Manager::getString("lighting method", "Shaders");
auto lightingMethod = LightManager::getLightingMethodFromString(lightingMethodString); auto lightingMethod = LightManager::getLightingMethodFromString(lightingMethodString);
if (lightingMethod == LightingMethod::Undefined)
{
Log(Debug::Error) << "Invalid option for 'lighting method': got '" << lightingMethodString
<< "', expected legacy, shaders compatible, or shaders. Falling back to 'shaders compatible'.";
lightingMethod = LightingMethod::PerObjectUniform;
}
updateSettings(); updateSettings();
@ -875,7 +858,6 @@ namespace SceneUtil
initSingleUBO(targetLights); initSingleUBO(targetLights);
getOrCreateStateSet()->addUniform(new osg::Uniform("PointLightCount", 0)); getOrCreateStateSet()->addUniform(new osg::Uniform("PointLightCount", 0));
getOrCreateStateSet()->setAttributeAndModes(new LightManagerStateAttributePerObjectUniform(this), osg::StateAttribute::ON);
addCullCallback(new LightManagerCullCallback(this)); addCullCallback(new LightManagerCullCallback(this));
} }
@ -894,10 +876,6 @@ namespace SceneUtil
return mLightingMethod; return mLightingMethod;
} }
LightManager::~LightManager()
{
}
bool LightManager::usingFFP() const bool LightManager::usingFFP() const
{ {
return mLightingMethod == LightingMethod::FFP; return mLightingMethod == LightingMethod::FFP;
@ -1029,6 +1007,7 @@ namespace SceneUtil
setLightingMethod(LightingMethod::PerObjectUniform); setLightingMethod(LightingMethod::PerObjectUniform);
setMaxLights(std::clamp(targetLights, mMaxLightsLowerLimit, LightManager::mMaxLightsUpperLimit)); setMaxLights(std::clamp(targetLights, mMaxLightsLowerLimit, LightManager::mMaxLightsUpperLimit));
stateset->setAttributeAndModes(new LightManagerStateAttributePerObjectUniform(this), osg::StateAttribute::ON);
stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "LightBuffer", getMaxLights())); stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "LightBuffer", getMaxLights()));
} }
@ -1064,9 +1043,6 @@ namespace SceneUtil
case LightingMethod::PerObjectUniform: case LightingMethod::PerObjectUniform:
mStateSetGenerator = std::make_unique<StateSetGeneratorPerObjectUniform>(); mStateSetGenerator = std::make_unique<StateSetGeneratorPerObjectUniform>();
break; break;
case LightingMethod::Undefined:
mStateSetGenerator = nullptr;
break;
} }
mStateSetGenerator->mLightManager = this; mStateSetGenerator->mLightManager = this;
} }
@ -1107,7 +1083,7 @@ namespace SceneUtil
getLightIndexMap(frameNum).clear(); getLightIndexMap(frameNum).clear();
mLights.clear(); mLights.clear();
mLightsInViewSpace.clear(); mLightsInViewSpace.clear();
return;
// Do an occasional cleanup for orphaned lights. // Do an occasional cleanup for orphaned lights.
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
{ {
@ -1146,7 +1122,7 @@ namespace SceneUtil
for (size_t i = 0; i < lightList.size(); ++i) for (size_t i = 0; i < lightList.size(); ++i)
{ {
auto id = lightList[i]->mLightSource->getId(); auto id = lightList[i]->mLightSource->getId();
hash_combine(hash, id); Misc::hashCombine(hash, id);
if (getLightingMethod() != LightingMethod::SingleUBO) if (getLightingMethod() != LightingMethod::SingleUBO)
continue; continue;

@ -31,7 +31,6 @@ namespace SceneUtil
FFP, FFP,
PerObjectUniform, PerObjectUniform,
SingleUBO, SingleUBO,
Undefined
}; };
void configureStateSetSunOverride(LightingMethod method, const osg::Light* light, osg::StateSet* stateset, int mode = osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); void configureStateSetSunOverride(LightingMethod method, const osg::Light* light, osg::StateSet* stateset, int mode = osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
@ -114,7 +113,6 @@ namespace SceneUtil
class LightManager : public osg::Group class LightManager : public osg::Group
{ {
public: public:
static bool isValidLightingModelString(const std::string& value);
static LightingMethod getLightingMethodFromString(const std::string& value); static LightingMethod getLightingMethodFromString(const std::string& value);
/// Returns string as used in settings file, or the empty string if the method is undefined /// Returns string as used in settings file, or the empty string if the method is undefined
static std::string getLightingMethodString(LightingMethod method); static std::string getLightingMethodString(LightingMethod method);
@ -139,8 +137,6 @@ namespace SceneUtil
LightManager(const LightManager& copy, const osg::CopyOp& copyop); LightManager(const LightManager& copy, const osg::CopyOp& copyop);
~LightManager();
/// @param mask This mask is compared with the current Camera's cull mask to determine if lighting is desired. /// @param mask This mask is compared with the current Camera's cull mask to determine if lighting is desired.
/// By default, it's ~0u i.e. always on. /// By default, it's ~0u i.e. always on.
/// If you have some views that do not require lighting, then set the Camera's cull mask to not include /// If you have some views that do not require lighting, then set the Camera's cull mask to not include
@ -233,7 +229,6 @@ namespace SceneUtil
float mPointLightRadiusMultiplier; float mPointLightRadiusMultiplier;
float mPointLightFadeEnd; float mPointLightFadeEnd;
float mPointLightFadeStart; float mPointLightFadeStart;
float mPointLightFadeDelta;
int mMaxLights; int mMaxLights;

@ -186,7 +186,7 @@ light bounds multiplier
:Type: float :Type: float
:Range: 0.0-5.0 :Range: 0.0-5.0
:Default: 1.75 :Default: 1.65
Controls the bounding sphere radius of point lights, which is used to determine Controls the bounding sphere radius of point lights, which is used to determine
if an object should receive lighting from a particular light source. Note, this if an object should receive lighting from a particular light source. Note, this
@ -243,7 +243,7 @@ minimum interior brightness
:Type: float :Type: float
:Range: 0.0-1.0 :Range: 0.0-1.0
:Default: 0.1 :Default: 0.08
Sets the minimum interior ambient brightness for interior cells when Sets the minimum interior ambient brightness for interior cells when
:ref:`lighting method` is not 'legacy'. A consequence of the new lighting system :ref:`lighting method` is not 'legacy'. A consequence of the new lighting system

@ -529,7 +529,7 @@
<Widget type="TextBox" skin="NormalText" position="0 176 352 18" align="Left Top" name="BoundingSphereMultText"> <Widget type="TextBox" skin="NormalText" position="0 176 352 18" align="Left Top" name="BoundingSphereMultText">
<UserString key="ToolTipType" value="Layout"/> <UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="TextToolTip"/> <UserString key="ToolTipLayout" value="TextToolTip"/>
<UserString key="Caption_Text" value="Default: 1.75\nMultipler for bounding sphere of lights.\nHigher numbers allows for smooth falloff but require an increase in number of max lights.\n\nDoes not effect the illumination or strength of lights."/> <UserString key="Caption_Text" value="Default: 1.65\nMultipler for bounding sphere of lights.\nHigher numbers allows for smooth falloff but require an increase in number of max lights.\n\nDoes not effect the illumination or strength of lights."/>
</Widget> </Widget>
<Widget type="ScrollBar" skin="MW_HScroll" position="0 200 352 18" align="HStretch Top"> <Widget type="ScrollBar" skin="MW_HScroll" position="0 200 352 18" align="HStretch Top">
<Property key="Range" value="500000"/> <Property key="Range" value="500000"/>
@ -547,7 +547,7 @@
<Widget type="TextBox" skin="NormalText" position="0 224 352 18" align="Left Top" name="MinimumBrightnessText"> <Widget type="TextBox" skin="NormalText" position="0 224 352 18" align="Left Top" name="MinimumBrightnessText">
<UserString key="ToolTipType" value="Layout"/> <UserString key="ToolTipType" value="Layout"/>
<UserString key="ToolTipLayout" value="TextToolTip"/> <UserString key="ToolTipLayout" value="TextToolTip"/>
<UserString key="Caption_Text" value="Default: 0.1\nMinimum ambient interior brightness.\n\nIncrease this if you feel interiors are too dark."/> <UserString key="Caption_Text" value="Default: 0.08\nMinimum ambient interior brightness.\n\nIncrease this if you feel interiors are too dark."/>
</Widget> </Widget>
<Widget type="ScrollBar" skin="MW_HScroll" position="0 248 352 18" align="HStretch Top"> <Widget type="ScrollBar" skin="MW_HScroll" position="0 248 352 18" align="HStretch Top">
<Property key="Range" value="10000"/> <Property key="Range" value="10000"/>

@ -456,7 +456,7 @@ lighting method = shaders compatibility
# lighting. Higher values will allow for smoother transitions of light sources, # 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' # but may carry a performance cost and requires a higher number of 'max lights'
# set. # set.
light bounds multiplier = 1.75 light bounds multiplier = 1.65
# The distance from the camera at which lights fade away completely. # The distance from the camera at which lights fade away completely.
# Set to 0 to disable fading. # Set to 0 to disable fading.
@ -472,7 +472,7 @@ max lights = 8
# Sets minimum ambient brightness of interior cells. Levels below this threshold will have their # 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. # When 'lighting method' is set to 'legacy', this setting will have no effect.
minimum interior brightness = 0.1 minimum interior brightness = 0.08
# Convert the alpha test (cutout/punchthrough alpha) to alpha-to-coverage. # Convert the alpha test (cutout/punchthrough alpha) to alpha-to-coverage.
# This allows MSAA to work with alpha-tested meshes, producing better-looking edges without pixelation. # This allows MSAA to work with alpha-tested meshes, producing better-looking edges without pixelation.

@ -56,7 +56,7 @@ void perLightPoint(out vec3 ambientOut, out vec3 diffuseOut, int lightIndex, vec
lambert *= clamp(-8.0 * (1.0 - 0.3) * eyeCosine + 1.0, 0.3, 1.0); lambert *= clamp(-8.0 * (1.0 - 0.3) * eyeCosine + 1.0, 0.3, 1.0);
#endif #endif
diffuseOut = lcalcDiffuse(lightIndex) * lambert; diffuseOut = lcalcDiffuse(lightIndex) * lambert;
} }
#if PER_PIXEL_LIGHTING #if PER_PIXEL_LIGHTING

@ -102,7 +102,7 @@ vec3 lcalcDiffuse(int lightIndex)
#if @lightingMethodPerObjectUniform #if @lightingMethodPerObjectUniform
return @getLight[lightIndex][2].xyz; return @getLight[lightIndex][2].xyz;
#elif @lightingMethodUBO #elif @lightingMethodUBO
return unpackRGB(@getLight[lightIndex].packedColors.x) * float(int(@getLight[lightIndex].packedColors.w)); return unpackRGB(@getLight[lightIndex].packedColors.x) * float(@getLight[lightIndex].packedColors.w);
#else #else
return @getLight[lightIndex].diffuse.xyz; return @getLight[lightIndex].diffuse.xyz;
#endif #endif

Loading…
Cancel
Save