mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-22 03:40:49 +00:00
in-game settings, some require restart
This commit is contained in:
parent
3d713e8602
commit
71c30a31df
@ -6,6 +6,7 @@
|
||||
#include <MyGUI_ScrollView.h>
|
||||
#include <MyGUI_Gui.h>
|
||||
#include <MyGUI_TabControl.h>
|
||||
#include <MyGUI_TabItem.h>
|
||||
|
||||
#include <SDL_video.h>
|
||||
|
||||
@ -17,6 +18,7 @@
|
||||
#include <components/misc/constants.hpp>
|
||||
#include <components/widgets/sharedstatebutton.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/sceneutil/lightmanager.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
@ -107,7 +109,7 @@ namespace
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
void SettingsWindow::configureWidgets(MyGUI::Widget* widget)
|
||||
void SettingsWindow::configureWidgets(MyGUI::Widget* widget, bool init)
|
||||
{
|
||||
MyGUI::EnumeratorWidgetPtr widgets = widget->getEnumerator();
|
||||
while (widgets.next())
|
||||
@ -121,7 +123,8 @@ namespace MWGui
|
||||
getSettingCategory(current))
|
||||
? "#{sOn}" : "#{sOff}";
|
||||
current->castType<MyGUI::Button>()->setCaptionWithReplacing(initialValue);
|
||||
current->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
if (init)
|
||||
current->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
|
||||
}
|
||||
if (type == sliderType)
|
||||
{
|
||||
@ -141,6 +144,12 @@ namespace MWGui
|
||||
ss << std::fixed << std::setprecision(2) << value/Constants::CellSizeInUnits;
|
||||
valueStr = ss.str();
|
||||
}
|
||||
else if (valueType == "Float")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::setprecision(2) << value;
|
||||
valueStr = ss.str();
|
||||
}
|
||||
else
|
||||
valueStr = MyGUI::utility::toString(int(value));
|
||||
|
||||
@ -155,12 +164,13 @@ namespace MWGui
|
||||
valueStr = MyGUI::utility::toString(value);
|
||||
scroll->setScrollPosition(value);
|
||||
}
|
||||
scroll->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
|
||||
if (init)
|
||||
scroll->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
|
||||
if (scroll->getVisible())
|
||||
updateSliderLabel(scroll, valueStr);
|
||||
}
|
||||
|
||||
configureWidgets(current);
|
||||
configureWidgets(current, init);
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,7 +197,7 @@ namespace MWGui
|
||||
getWidget(unusedSlider, widgetName);
|
||||
unusedSlider->setVisible(false);
|
||||
|
||||
configureWidgets(mMainWidget);
|
||||
configureWidgets(mMainWidget, true);
|
||||
|
||||
setTitle("#{sOptions}");
|
||||
|
||||
@ -204,6 +214,9 @@ namespace MWGui
|
||||
getWidget(mControllerSwitch, "ControllerButton");
|
||||
getWidget(mWaterTextureSize, "WaterTextureSize");
|
||||
getWidget(mWaterReflectionDetail, "WaterReflectionDetail");
|
||||
getWidget(mLightingMethodButton, "LightingMethodButton");
|
||||
getWidget(mMaxLightsSlider, "MaxLightsSlider");
|
||||
getWidget(mLightsResetButton, "LightsResetButton");
|
||||
|
||||
#ifndef WIN32
|
||||
// hide gamma controls since it currently does not work under Linux
|
||||
@ -229,6 +242,9 @@ namespace MWGui
|
||||
mWaterTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWaterTextureSizeChanged);
|
||||
mWaterReflectionDetail->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWaterReflectionDetailChanged);
|
||||
|
||||
mLightingMethodButton->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onLightingMethodChanged);
|
||||
mLightsResetButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onLightsResetButtonClicked);
|
||||
|
||||
mKeyboardSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onKeyboardSwitchClicked);
|
||||
mControllerSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onControllerSwitchClicked);
|
||||
|
||||
@ -272,6 +288,21 @@ namespace MWGui
|
||||
waterReflectionDetail = std::min(5, std::max(0, waterReflectionDetail));
|
||||
mWaterReflectionDetail->setIndexSelected(waterReflectionDetail);
|
||||
|
||||
auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString(Settings::Manager::getString("lighting method", "Shaders"));
|
||||
switch (lightingMethod)
|
||||
{
|
||||
case SceneUtil::LightingMethod::Undefined:
|
||||
case SceneUtil::LightingMethod::FFP:
|
||||
mLightingMethodButton->setIndexSelected(0);
|
||||
break;
|
||||
case SceneUtil::LightingMethod::PerObjectUniform:
|
||||
mLightingMethodButton->setIndexSelected(1);
|
||||
break;
|
||||
case SceneUtil::LightingMethod::SingleUBO:
|
||||
mLightingMethodButton->setIndexSelected(2);
|
||||
break;
|
||||
}
|
||||
|
||||
mWindowBorderButton->setEnabled(!Settings::Manager::getBool("fullscreen", "Video"));
|
||||
|
||||
mKeyboardSwitch->setStateSelected(true);
|
||||
@ -358,6 +389,49 @@ namespace MWGui
|
||||
apply();
|
||||
}
|
||||
|
||||
void SettingsWindow::onLightsResetButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
std::vector<std::string> buttons = {"#{sYes}", "#{sNo}"};
|
||||
std::string message = "This will reset all lighting settings to default, some changes will require a restart. Would you like to continue?";
|
||||
MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, buttons, true);
|
||||
int selectedButton = MWBase::Environment::get().getWindowManager()->readPressedButton();
|
||||
if (selectedButton == 1 || selectedButton == -1)
|
||||
return;
|
||||
|
||||
Settings::Manager::setString("lighting method", "Shaders", "shaders compatibility");
|
||||
Settings::Manager::setFloat("light bounds multiplier", "Shaders", 1.75);
|
||||
Settings::Manager::setInt("maximum light distance", "Shaders", 8192);
|
||||
Settings::Manager::setFloat("light fade start", "Shaders", 0.85);
|
||||
Settings::Manager::setFloat("minimum interior brightness", "Shaders", 0.1);
|
||||
Settings::Manager::setInt("max lights", "Shaders", 8);
|
||||
|
||||
mLightingMethodButton->setIndexSelected(1);
|
||||
|
||||
apply();
|
||||
configureWidgets(mMainWidget, false);
|
||||
}
|
||||
|
||||
void SettingsWindow::onLightingMethodChanged(MyGUI::ComboBox* _sender, size_t pos)
|
||||
{
|
||||
std::string setting;
|
||||
auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString(_sender->getItemNameAt(pos));
|
||||
switch (lightingMethod)
|
||||
{
|
||||
case SceneUtil::LightingMethod::FFP:
|
||||
setting = "legacy";
|
||||
break;
|
||||
case SceneUtil::LightingMethod::Undefined:
|
||||
case SceneUtil::LightingMethod::PerObjectUniform:
|
||||
setting = "shaders compatibility";
|
||||
break;
|
||||
case SceneUtil::LightingMethod::SingleUBO:
|
||||
setting = "shaders";
|
||||
break;
|
||||
}
|
||||
Settings::Manager::setString("lighting method", "Shaders", setting);
|
||||
apply();
|
||||
}
|
||||
|
||||
void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender)
|
||||
{
|
||||
std::string on = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOn", "On");
|
||||
@ -460,6 +534,12 @@ namespace MWGui
|
||||
ss << std::fixed << std::setprecision(2) << value/Constants::CellSizeInUnits;
|
||||
valueStr = ss.str();
|
||||
}
|
||||
else if (valueType == "Float")
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::setprecision(2) << value;
|
||||
valueStr = ss.str();
|
||||
}
|
||||
else
|
||||
valueStr = MyGUI::utility::toString(int(value));
|
||||
}
|
||||
|
@ -35,6 +35,10 @@ namespace MWGui
|
||||
MyGUI::ComboBox* mWaterTextureSize;
|
||||
MyGUI::ComboBox* mWaterReflectionDetail;
|
||||
|
||||
MyGUI::ComboBox* mLightingMethodButton;
|
||||
MyGUI::ScrollBar* mMaxLightsSlider;
|
||||
MyGUI::Button* mLightsResetButton;
|
||||
|
||||
// controls
|
||||
MyGUI::ScrollView* mControlsBox;
|
||||
MyGUI::Button* mResetControlsButton;
|
||||
@ -55,6 +59,9 @@ namespace MWGui
|
||||
void onWaterTextureSizeChanged(MyGUI::ComboBox* _sender, size_t pos);
|
||||
void onWaterReflectionDetailChanged(MyGUI::ComboBox* _sender, size_t pos);
|
||||
|
||||
void onLightsResetButtonClicked(MyGUI::Widget* _sender);
|
||||
void onLightingMethodChanged(MyGUI::ComboBox* _sender, size_t pos);
|
||||
|
||||
void onRebindAction(MyGUI::Widget* _sender);
|
||||
void onInputTabMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||
void onResetDefaultBindings(MyGUI::Widget* _sender);
|
||||
@ -66,7 +73,7 @@ namespace MWGui
|
||||
|
||||
void apply();
|
||||
|
||||
void configureWidgets(MyGUI::Widget* widget);
|
||||
void configureWidgets(MyGUI::Widget* widget, bool init);
|
||||
void updateSliderLabel(MyGUI::ScrollBar* scroller, const std::string& value);
|
||||
|
||||
void layoutControlsBox();
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "../mwgui/loadingscreen.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwmechanics/actorutil.hpp"
|
||||
|
||||
#include "sky.hpp"
|
||||
#include "effectmanager.hpp"
|
||||
@ -224,8 +225,7 @@ namespace MWRender
|
||||
resourceSystem->getSceneManager()->getShaderManager().setLightingMethod(sceneRoot->getLightingMethod());
|
||||
resourceSystem->getSceneManager()->setLightingMethod(sceneRoot->getLightingMethod());
|
||||
|
||||
if (sceneRoot->getLightingMethod() != SceneUtil::LightingMethod::FFP)
|
||||
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);
|
||||
|
||||
sceneRoot->setLightingMask(Mask_Lighting);
|
||||
mSceneRoot = sceneRoot;
|
||||
@ -1144,9 +1144,25 @@ namespace MWRender
|
||||
else if (it->first == "General" && (it->second == "texture filter" ||
|
||||
it->second == "texture mipmap" ||
|
||||
it->second == "anisotropy"))
|
||||
{
|
||||
updateTextureFiltering();
|
||||
}
|
||||
else if (it->first == "Water")
|
||||
{
|
||||
mWater->processChangedSettings(changed);
|
||||
}
|
||||
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().getCell())
|
||||
configureAmbient(MWMechanics::getPlayer().getCell()->getCell());
|
||||
}
|
||||
else if (it->first == "Shaders" && (it->second == "light bounds multiplier" ||
|
||||
it->second == "maximum light distance" ||
|
||||
it->second == "light fade start"))
|
||||
{
|
||||
static_cast<SceneUtil::LightManager*>(getLightRoot())->processChangedSettings(changed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
|
||||
namespace
|
||||
@ -41,6 +39,43 @@ namespace
|
||||
{
|
||||
light->setUserValue("radius", value);
|
||||
}
|
||||
|
||||
void configurePosition(osg::Matrixf& mat, const osg::Vec4& pos)
|
||||
{
|
||||
mat(0, 0) = pos.x();
|
||||
mat(0, 1) = pos.y();
|
||||
mat(0, 2) = pos.z();
|
||||
}
|
||||
|
||||
void configureAmbient(osg::Matrixf& mat, const osg::Vec4& color)
|
||||
{
|
||||
mat(1, 0) = color.r();
|
||||
mat(1, 1) = color.g();
|
||||
mat(1, 2) = color.b();
|
||||
}
|
||||
|
||||
void configureDiffuse(osg::Matrixf& mat, const osg::Vec4& color)
|
||||
{
|
||||
mat(2, 0) = color.r();
|
||||
mat(2, 1) = color.g();
|
||||
mat(2, 2) = color.b();
|
||||
}
|
||||
|
||||
void configureSpecular(osg::Matrixf& mat, const osg::Vec4& color)
|
||||
{
|
||||
mat(3, 0) = color.r();
|
||||
mat(3, 1) = color.g();
|
||||
mat(3, 2) = color.b();
|
||||
mat(3, 3) = color.a();
|
||||
}
|
||||
|
||||
void configureAttenuation(osg::Matrixf& mat, float c, float l, float q, float r)
|
||||
{
|
||||
mat(0, 3) = c;
|
||||
mat(1, 3) = l;
|
||||
mat(2, 3) = q;
|
||||
mat(3, 3) = r;
|
||||
}
|
||||
}
|
||||
|
||||
namespace SceneUtil
|
||||
@ -206,11 +241,12 @@ namespace SceneUtil
|
||||
}
|
||||
case LightingMethod::PerObjectUniform:
|
||||
{
|
||||
stateset->addUniform(new osg::Uniform("LightBuffer[0].diffuse", light->getDiffuse()), mode);
|
||||
stateset->addUniform(new osg::Uniform("LightBuffer[0].ambient", light->getAmbient()), mode);
|
||||
stateset->addUniform(new osg::Uniform("LightBuffer[0].specular", light->getSpecular()), mode);
|
||||
stateset->addUniform(new osg::Uniform("LightBuffer[0].position", light->getPosition()), mode);
|
||||
|
||||
osg::Matrixf lightMat;
|
||||
configurePosition(lightMat, light->getPosition());
|
||||
configureAmbient(lightMat, light->getAmbient());
|
||||
configureDiffuse(lightMat, light->getDiffuse());
|
||||
configureSpecular(lightMat, light->getSpecular());
|
||||
stateset->addUniform(new osg::Uniform("LightBuffer", lightMat), mode);
|
||||
break;
|
||||
}
|
||||
case LightingMethod::SingleUBO:
|
||||
@ -381,14 +417,20 @@ namespace SceneUtil
|
||||
|
||||
void apply(osg::State &state) const override
|
||||
{
|
||||
auto* lightUniform = mLightManager->getStateSet()->getUniform("LightBuffer");
|
||||
for (size_t i = 0; i < mLights.size(); ++i)
|
||||
{
|
||||
auto light = 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());
|
||||
osg::Matrixf lightMat;
|
||||
|
||||
configurePosition(lightMat, light->getPosition() * state.getInitialViewMatrix());
|
||||
configureAmbient(lightMat, light->getAmbient());
|
||||
configureDiffuse(lightMat, light->getDiffuse());
|
||||
configureAttenuation(lightMat, light->getConstantAttenuation(), light->getLinearAttenuation(), light->getQuadraticAttenuation(), getLightRadius(light));
|
||||
|
||||
lightUniform->setElement(i+1, lightMat);
|
||||
}
|
||||
lightUniform->dirty();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -589,10 +631,12 @@ namespace SceneUtil
|
||||
{
|
||||
if (mLightManager->getLightingMethod() == LightingMethod::PerObjectUniform)
|
||||
{
|
||||
mLightManager->getLightUniform(0, LightManager::UniformKey::Diffuse)->set(sun->getDiffuse());
|
||||
mLightManager->getLightUniform(0, LightManager::UniformKey::Ambient)->set(sun->getAmbient());
|
||||
mLightManager->getLightUniform(0, LightManager::UniformKey::Specular)->set(sun->getSpecular());
|
||||
mLightManager->getLightUniform(0, LightManager::UniformKey::Position)->set(sun->getPosition() * (*cv->getCurrentRenderStage()->getInitialViewMatrix()));
|
||||
osg::Matrixf lightMat;
|
||||
configurePosition(lightMat, sun->getPosition() * (*cv->getCurrentRenderStage()->getInitialViewMatrix()));
|
||||
configureAmbient(lightMat, sun->getAmbient());
|
||||
configureDiffuse(lightMat, sun->getDiffuse());
|
||||
configureSpecular(lightMat, sun->getSpecular());
|
||||
mLightManager->getStateSet()->getUniform("LightBuffer")->setElement(0, lightMat);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -760,14 +804,7 @@ namespace SceneUtil
|
||||
lightingMethod = LightingMethod::PerObjectUniform;
|
||||
}
|
||||
|
||||
mPointLightRadiusMultiplier = std::clamp(Settings::Manager::getFloat("light bounds multiplier", "Shaders"), 0.f, 10.f);
|
||||
|
||||
mPointLightFadeEnd = std::max(0.f, Settings::Manager::getFloat("maximum light distance", "Shaders"));
|
||||
if (mPointLightFadeEnd > 0)
|
||||
{
|
||||
mPointLightFadeStart = std::clamp(Settings::Manager::getFloat("light fade start", "Shaders"), 0.f, 1.f);
|
||||
mPointLightFadeStart = mPointLightFadeEnd * mPointLightFadeStart;
|
||||
}
|
||||
updateSettings();
|
||||
|
||||
osg::GLExtensions* exts = osg::GLExtensions::Get(0, false);
|
||||
bool supportsUBO = exts && exts->isUniformBufferObjectSupported;
|
||||
@ -839,9 +876,6 @@ namespace SceneUtil
|
||||
{
|
||||
Shader::ShaderManager::DefineMap defines;
|
||||
|
||||
bool ffp = usingFFP();
|
||||
|
||||
defines["ffpLighting"] = ffp ? "1" : "0";
|
||||
defines["maxLights"] = std::to_string(getMaxLights());
|
||||
defines["maxLightsInScene"] = std::to_string(getMaxLightsInScene());
|
||||
defines["lightingModel"] = std::to_string(static_cast<int>(mLightingMethod));
|
||||
@ -852,6 +886,26 @@ namespace SceneUtil
|
||||
return defines;
|
||||
}
|
||||
|
||||
void LightManager::processChangedSettings(const Settings::CategorySettingVector& changed)
|
||||
{
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
void LightManager::updateSettings()
|
||||
{
|
||||
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"));
|
||||
if (mPointLightFadeEnd > 0)
|
||||
{
|
||||
mPointLightFadeStart = std::clamp(Settings::Manager::getFloat("light fade start", "Shaders"), 0.f, 1.f);
|
||||
mPointLightFadeStart = mPointLightFadeEnd * mPointLightFadeStart;
|
||||
}
|
||||
}
|
||||
|
||||
void LightManager::initFFP(int targetLights)
|
||||
{
|
||||
setLightingMethod(LightingMethod::FFP);
|
||||
@ -866,38 +920,15 @@ namespace SceneUtil
|
||||
auto* stateset = getOrCreateStateSet();
|
||||
|
||||
setLightingMethod(LightingMethod::PerObjectUniform);
|
||||
setMaxLights(std::max(2, targetLights));
|
||||
setMaxLights(std::clamp(targetLights, 2, 64));
|
||||
|
||||
mLightUniforms.resize(getMaxLights()+1);
|
||||
for (size_t i = 0; i < mLightUniforms.size(); ++i)
|
||||
{
|
||||
osg::ref_ptr<osg::Uniform> udiffuse = new osg::Uniform(osg::Uniform::FLOAT_VEC4, ("LightBuffer[" + std::to_string(i) + "].diffuse").c_str());
|
||||
osg::ref_ptr<osg::Uniform> uspecular = new osg::Uniform(osg::Uniform::FLOAT_VEC4, ("LightBuffer[" + std::to_string(i) + "].specular").c_str());
|
||||
osg::ref_ptr<osg::Uniform> uambient = new osg::Uniform(osg::Uniform::FLOAT_VEC4, ("LightBuffer[" + std::to_string(i) + "].ambient").c_str());
|
||||
osg::ref_ptr<osg::Uniform> uposition = new osg::Uniform(osg::Uniform::FLOAT_VEC4, ("LightBuffer[" + std::to_string(i) + "].position").c_str());
|
||||
osg::ref_ptr<osg::Uniform> uattenuation = new osg::Uniform(osg::Uniform::FLOAT_VEC4, ("LightBuffer[" + std::to_string(i) + "].attenuation").c_str());
|
||||
|
||||
mLightUniforms[i].emplace(UniformKey::Diffuse, udiffuse);
|
||||
mLightUniforms[i].emplace(UniformKey::Ambient, uambient);
|
||||
mLightUniforms[i].emplace(UniformKey::Specular, uspecular);
|
||||
mLightUniforms[i].emplace(UniformKey::Position, uposition);
|
||||
mLightUniforms[i].emplace(UniformKey::Attenuation, uattenuation);
|
||||
|
||||
stateset->addUniform(udiffuse);
|
||||
stateset->addUniform(uambient);
|
||||
stateset->addUniform(uposition);
|
||||
stateset->addUniform(uattenuation);
|
||||
|
||||
// specular isn't used besides sun, complete waste to upload it
|
||||
if (i == 0)
|
||||
stateset->addUniform(uspecular);
|
||||
}
|
||||
stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "LightBuffer", getMaxLights() + 1));
|
||||
}
|
||||
|
||||
void LightManager::initSingleUBO(int targetLights)
|
||||
{
|
||||
setLightingMethod(LightingMethod::SingleUBO);
|
||||
setMaxLights(std::clamp(targetLights, 2, getMaxLightsInScene() / 2));
|
||||
setMaxLights(std::clamp(targetLights, 2, 64));
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
@ -912,7 +943,6 @@ namespace SceneUtil
|
||||
getOrCreateStateSet()->setAttribute(new LightManagerStateAttribute(this), osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
|
||||
void LightManager::setLightingMethod(LightingMethod method)
|
||||
{
|
||||
mLightingMethod = method;
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
#include <components/shader/shadermanager.hpp>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
namespace osgUtil
|
||||
{
|
||||
class CullVisitor;
|
||||
@ -172,10 +174,10 @@ namespace SceneUtil
|
||||
|
||||
auto& getLightBuffer(size_t frameNum) { return mLightBuffers[frameNum%2]; }
|
||||
|
||||
auto& getLightUniform(int index, UniformKey key) { return mLightUniforms[index][key]; }
|
||||
|
||||
std::map<std::string, std::string> getLightDefines() const;
|
||||
|
||||
void processChangedSettings(const Settings::CategorySettingVector& changed);
|
||||
|
||||
private:
|
||||
friend class LightManagerStateAttribute;
|
||||
friend class LightManagerCullCallback;
|
||||
@ -184,6 +186,8 @@ namespace SceneUtil
|
||||
void initPerObjectUniform(int targetLights);
|
||||
void initSingleUBO(int targetLights);
|
||||
|
||||
void updateSettings();
|
||||
|
||||
void setLightingMethod(LightingMethod method);
|
||||
void setMaxLights(int value);
|
||||
|
||||
@ -212,9 +216,6 @@ namespace SceneUtil
|
||||
using LightIndexMap = std::unordered_map<int, int>;
|
||||
LightIndexMap mLightIndexMaps[2];
|
||||
|
||||
using UniformMap = std::vector<std::unordered_map<UniformKey, osg::ref_ptr<osg::Uniform>>>;
|
||||
UniformMap mLightUniforms;
|
||||
|
||||
std::unique_ptr<StateSetGenerator> mStateSetGenerator;
|
||||
|
||||
LightingMethod mLightingMethod;
|
||||
|
@ -185,7 +185,7 @@ light bounds multiplier
|
||||
-----------------------
|
||||
|
||||
:Type: float
|
||||
:Range: 0.0-10.0
|
||||
:Range: 0.0-5.0
|
||||
:Default: 1.75
|
||||
|
||||
Controls the bounding sphere radius of point lights, which is used to determine
|
||||
@ -228,7 +228,7 @@ max lights
|
||||
----------
|
||||
|
||||
:Type: integer
|
||||
:Range: >=2
|
||||
:Range: 2-64
|
||||
:Default: 8
|
||||
|
||||
Sets the maximum number of lights that each object can receive lighting from.
|
||||
|
@ -456,6 +456,95 @@
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
|
||||
<Widget type="TabItem" skin="" position="4 32 360 308">
|
||||
<Property key="Caption" value=" Lights "/>
|
||||
<!-- Lighting Method -->
|
||||
<Widget type="TextBox" skin="NormalText" position="0 4 160 18" align="Left Top">
|
||||
<Property key="Caption" value="*Lighting Method"/>
|
||||
</Widget>
|
||||
<Widget type="ComboBox" skin="MW_ComboBox" position="0 28 170 24" align="Left Top" name="LightingMethodButton">
|
||||
<Property key="AddItem" value="legacy"/>
|
||||
<Property key="AddItem" value="shaders compatibility"/>
|
||||
<Property key="AddItem" value="shaders"/>
|
||||
</Widget>
|
||||
<!-- Max Lights -->
|
||||
<Widget type="TextBox" skin="NormalText" position="178 4 160 18" align="Left Top" name="MaxLightsText"/>
|
||||
<Widget type="ScrollBar" skin="MW_HScroll" position="178 30 160 18" align="Right Top HStretch" name="MaxLightsSlider">
|
||||
<Property key="Range" value="24"/>
|
||||
<Property key="Page" value="1"/>
|
||||
<UserString key="SettingType" value="Slider"/>
|
||||
<UserString key="SettingMin" value="8"/>
|
||||
<UserString key="SettingMax" value="32"/>
|
||||
<UserString key="SettingCategory" value="Shaders"/>
|
||||
<UserString key="SettingName" value="max lights"/>
|
||||
<UserString key="SettingValueType" value="Integer"/>
|
||||
<UserString key="SettingLabelWidget" value="MaxLightsText"/>
|
||||
<UserString key="SettingLabelCaption" value="*Max Lights (%s)"/>
|
||||
</Widget>
|
||||
<Widget type="ImageBox" skin="MW_HLine" position="0 54 360 18" align="Top HStretch"/>
|
||||
<!-- Light Fade Start -->
|
||||
<Widget type="TextBox" skin="NormalText" position="0 78 352 18" align="Left Top" name="MaxLightDistanceText"/>
|
||||
<Widget type="ScrollBar" skin="MW_HScroll" position="0 104 352 18" align="HStretch Top">
|
||||
<Property key="Range" value="8192"/>
|
||||
<Property key="Page" value="1"/>
|
||||
<UserString key="SettingType" value="Slider"/>
|
||||
<UserString key="SettingMin" value="0"/>
|
||||
<UserString key="SettingMax" value="8192"/>
|
||||
<UserString key="SettingCategory" value="Shaders"/>
|
||||
<UserString key="SettingName" value="maximum light distance"/>
|
||||
<UserString key="SettingValueType" value="Integer"/>
|
||||
<UserString key="SettingLabelWidget" value="MaxLightDistanceText"/>
|
||||
<UserString key="SettingLabelCaption" value="Maximum Light Distance (%s)"/>
|
||||
</Widget>
|
||||
<!-- Light Fade Multiplier -->
|
||||
<Widget type="TextBox" skin="NormalText" position="0 128 352 18" align="Left Top" name="LightFadeMultiplierText"/>
|
||||
<Widget type="ScrollBar" skin="MW_HScroll" position="0 152 352 18" align="HStretch Top">
|
||||
<Property key="Range" value="10000"/>
|
||||
<Property key="Page" value="300"/>
|
||||
<UserString key="SettingType" value="Slider"/>
|
||||
<UserString key="SettingCategory" value="Shaders"/>
|
||||
<UserString key="SettingName" value="light fade start"/>
|
||||
<UserString key="SettingValueType" value="Float"/>
|
||||
<UserString key="SettingLabelWidget" value="LightFadeMultiplierText"/>
|
||||
<UserString key="SettingLabelCaption" value="Fade Start Multiplier (%s)"/>
|
||||
</Widget>
|
||||
<!-- Bounding Sphere Multiplier -->
|
||||
<Widget type="TextBox" skin="NormalText" position="0 176 352 18" align="Left Top" name="BoundingSphereMultText"/>
|
||||
<Widget type="ScrollBar" skin="MW_HScroll" position="0 200 352 18" align="HStretch Top">
|
||||
<Property key="Range" value="10000"/>
|
||||
<Property key="Page" value="300"/>
|
||||
<UserString key="SettingType" value="Slider"/>
|
||||
<UserString key="SettingMin" value="0.1"/>
|
||||
<UserString key="SettingMax" value="5.0"/>
|
||||
<UserString key="SettingCategory" value="Shaders"/>
|
||||
<UserString key="SettingName" value="light bounds multiplier"/>
|
||||
<UserString key="SettingValueType" value="Float"/>
|
||||
<UserString key="SettingLabelWidget" value="BoundingSphereMultText"/>
|
||||
<UserString key="SettingLabelCaption" value="Bounding Sphere Multiplier (%s)"/>
|
||||
</Widget>
|
||||
<!-- Minimum Ambient Brightness -->
|
||||
<Widget type="TextBox" skin="NormalText" position="0 224 352 18" align="Left Top" name="MinimumBrightnessText"/>
|
||||
<Widget type="ScrollBar" skin="MW_HScroll" position="0 248 352 18" align="HStretch Top">
|
||||
<Property key="Range" value="10000"/>
|
||||
<Property key="Page" value="300"/>
|
||||
<UserString key="SettingType" value="Slider"/>
|
||||
<UserString key="SettingCategory" value="Shaders"/>
|
||||
<UserString key="SettingName" value="minimum interior brightness"/>
|
||||
<UserString key="SettingValueType" value="Float"/>
|
||||
<UserString key="SettingLabelWidget" value="MinimumBrightnessText"/>
|
||||
<UserString key="SettingLabelCaption" value="Minimum Interior Brightness (%s)"/>
|
||||
</Widget>
|
||||
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" position="0 308 0 0" align="Bottom Left" name="LightsResetButton">
|
||||
<Property key="Caption" value="Reset To Defaults"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedTextBox" skin="NormalText" position="210 308 0 0" align="Bottom Right HStretch">
|
||||
<Property key="Caption" value="(*) Requires Restart"/>
|
||||
<Property key="TextAlign" value="Right"/>
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
<!--
|
||||
<Widget type="TabItem" skin="" position="0 28 352 268">
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define LIGHTING_MODEL_SINGLE_UBO 1
|
||||
#define LIGHTING_MODEL_PER_OBJECT_UNIFORM 2
|
||||
|
||||
#if !@ffpLighting
|
||||
#if @lightingModel != LIGHTING_MODEL_FFP
|
||||
#define getLight LightBuffer
|
||||
|
||||
float quickstep(float x)
|
||||
@ -13,7 +13,7 @@ float quickstep(float x)
|
||||
return x;
|
||||
}
|
||||
|
||||
#if @useUBO
|
||||
#if @lightingModel == LIGHTING_MODEL_SINGLE_UBO
|
||||
|
||||
const int mask = int(0xff);
|
||||
const ivec4 shift = ivec4(int(0), int(8), int(16), int(24));
|
||||
@ -33,11 +33,16 @@ vec4 unpackRGBA(int data)
|
||||
,(float(((data >> shift.w) & mask)) / 255.0));
|
||||
}
|
||||
|
||||
/* Layout:
|
||||
packedColors: 8-bit unsigned RGB packed as (diffuse, ambient, specular).
|
||||
sign bit is stored in diffuse alpha component
|
||||
attenuation: constant, linear, quadratic, light radius (as defined in content)
|
||||
*/
|
||||
struct LightData
|
||||
{
|
||||
ivec4 packedColors; // diffuse, ambient, specular
|
||||
ivec4 packedColors;
|
||||
vec4 position;
|
||||
vec4 attenuation; // constant, linear, quadratic, radius
|
||||
vec4 attenuation;
|
||||
};
|
||||
|
||||
uniform int PointLightIndex[@maxLights];
|
||||
@ -51,16 +56,15 @@ uniform LightBufferBinding
|
||||
|
||||
#else
|
||||
|
||||
struct LightData
|
||||
{
|
||||
vec4 position;
|
||||
vec4 diffuse;
|
||||
vec4 ambient;
|
||||
vec4 specular;
|
||||
vec4 attenuation; // constant, linear, quadratic, radius
|
||||
};
|
||||
|
||||
uniform LightData LightBuffer[@maxLights];
|
||||
/* Layout:
|
||||
--------------------------------------- -----------
|
||||
| pos_x | ambi_r | diff_r | spec_r |
|
||||
| pos_y | ambi_g | diff_g | spec_g |
|
||||
| pos_z | ambi_b | diff_b | spec_b |
|
||||
| att_c | att_l | att_q | radius/spec_a |
|
||||
--------------------------------------------------
|
||||
*/
|
||||
uniform mat4 LightBuffer[@maxLights];
|
||||
uniform int PointLightCount;
|
||||
|
||||
#endif
|
||||
@ -71,9 +75,16 @@ uniform int PointLightCount;
|
||||
|
||||
void perLightSun(out vec3 ambientOut, out vec3 diffuseOut, vec3 viewPos, vec3 viewNormal)
|
||||
{
|
||||
#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM
|
||||
vec3 lightDir = normalize(getLight[0][0].xyz);
|
||||
#else
|
||||
vec3 lightDir = normalize(getLight[0].position.xyz);
|
||||
#endif
|
||||
|
||||
#if @lightingModel == LIGHTING_MODEL_SINGLE_UBO
|
||||
#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM
|
||||
ambientOut = getLight[0][1].xyz;
|
||||
vec3 sunDiffuse = getLight[0][2].xyz;
|
||||
#elif @lightingModel == LIGHTING_MODEL_SINGLE_UBO
|
||||
ivec4 data = getLight[0].packedColors;
|
||||
ambientOut = unpackRGB(data.y);
|
||||
vec3 sunDiffuse = unpackRGB(data.x);
|
||||
@ -81,6 +92,7 @@ void perLightSun(out vec3 ambientOut, out vec3 diffuseOut, vec3 viewPos, vec3 vi
|
||||
ambientOut = getLight[0].ambient.xyz;
|
||||
vec3 sunDiffuse = getLight[0].diffuse.xyz;
|
||||
#endif
|
||||
|
||||
float lambert = dot(viewNormal.xyz, lightDir);
|
||||
#ifndef GROUNDCOVER
|
||||
lambert = max(lambert, 0.0);
|
||||
@ -98,13 +110,22 @@ void perLightSun(out vec3 ambientOut, out vec3 diffuseOut, vec3 viewPos, vec3 vi
|
||||
|
||||
void perLightPoint(out vec3 ambientOut, out vec3 diffuseOut, int lightIndex, vec3 viewPos, vec3 viewNormal)
|
||||
{
|
||||
#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM
|
||||
vec3 lightPos = getLight[lightIndex][0].xyz - viewPos;
|
||||
#else
|
||||
vec3 lightPos = getLight[lightIndex].position.xyz - viewPos;
|
||||
#endif
|
||||
|
||||
float lightDistance = length(lightPos);
|
||||
|
||||
#if !@ffpLighting
|
||||
// This has a *considerable* performance uplift where GPU is a bottleneck
|
||||
if (lightDistance > getLight[lightIndex].attenuation.w * 2.0)
|
||||
#if @lightingModel != LIGHTING_MODEL_FFP
|
||||
#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM
|
||||
float radius = getLight[lightIndex][3][3];
|
||||
#else
|
||||
float radius = getLight[lightIndex].attenuation.w;
|
||||
#endif
|
||||
|
||||
if (lightDistance > radius * 2.0)
|
||||
{
|
||||
ambientOut = vec3(0.0);
|
||||
diffuseOut = vec3(0.0);
|
||||
@ -114,17 +135,17 @@ void perLightPoint(out vec3 ambientOut, out vec3 diffuseOut, int lightIndex, vec
|
||||
|
||||
lightPos = normalize(lightPos);
|
||||
|
||||
#if @ffpLighting
|
||||
float illumination = clamp(1.0 / (getLight[lightIndex].constantAttenuation + getLight[lightIndex].linearAttenuation * lightDistance + getLight[lightIndex].quadraticAttenuation * lightDistance * lightDistance), 0.0, 1.0);
|
||||
#else
|
||||
#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM
|
||||
float illumination = clamp(1.0 / (getLight[lightIndex][0].w + getLight[lightIndex][1].w * lightDistance + getLight[lightIndex][2].w * lightDistance * lightDistance), 0.0, 1.0);
|
||||
illumination *= 1.0 - quickstep((lightDistance / radius) - 1.0);
|
||||
ambientOut = getLight[lightIndex][1].xyz * illumination;
|
||||
#elif @lightingModel == LIGHTING_MODEL_SINGLE_UBO
|
||||
float illumination = clamp(1.0 / (getLight[lightIndex].attenuation.x + getLight[lightIndex].attenuation.y * lightDistance + getLight[lightIndex].attenuation.z * lightDistance * lightDistance), 0.0, 1.0);
|
||||
illumination *= 1.0 - quickstep((lightDistance / (getLight[lightIndex].attenuation.w)) - 1.0);
|
||||
#endif
|
||||
|
||||
#if @useUBO
|
||||
illumination *= 1.0 - quickstep((lightDistance / radius) - 1.0);
|
||||
ivec4 data = getLight[lightIndex].packedColors;
|
||||
ambientOut = unpackRGB(data.y) * illumination;
|
||||
#else
|
||||
float illumination = clamp(1.0 / (getLight[lightIndex].constantAttenuation + getLight[lightIndex].linearAttenuation * lightDistance + getLight[lightIndex].quadraticAttenuation * lightDistance * lightDistance), 0.0, 1.0);
|
||||
ambientOut = getLight[lightIndex].ambient.xyz * illumination;
|
||||
#endif
|
||||
|
||||
@ -142,8 +163,10 @@ 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);
|
||||
#endif
|
||||
|
||||
#if @useUBO
|
||||
#if @lightingModel == LIGHTING_MODEL_SINGLE_UBO
|
||||
diffuseOut = unpackRGB(data.x) * lambert * float(int(data.w));
|
||||
#elif @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM
|
||||
diffuseOut = getLight[lightIndex][2].xyz * lambert;
|
||||
#else
|
||||
diffuseOut = getLight[lightIndex].diffuse.xyz * lambert;
|
||||
#endif
|
||||
@ -191,10 +214,16 @@ void doLighting(vec3 viewPos, vec3 viewNormal, out vec3 diffuseLight, out vec3 a
|
||||
|
||||
vec3 getSpecular(vec3 viewNormal, vec3 viewDirection, float shininess, vec3 matSpec)
|
||||
{
|
||||
#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM
|
||||
vec3 sunDir = getLight[0][0].xyz;
|
||||
#else
|
||||
vec3 sunDir = getLight[0].position.xyz;
|
||||
#endif
|
||||
|
||||
#if @lightingModel == LIGHTING_MODEL_SINGLE_UBO
|
||||
vec3 sunSpec = unpackRGB(getLight[0].packedColors.z);
|
||||
#elif @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM
|
||||
vec3 sunSpec = getLight[0][3].xyz;
|
||||
#else
|
||||
vec3 sunSpec = getLight[0].specular.xyz;
|
||||
#endif
|
||||
|
@ -203,8 +203,11 @@ void main(void)
|
||||
normal3 * midWaves.y + normal4 * smallWaves.x + normal5 * smallWaves.y + rippleAdd);
|
||||
normal = normalize(vec3(-normal.x * bump, -normal.y * bump, normal.z));
|
||||
|
||||
#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM
|
||||
vec3 lVec = normalize((gl_ModelViewMatrixInverse * vec4(getLight[0][0].xyz, 0.0)).xyz);
|
||||
#else
|
||||
vec3 lVec = normalize((gl_ModelViewMatrixInverse * vec4(getLight[0].position.xyz, 0.0)).xyz);
|
||||
|
||||
#endif
|
||||
vec3 cameraPos = (gl_ModelViewMatrixInverse * vec4(0,0,0,1)).xyz;
|
||||
vec3 vVec = normalize(position.xyz - cameraPos.xyz);
|
||||
|
||||
@ -241,6 +244,8 @@ void main(void)
|
||||
|
||||
#if @lightingModel == LIGHTING_MODEL_SINGLE_UBO
|
||||
vec4 sunSpec = unpackRGBA(getLight[0].packedColors.z);
|
||||
#elif @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM
|
||||
vec4 sunSpec = getLight[0][3];
|
||||
#else
|
||||
vec4 sunSpec = getLight[0].specular;
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user