mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 22:23:51 +00:00
Merge branch 'light_settings_tweak' into 'master'
Lighting patch Closes #5957 and #5959 See merge request OpenMW/openmw!752
This commit is contained in:
commit
d0883f9a0d
11 changed files with 280 additions and 219 deletions
|
@ -111,20 +111,17 @@ namespace
|
||||||
max = MyGUI::utility::parseFloat(widget->getUserString(settingMax));
|
max = MyGUI::utility::parseFloat(widget->getUserString(settingMax));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* getLightingMethodCaptionText(SceneUtil::LightingMethod lightingMethod)
|
void updateMaxLightsComboBox(MyGUI::ComboBox* box)
|
||||||
{
|
{
|
||||||
switch (lightingMethod)
|
constexpr int min = 8;
|
||||||
{
|
constexpr int max = 32;
|
||||||
case SceneUtil::LightingMethod::FFP:
|
constexpr int increment = 8;
|
||||||
return "Emulates fixed function pipeline lighting, advanced light settings are disabled when this mode is active";
|
int maxLights = Settings::Manager::getInt("max lights", "Shaders");
|
||||||
case SceneUtil::LightingMethod::PerObjectUniform:
|
// show increments of 8 in dropdown
|
||||||
return "Removes limit of 8 lights per object, fixes lighting attenuation, and enables groundcover lighting and light fade."
|
if (maxLights >= min && maxLights <= max && !(maxLights % increment))
|
||||||
"\n\nDesigned for compatibility across hardware, and is not meant for large max light counts.";
|
box->setIndexSelected((maxLights / increment)-1);
|
||||||
case SceneUtil::LightingMethod::SingleUBO:
|
else
|
||||||
return "Removes limit of 8 lights per object, fixes lighting attenuation, and enables groundcover lighting and light fade."
|
box->setIndexSelected(MyGUI::ITEM_NONE);
|
||||||
"\n\nDesigned for more modern hardware and large max light counts.";
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,9 +232,9 @@ namespace MWGui
|
||||||
getWidget(mControllerSwitch, "ControllerButton");
|
getWidget(mControllerSwitch, "ControllerButton");
|
||||||
getWidget(mWaterTextureSize, "WaterTextureSize");
|
getWidget(mWaterTextureSize, "WaterTextureSize");
|
||||||
getWidget(mWaterReflectionDetail, "WaterReflectionDetail");
|
getWidget(mWaterReflectionDetail, "WaterReflectionDetail");
|
||||||
getWidget(mLightingMethodText, "LightingMethodText");
|
getWidget(mLightingMethodButton, "LightingMethodButton");
|
||||||
getWidget(mLightsResetButton, "LightsResetButton");
|
getWidget(mLightsResetButton, "LightsResetButton");
|
||||||
getWidget(mLightSettingOverlay, "LightSettingOverlay");
|
getWidget(mMaxLights, "MaxLights");
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
// hide gamma controls since it currently does not work under Linux
|
// hide gamma controls since it currently does not work under Linux
|
||||||
|
@ -263,7 +260,9 @@ namespace MWGui
|
||||||
mWaterTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWaterTextureSizeChanged);
|
mWaterTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWaterTextureSizeChanged);
|
||||||
mWaterReflectionDetail->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWaterReflectionDetailChanged);
|
mWaterReflectionDetail->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWaterReflectionDetailChanged);
|
||||||
|
|
||||||
|
mLightingMethodButton->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onLightingMethodButtonChanged);
|
||||||
mLightsResetButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onLightsResetButtonClicked);
|
mLightsResetButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onLightsResetButtonClicked);
|
||||||
|
mMaxLights->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onMaxLightsChanged);
|
||||||
|
|
||||||
mKeyboardSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onKeyboardSwitchClicked);
|
mKeyboardSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onKeyboardSwitchClicked);
|
||||||
mControllerSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onControllerSwitchClicked);
|
mControllerSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onControllerSwitchClicked);
|
||||||
|
@ -310,6 +309,8 @@ namespace MWGui
|
||||||
waterReflectionDetail = std::min(5, std::max(0, waterReflectionDetail));
|
waterReflectionDetail = std::min(5, std::max(0, waterReflectionDetail));
|
||||||
mWaterReflectionDetail->setIndexSelected(waterReflectionDetail);
|
mWaterReflectionDetail->setIndexSelected(waterReflectionDetail);
|
||||||
|
|
||||||
|
updateMaxLightsComboBox(mMaxLights);
|
||||||
|
|
||||||
mWindowBorderButton->setEnabled(!Settings::Manager::getBool("fullscreen", "Video"));
|
mWindowBorderButton->setEnabled(!Settings::Manager::getBool("fullscreen", "Video"));
|
||||||
|
|
||||||
mKeyboardSwitch->setStateSelected(true);
|
mKeyboardSwitch->setStateSelected(true);
|
||||||
|
@ -396,19 +397,50 @@ namespace MWGui
|
||||||
apply();
|
apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsWindow::onLightingMethodButtonChanged(MyGUI::ComboBox* _sender, size_t pos)
|
||||||
|
{
|
||||||
|
if (pos == MyGUI::ITEM_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string message = "This change requires a restart to take effect.";
|
||||||
|
MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, {"#{sOK}"}, true);
|
||||||
|
|
||||||
|
Settings::Manager::setString("lighting method", "Shaders", _sender->getItemNameAt(pos));
|
||||||
|
apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsWindow::onMaxLightsChanged(MyGUI::ComboBox* _sender, size_t pos)
|
||||||
|
{
|
||||||
|
int count = 8 * (pos + 1);
|
||||||
|
|
||||||
|
Settings::Manager::setInt("max lights", "Shaders", count);
|
||||||
|
apply();
|
||||||
|
configureWidgets(mMainWidget, false);
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsWindow::onLightsResetButtonClicked(MyGUI::Widget* _sender)
|
void SettingsWindow::onLightsResetButtonClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
std::vector<std::string> buttons = {"#{sYes}", "#{sNo}"};
|
std::vector<std::string> buttons = {"#{sYes}", "#{sNo}"};
|
||||||
std::string message = "Resets to default values, would you like to continue?";
|
std::string message = "Resets to default values, would you like to continue? Changes to lighting method will require a restart.";
|
||||||
MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, buttons, true);
|
MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, buttons, true);
|
||||||
int selectedButton = MWBase::Environment::get().getWindowManager()->readPressedButton();
|
int selectedButton = MWBase::Environment::get().getWindowManager()->readPressedButton();
|
||||||
if (selectedButton == 1 || selectedButton == -1)
|
if (selectedButton == 1 || selectedButton == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
constexpr std::array<const char*, 5> settings = {"light bounds multiplier", "maximum light distance", "light fade start", "minimum interior brightness", "max lights"};
|
constexpr std::array<const char*, 6> settings = {
|
||||||
|
"light bounds multiplier",
|
||||||
|
"maximum light distance",
|
||||||
|
"light fade start",
|
||||||
|
"minimum interior brightness",
|
||||||
|
"max lights",
|
||||||
|
"lighting method",
|
||||||
|
};
|
||||||
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}]);
|
||||||
|
|
||||||
|
mLightingMethodButton->setIndexSelected(mLightingMethodButton->findItemIndexWith(Settings::Manager::mDefaultSettings[{"Shaders", "lighting method"}]));
|
||||||
|
updateMaxLightsComboBox(mMaxLights);
|
||||||
|
|
||||||
apply();
|
apply();
|
||||||
configureWidgets(mMainWidget, false);
|
configureWidgets(mMainWidget, false);
|
||||||
}
|
}
|
||||||
|
@ -614,20 +646,25 @@ namespace MWGui
|
||||||
void SettingsWindow::updateLightSettings()
|
void SettingsWindow::updateLightSettings()
|
||||||
{
|
{
|
||||||
auto lightingMethod = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getLightingMethod();
|
auto lightingMethod = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getLightingMethod();
|
||||||
mLightingMethodText->setCaption(SceneUtil::LightManager::getLightingMethodString(lightingMethod));
|
std::string lightingMethodStr = SceneUtil::LightManager::getLightingMethodString(lightingMethod);
|
||||||
|
|
||||||
if (lightingMethod == SceneUtil::LightingMethod::FFP || !Settings::Manager::getBool("force shaders", "Shaders"))
|
mLightingMethodButton->removeAllItems();
|
||||||
|
|
||||||
|
std::array<SceneUtil::LightingMethod, 3> methods = {
|
||||||
|
SceneUtil::LightingMethod::FFP,
|
||||||
|
SceneUtil::LightingMethod::PerObjectUniform,
|
||||||
|
SceneUtil::LightingMethod::SingleUBO,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& method : methods)
|
||||||
{
|
{
|
||||||
MyGUI::Widget* parent = mLightSettingOverlay->getParent();
|
if (!MWBase::Environment::get().getResourceSystem()->getSceneManager()->isSupportedLightingMethod(method))
|
||||||
mLightSettingOverlay->setEnabled(false);
|
continue;
|
||||||
mLightSettingOverlay->setAlpha(0.8);
|
|
||||||
parent->setUserString("ToolTipType", "Layout");
|
mLightingMethodButton->addItem(SceneUtil::LightManager::getLightingMethodString(method));
|
||||||
parent->setUserString("ToolTipLayout", "TextToolTip");
|
|
||||||
parent->setUserString("Caption_Text", "Unavailable with current settings.");
|
|
||||||
parent->setEnabled(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mLightingMethodText->setUserString("Caption_Text", getLightingMethodCaptionText(lightingMethod));
|
mLightingMethodButton->setIndexSelected(mLightingMethodButton->findItemIndexWith(lightingMethodStr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsWindow::layoutControlsBox()
|
void SettingsWindow::layoutControlsBox()
|
||||||
|
|
|
@ -32,8 +32,8 @@ namespace MWGui
|
||||||
MyGUI::ComboBox* mWaterTextureSize;
|
MyGUI::ComboBox* mWaterTextureSize;
|
||||||
MyGUI::ComboBox* mWaterReflectionDetail;
|
MyGUI::ComboBox* mWaterReflectionDetail;
|
||||||
|
|
||||||
MyGUI::Widget* mLightSettingOverlay;
|
MyGUI::ComboBox* mMaxLights;
|
||||||
MyGUI::TextBox* mLightingMethodText;
|
MyGUI::ComboBox* mLightingMethodButton;
|
||||||
MyGUI::Button* mLightsResetButton;
|
MyGUI::Button* mLightsResetButton;
|
||||||
|
|
||||||
// controls
|
// controls
|
||||||
|
@ -56,7 +56,9 @@ namespace MWGui
|
||||||
void onWaterTextureSizeChanged(MyGUI::ComboBox* _sender, size_t pos);
|
void onWaterTextureSizeChanged(MyGUI::ComboBox* _sender, size_t pos);
|
||||||
void onWaterReflectionDetailChanged(MyGUI::ComboBox* _sender, size_t pos);
|
void onWaterReflectionDetailChanged(MyGUI::ComboBox* _sender, size_t pos);
|
||||||
|
|
||||||
|
void onLightingMethodButtonChanged(MyGUI::ComboBox* _sender, size_t pos);
|
||||||
void onLightsResetButtonClicked(MyGUI::Widget* _sender);
|
void onLightsResetButtonClicked(MyGUI::Widget* _sender);
|
||||||
|
void onMaxLightsChanged(MyGUI::ComboBox* _sender, size_t pos);
|
||||||
|
|
||||||
void onRebindAction(MyGUI::Widget* _sender);
|
void onRebindAction(MyGUI::Widget* _sender);
|
||||||
void onInputTabMouseWheel(MyGUI::Widget* _sender, int _rel);
|
void onInputTabMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||||
|
|
|
@ -233,7 +233,16 @@ namespace MWRender
|
||||||
float positionZ = std::cos(altitude);
|
float positionZ = std::cos(altitude);
|
||||||
light->setPosition(osg::Vec4(positionX,positionY,positionZ, 0.0));
|
light->setPosition(osg::Vec4(positionX,positionY,positionZ, 0.0));
|
||||||
light->setDiffuse(osg::Vec4(diffuseR,diffuseG,diffuseB,1));
|
light->setDiffuse(osg::Vec4(diffuseR,diffuseG,diffuseB,1));
|
||||||
light->setAmbient(osg::Vec4(ambientR,ambientG,ambientB,1));
|
osg::Vec4 ambientRGBA = osg::Vec4(ambientR,ambientG,ambientB,1);
|
||||||
|
if (mResourceSystem->getSceneManager()->getForceShaders())
|
||||||
|
{
|
||||||
|
// When using shaders, we now skip the ambient sun calculation as this is the only place it's used.
|
||||||
|
// Using the scene ambient will give identical results.
|
||||||
|
lightmodel->setAmbientIntensity(ambientRGBA);
|
||||||
|
light->setAmbient(osg::Vec4(0,0,0,1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
light->setAmbient(ambientRGBA);
|
||||||
light->setSpecular(osg::Vec4(0,0,0,0));
|
light->setSpecular(osg::Vec4(0,0,0,0));
|
||||||
light->setLightNum(0);
|
light->setLightNum(0);
|
||||||
light->setConstantAttenuation(1.f);
|
light->setConstantAttenuation(1.f);
|
||||||
|
|
|
@ -224,8 +224,7 @@ osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, f
|
||||||
SceneUtil::ShadowManager::disableShadowsForStateSet(stateset);
|
SceneUtil::ShadowManager::disableShadowsForStateSet(stateset);
|
||||||
|
|
||||||
// override sun for local map
|
// override sun for local map
|
||||||
auto lightingMethod = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getLightingMethod();
|
SceneUtil::configureStateSetSunOverride(static_cast<SceneUtil::LightManager*>(mSceneRoot.get()), light, stateset);
|
||||||
SceneUtil::configureStateSetSunOverride(lightingMethod, light, stateset);
|
|
||||||
|
|
||||||
camera->addChild(lightSource);
|
camera->addChild(lightSource);
|
||||||
camera->setStateSet(stateset);
|
camera->setStateSet(stateset);
|
||||||
|
|
|
@ -201,11 +201,15 @@ namespace MWRender
|
||||||
, mFieldOfViewOverridden(false)
|
, mFieldOfViewOverridden(false)
|
||||||
, mFieldOfViewOverride(0.f)
|
, mFieldOfViewOverride(0.f)
|
||||||
{
|
{
|
||||||
|
auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString(Settings::Manager::getString("lighting method", "Shaders"));
|
||||||
|
|
||||||
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") || explicitlyForceShaders || Settings::Manager::getBool("enable shadows", "Shadows");
|
bool forceShaders = Settings::Manager::getBool("radial fog", "Shaders")
|
||||||
|
|| Settings::Manager::getBool("force shaders", "Shaders")
|
||||||
|
|| Settings::Manager::getBool("enable shadows", "Shadows")
|
||||||
|
|| lightingMethod != SceneUtil::LightingMethod::FFP;
|
||||||
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(Settings::Manager::getBool("clamp lighting", "Shaders"));
|
resourceSystem->getSceneManager()->setClampLighting(Settings::Manager::getBool("clamp lighting", "Shaders"));
|
||||||
|
@ -217,12 +221,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);
|
||||||
|
|
||||||
auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString(Settings::Manager::getString("lighting method", "Shaders"));
|
|
||||||
// Let LightManager choose which backend to use based on our hint. For methods besides legacy lighting, this depends on support for various OpenGL extensions.
|
// 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);
|
osg::ref_ptr<SceneUtil::LightManager> sceneRoot = new SceneUtil::LightManager(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());
|
||||||
|
resourceSystem->getSceneManager()->setSupportedLightingMethods(sceneRoot->getSupportedLightingMethods());
|
||||||
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);
|
sceneRoot->setLightingMask(Mask_Lighting);
|
||||||
|
@ -554,7 +557,7 @@ namespace MWRender
|
||||||
// brighten ambient so it reaches the minimum threshold but no more, we want to mess with content data as least we can
|
// brighten ambient so it reaches the minimum threshold but no more, we want to mess with content data as least we can
|
||||||
float targetBrightnessIncreaseFactor = mMinimumAmbientLuminance / relativeLuminance;
|
float targetBrightnessIncreaseFactor = mMinimumAmbientLuminance / relativeLuminance;
|
||||||
if (ambient.r() == 0.f && ambient.g() == 0.f && ambient.b() == 0.f)
|
if (ambient.r() == 0.f && ambient.g() == 0.f && ambient.b() == 0.f)
|
||||||
ambient = osg::Vec4(targetBrightnessIncreaseFactor, targetBrightnessIncreaseFactor, targetBrightnessIncreaseFactor, ambient.a());
|
ambient = osg::Vec4(mMinimumAmbientLuminance, mMinimumAmbientLuminance, mMinimumAmbientLuminance, ambient.a());
|
||||||
else
|
else
|
||||||
ambient *= targetBrightnessIncreaseFactor;
|
ambient *= targetBrightnessIncreaseFactor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -305,6 +305,16 @@ namespace Resource
|
||||||
mApplyLightingToEnvMaps = apply;
|
mApplyLightingToEnvMaps = apply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneManager::setSupportedLightingMethods(const SceneUtil::LightManager::SupportedMethods& supported)
|
||||||
|
{
|
||||||
|
mSupportedLightingMethods = supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SceneManager::isSupportedLightingMethod(SceneUtil::LightingMethod method) const
|
||||||
|
{
|
||||||
|
return mSupportedLightingMethods[static_cast<int>(method)];
|
||||||
|
}
|
||||||
|
|
||||||
void SceneManager::setLightingMethod(SceneUtil::LightingMethod method)
|
void SceneManager::setLightingMethod(SceneUtil::LightingMethod method)
|
||||||
{
|
{
|
||||||
mLightingMethod = method;
|
mLightingMethod = method;
|
||||||
|
|
|
@ -107,6 +107,9 @@ namespace Resource
|
||||||
|
|
||||||
void setApplyLightingToEnvMaps(bool apply);
|
void setApplyLightingToEnvMaps(bool apply);
|
||||||
|
|
||||||
|
void setSupportedLightingMethods(const SceneUtil::LightManager::SupportedMethods& supported);
|
||||||
|
bool isSupportedLightingMethod(SceneUtil::LightingMethod method) const;
|
||||||
|
|
||||||
void setLightingMethod(SceneUtil::LightingMethod method);
|
void setLightingMethod(SceneUtil::LightingMethod method);
|
||||||
SceneUtil::LightingMethod getLightingMethod() const;
|
SceneUtil::LightingMethod getLightingMethod() const;
|
||||||
|
|
||||||
|
@ -197,6 +200,7 @@ namespace Resource
|
||||||
std::string mSpecularMapPattern;
|
std::string mSpecularMapPattern;
|
||||||
bool mApplyLightingToEnvMaps;
|
bool mApplyLightingToEnvMaps;
|
||||||
SceneUtil::LightingMethod mLightingMethod;
|
SceneUtil::LightingMethod mLightingMethod;
|
||||||
|
SceneUtil::LightManager::SupportedMethods mSupportedLightingMethods;
|
||||||
bool mConvertAlphaTestToAlphaToCoverage;
|
bool mConvertAlphaTestToAlphaToCoverage;
|
||||||
|
|
||||||
osg::ref_ptr<MultiObjectCache> mInstanceCache;
|
osg::ref_ptr<MultiObjectCache> mInstanceCache;
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include <osg/BufferObject>
|
#include <osg/BufferObject>
|
||||||
#include <osg/BufferIndexBinding>
|
#include <osg/BufferIndexBinding>
|
||||||
#include <osg/Endian>
|
#include <osg/Endian>
|
||||||
|
#include <osg/Version>
|
||||||
|
#include <osg/ValueObject>
|
||||||
|
|
||||||
#include <osgUtil/CullVisitor>
|
#include <osgUtil/CullVisitor>
|
||||||
|
|
||||||
|
@ -102,6 +104,7 @@ namespace SceneUtil
|
||||||
, mEndian(osg::getCpuByteOrder())
|
, mEndian(osg::getCpuByteOrder())
|
||||||
, mCount(count)
|
, mCount(count)
|
||||||
, mStride(12)
|
, mStride(12)
|
||||||
|
, mCachedSunPos(osg::Vec4())
|
||||||
{
|
{
|
||||||
mOffsets[Diffuse] = 0;
|
mOffsets[Diffuse] = 0;
|
||||||
mOffsets[Ambient] = 1;
|
mOffsets[Ambient] = 1;
|
||||||
|
@ -118,6 +121,7 @@ namespace SceneUtil
|
||||||
, mCount(copy.mCount)
|
, mCount(copy.mCount)
|
||||||
, mStride(copy.mStride)
|
, mStride(copy.mStride)
|
||||||
, mOffsets(copy.mOffsets)
|
, mOffsets(copy.mOffsets)
|
||||||
|
, mCachedSunPos(copy.mCachedSunPos)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void setDiffuse(int index, const osg::Vec4& value)
|
void setDiffuse(int index, const osg::Vec4& value)
|
||||||
|
@ -172,6 +176,17 @@ namespace SceneUtil
|
||||||
return 3 * osg::Vec4::num_components * sizeof(GL_FLOAT) * sz;
|
return 3 * osg::Vec4::num_components * sizeof(GL_FLOAT) * sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setCachedSunPos(const osg::Vec4& pos)
|
||||||
|
{
|
||||||
|
mCachedSunPos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uploadCachedSunPos(const osg::Matrix& viewMat)
|
||||||
|
{
|
||||||
|
osg::Vec4 viewPos = mCachedSunPos * viewMat;
|
||||||
|
std::memcpy(&(*mData)[getOffset(0, Position)], viewPos.ptr(), sizeof(osg::Vec4f));
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int asRGBA(const osg::Vec4& value) const
|
unsigned int asRGBA(const osg::Vec4& value) const
|
||||||
{
|
{
|
||||||
return mEndian == osg::BigEndian ? value.asABGR() : value.asRGBA();
|
return mEndian == osg::BigEndian ? value.asABGR() : value.asRGBA();
|
||||||
|
@ -187,6 +202,8 @@ namespace SceneUtil
|
||||||
constexpr auto sizeofFloat = sizeof(GL_FLOAT);
|
constexpr auto sizeofFloat = sizeof(GL_FLOAT);
|
||||||
constexpr auto sizeofVec4 = sizeofFloat * osg::Vec4::num_components;
|
constexpr auto sizeofVec4 = sizeofFloat * osg::Vec4::num_components;
|
||||||
|
|
||||||
|
LightBuffer oldBuffer = LightBuffer(*this);
|
||||||
|
|
||||||
mOffsets[Diffuse] = offsetColors / sizeofFloat;
|
mOffsets[Diffuse] = offsetColors / sizeofFloat;
|
||||||
mOffsets[Ambient] = mOffsets[Diffuse] + 1;
|
mOffsets[Ambient] = mOffsets[Diffuse] + 1;
|
||||||
mOffsets[Specular] = mOffsets[Diffuse] + 2;
|
mOffsets[Specular] = mOffsets[Diffuse] + 2;
|
||||||
|
@ -196,7 +213,6 @@ namespace SceneUtil
|
||||||
mStride = (offsetAttenuationRadius + sizeofVec4 + stride) / 4;
|
mStride = (offsetAttenuationRadius + sizeofVec4 + stride) / 4;
|
||||||
|
|
||||||
// Copy over previous buffers light data. Buffers populate before we know the layout.
|
// Copy over previous buffers light data. Buffers populate before we know the layout.
|
||||||
LightBuffer oldBuffer = LightBuffer(*this);
|
|
||||||
mData->resize(size / sizeofFloat);
|
mData->resize(size / sizeofFloat);
|
||||||
for (int i = 0; i < oldBuffer.mCount; ++i)
|
for (int i = 0; i < oldBuffer.mCount; ++i)
|
||||||
{
|
{
|
||||||
|
@ -212,6 +228,7 @@ namespace SceneUtil
|
||||||
int mCount;
|
int mCount;
|
||||||
int mStride;
|
int mStride;
|
||||||
std::array<std::size_t, 6> mOffsets;
|
std::array<std::size_t, 6> mOffsets;
|
||||||
|
osg::Vec4 mCachedSunPos;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LightStateCache
|
class LightStateCache
|
||||||
|
@ -229,8 +246,9 @@ namespace SceneUtil
|
||||||
return &cacheVector[contextid];
|
return &cacheVector[contextid];
|
||||||
}
|
}
|
||||||
|
|
||||||
void configureStateSetSunOverride(LightingMethod method, const osg::Light* light, osg::StateSet* stateset, int mode)
|
void configureStateSetSunOverride(LightManager* lightManager, const osg::Light* light, osg::StateSet* stateset, int mode)
|
||||||
{
|
{
|
||||||
|
auto method = lightManager->getLightingMethod();
|
||||||
switch (method)
|
switch (method)
|
||||||
{
|
{
|
||||||
case LightingMethod::FFP:
|
case LightingMethod::FFP:
|
||||||
|
@ -244,12 +262,15 @@ namespace SceneUtil
|
||||||
configureAmbient(lightMat, light->getAmbient());
|
configureAmbient(lightMat, light->getAmbient());
|
||||||
configureDiffuse(lightMat, light->getDiffuse());
|
configureDiffuse(lightMat, light->getDiffuse());
|
||||||
configureSpecular(lightMat, light->getSpecular());
|
configureSpecular(lightMat, light->getSpecular());
|
||||||
stateset->addUniform(new osg::Uniform("LightBuffer", lightMat), mode);
|
|
||||||
|
osg::ref_ptr<osg::Uniform> uni = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "LightBuffer", lightManager->getMaxLights());
|
||||||
|
uni->setElement(0, lightMat);
|
||||||
|
stateset->addUniform(uni, mode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LightingMethod::SingleUBO:
|
case LightingMethod::SingleUBO:
|
||||||
{
|
{
|
||||||
osg::ref_ptr<LightBuffer> buffer = new LightBuffer(1);
|
osg::ref_ptr<LightBuffer> buffer = new LightBuffer(lightManager->getMaxLightsInScene());
|
||||||
|
|
||||||
buffer->setDiffuse(0, light->getDiffuse());
|
buffer->setDiffuse(0, light->getDiffuse());
|
||||||
buffer->setAmbient(0, light->getAmbient());
|
buffer->setAmbient(0, light->getAmbient());
|
||||||
|
@ -258,8 +279,11 @@ namespace SceneUtil
|
||||||
|
|
||||||
osg::ref_ptr<osg::UniformBufferObject> ubo = new osg::UniformBufferObject;
|
osg::ref_ptr<osg::UniformBufferObject> ubo = new osg::UniformBufferObject;
|
||||||
buffer->getData()->setBufferObject(ubo);
|
buffer->getData()->setBufferObject(ubo);
|
||||||
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Shader::UBOBinding::LightBuffer), buffer->getData().get(), 0, buffer->getData()->getTotalDataSize());
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,5,7)
|
||||||
|
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Shader::UBOBinding::LightBuffer), buffer->getData(), 0, buffer->getData()->getTotalDataSize());
|
||||||
|
#else
|
||||||
|
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Shader::UBOBinding::LightBuffer), ubo, 0, buffer->getData()->getTotalDataSize());
|
||||||
|
#endif
|
||||||
stateset->setAttributeAndModes(ubb, mode);
|
stateset->setAttributeAndModes(ubb, mode);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -433,6 +457,11 @@ namespace SceneUtil
|
||||||
|
|
||||||
lightUniform->setElement(i+1, lightMat);
|
lightUniform->setElement(i+1, lightMat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto sun = mLightManager->getSunlightBuffer(state.getFrameStamp()->getFrameNumber());
|
||||||
|
configurePosition(sun, osg::Vec4(sun(0,0), sun(0,1), sun(0,2), 0.0) * state.getInitialViewMatrix());
|
||||||
|
lightUniform->setElement(0, sun);
|
||||||
|
|
||||||
lightUniform->dirty();
|
lightUniform->dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,7 +647,6 @@ namespace SceneUtil
|
||||||
void operator()(osg::Node* node, osg::NodeVisitor* nv) override
|
void operator()(osg::Node* node, osg::NodeVisitor* nv) override
|
||||||
{
|
{
|
||||||
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
|
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
|
||||||
bool pop = false;
|
|
||||||
|
|
||||||
if (mLastFrameNumber != cv->getTraversalNumber())
|
if (mLastFrameNumber != cv->getTraversalNumber())
|
||||||
{
|
{
|
||||||
|
@ -628,18 +656,24 @@ namespace SceneUtil
|
||||||
{
|
{
|
||||||
auto stateset = mLightManager->getStateSet();
|
auto stateset = mLightManager->getStateSet();
|
||||||
auto bo = mLightManager->getLightBuffer(mLastFrameNumber);
|
auto bo = mLightManager->getLightBuffer(mLastFrameNumber);
|
||||||
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Shader::UBOBinding::LightBuffer), bo->getData().get(), 0, bo->getData()->getTotalDataSize());
|
|
||||||
stateset->setAttributeAndModes(ubb.get(), osg::StateAttribute::ON);
|
#if OSG_VERSION_GREATER_OR_EQUAL(3,5,7)
|
||||||
|
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Shader::UBOBinding::LightBuffer), bo->getData(), 0, bo->getData()->getTotalDataSize());
|
||||||
|
#else
|
||||||
|
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Shader::UBOBinding::LightBuffer), bo->getData()->getBufferObject(), 0, bo->getData()->getTotalDataSize());
|
||||||
|
#endif
|
||||||
|
stateset->setAttributeAndModes(ubb, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sun = mLightManager->getSunlight();
|
auto sun = mLightManager->getSunlight();
|
||||||
|
|
||||||
if (sun)
|
if (sun)
|
||||||
{
|
{
|
||||||
|
// we must defer uploading the transformation to view-space position to deal with different cameras (e.g. reflection RTT).
|
||||||
if (mLightManager->getLightingMethod() == LightingMethod::PerObjectUniform)
|
if (mLightManager->getLightingMethod() == LightingMethod::PerObjectUniform)
|
||||||
{
|
{
|
||||||
osg::Matrixf lightMat;
|
osg::Matrixf lightMat;
|
||||||
configurePosition(lightMat, sun->getPosition() * (*cv->getCurrentRenderStage()->getInitialViewMatrix()));
|
configurePosition(lightMat, sun->getPosition());
|
||||||
configureAmbient(lightMat, sun->getAmbient());
|
configureAmbient(lightMat, sun->getAmbient());
|
||||||
configureDiffuse(lightMat, sun->getDiffuse());
|
configureDiffuse(lightMat, sun->getDiffuse());
|
||||||
configureSpecular(lightMat, sun->getSpecular());
|
configureSpecular(lightMat, sun->getSpecular());
|
||||||
|
@ -649,33 +683,15 @@ namespace SceneUtil
|
||||||
{
|
{
|
||||||
auto buf = mLightManager->getLightBuffer(mLastFrameNumber);
|
auto buf = mLightManager->getLightBuffer(mLastFrameNumber);
|
||||||
|
|
||||||
buf->setPosition(0, sun->getPosition() * (*cv->getCurrentRenderStage()->getInitialViewMatrix()));
|
buf->setCachedSunPos(sun->getPosition());
|
||||||
buf->setAmbient(0, sun->getAmbient());
|
buf->setAmbient(0, sun->getAmbient());
|
||||||
buf->setDiffuse(0, sun->getDiffuse());
|
buf->setDiffuse(0, sun->getDiffuse());
|
||||||
buf->setSpecular(0, sun->getSpecular());
|
buf->setSpecular(0, sun->getSpecular());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isReflectionCamera(cv->getCurrentCamera()))
|
|
||||||
{
|
|
||||||
auto sun = mLightManager->getSunlight();
|
|
||||||
if (sun)
|
|
||||||
{
|
|
||||||
osg::Vec4 originalPos = sun->getPosition();
|
|
||||||
sun->setPosition(originalPos * (*cv->getCurrentRenderStage()->getInitialViewMatrix()));
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
|
|
||||||
configureStateSetSunOverride(mLightManager->getLightingMethod(), sun, stateset);
|
|
||||||
|
|
||||||
sun->setPosition(originalPos);
|
|
||||||
cv->pushStateSet(stateset);
|
|
||||||
pop = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
traverse(node, nv);
|
traverse(node, nv);
|
||||||
if (pop)
|
|
||||||
cv->popStateSet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -692,6 +708,7 @@ namespace SceneUtil
|
||||||
LightManagerStateAttribute(LightManager* lightManager)
|
LightManagerStateAttribute(LightManager* lightManager)
|
||||||
: mLightManager(lightManager)
|
: mLightManager(lightManager)
|
||||||
, mDummyProgram(new osg::Program)
|
, mDummyProgram(new osg::Program)
|
||||||
|
, mInitLayout(false)
|
||||||
{
|
{
|
||||||
static const std::string dummyVertSource = generateDummyShader(mLightManager->getMaxLightsInScene());
|
static const std::string dummyVertSource = generateDummyShader(mLightManager->getMaxLightsInScene());
|
||||||
|
|
||||||
|
@ -741,8 +758,7 @@ namespace SceneUtil
|
||||||
|
|
||||||
void apply(osg::State& state) const override
|
void apply(osg::State& state) const override
|
||||||
{
|
{
|
||||||
static bool init = false;
|
if (!mInitLayout)
|
||||||
if (!init)
|
|
||||||
{
|
{
|
||||||
auto handle = mDummyProgram->getPCP(state)->getHandle();
|
auto handle = mDummyProgram->getPCP(state)->getHandle();
|
||||||
auto* ext = state.get<osg::GLExtensions>();
|
auto* ext = state.get<osg::GLExtensions>();
|
||||||
|
@ -754,14 +770,12 @@ namespace SceneUtil
|
||||||
if (activeUniformBlocks > 0)
|
if (activeUniformBlocks > 0)
|
||||||
{
|
{
|
||||||
initSharedLayout(ext, handle);
|
initSharedLayout(ext, handle);
|
||||||
init = true;
|
mInitLayout = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
mLightManager->getLightBuffer(state.getFrameStamp()->getFrameNumber())->uploadCachedSunPos(state.getInitialViewMatrix());
|
||||||
{
|
|
||||||
mLightManager->getLightBuffer(state.getFrameStamp()->getFrameNumber())->dirty();
|
mLightManager->getLightBuffer(state.getFrameStamp()->getFrameNumber())->dirty();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -792,36 +806,7 @@ namespace SceneUtil
|
||||||
|
|
||||||
LightManager* mLightManager;
|
LightManager* mLightManager;
|
||||||
osg::ref_ptr<osg::Program> mDummyProgram;
|
osg::ref_ptr<osg::Program> mDummyProgram;
|
||||||
};
|
mutable bool mInitLayout;
|
||||||
|
|
||||||
class LightManagerStateAttributePerObjectUniform : public osg::StateAttribute
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LightManagerStateAttributePerObjectUniform()
|
|
||||||
: mLightManager(nullptr) {}
|
|
||||||
|
|
||||||
LightManagerStateAttributePerObjectUniform(LightManager* lightManager)
|
|
||||||
: mLightManager(lightManager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LightManagerStateAttributePerObjectUniform(const LightManagerStateAttributePerObjectUniform& copy, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY)
|
|
||||||
: osg::StateAttribute(copy,copyop), mLightManager(copy.mLightManager) {}
|
|
||||||
|
|
||||||
int compare(const StateAttribute &sa) const override
|
|
||||||
{
|
|
||||||
throw std::runtime_error("LightManagerStateAttributePerObjectUniform::compare: unimplemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
META_StateAttribute(NifOsg, LightManagerStateAttributePerObjectUniform, osg::StateAttribute::LIGHT)
|
|
||||||
|
|
||||||
void apply(osg::State& state) const override
|
|
||||||
{
|
|
||||||
mLightManager->getStateSet()->getUniform("LightBuffer")->setElement(0, mLightManager->getSunlightBuffer(state.getFrameStamp()->getFrameNumber()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
LightManager* mLightManager;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::unordered_map<std::string, LightingMethod> LightManager::mLightingMethodSettingMap = {
|
const std::unordered_map<std::string, LightingMethod> LightManager::mLightingMethodSettingMap = {
|
||||||
|
@ -857,6 +842,14 @@ namespace SceneUtil
|
||||||
, mPointLightFadeEnd(0.f)
|
, mPointLightFadeEnd(0.f)
|
||||||
, mPointLightFadeStart(0.f)
|
, mPointLightFadeStart(0.f)
|
||||||
{
|
{
|
||||||
|
osg::GLExtensions* exts = osg::GLExtensions::Get(0, false);
|
||||||
|
bool supportsUBO = exts && exts->isUniformBufferObjectSupported;
|
||||||
|
bool supportsGPU4 = exts && exts->isGpuShader4Supported;
|
||||||
|
|
||||||
|
mSupported[static_cast<int>(LightingMethod::FFP)] = true;
|
||||||
|
mSupported[static_cast<int>(LightingMethod::PerObjectUniform)] = true;
|
||||||
|
mSupported[static_cast<int>(LightingMethod::SingleUBO)] = supportsUBO && supportsGPU4;
|
||||||
|
|
||||||
setUpdateCallback(new LightManagerUpdateCallback);
|
setUpdateCallback(new LightManagerUpdateCallback);
|
||||||
|
|
||||||
if (ffp)
|
if (ffp)
|
||||||
|
@ -870,10 +863,6 @@ namespace SceneUtil
|
||||||
|
|
||||||
updateSettings();
|
updateSettings();
|
||||||
|
|
||||||
osg::GLExtensions* exts = osg::GLExtensions::Get(0, false);
|
|
||||||
bool supportsUBO = exts && exts->isUniformBufferObjectSupported;
|
|
||||||
bool supportsGPU4 = exts && exts->isGpuShader4Supported;
|
|
||||||
|
|
||||||
static bool hasLoggedWarnings = false;
|
static bool hasLoggedWarnings = false;
|
||||||
|
|
||||||
if (lightingMethod == LightingMethod::SingleUBO && !hasLoggedWarnings)
|
if (lightingMethod == LightingMethod::SingleUBO && !hasLoggedWarnings)
|
||||||
|
@ -1046,7 +1035,8 @@ namespace SceneUtil
|
||||||
setLightingMethod(LightingMethod::PerObjectUniform);
|
setLightingMethod(LightingMethod::PerObjectUniform);
|
||||||
setMaxLights(std::clamp(targetLights, mMaxLightsLowerLimit, mMaxLightsUpperLimit));
|
setMaxLights(std::clamp(targetLights, mMaxLightsLowerLimit, mMaxLightsUpperLimit));
|
||||||
|
|
||||||
stateset->setAttributeAndModes(new LightManagerStateAttributePerObjectUniform(this), osg::StateAttribute::ON);
|
// ensures sunlight element in our uniform array is updated when there are no point lights in scene
|
||||||
|
stateset->setAttributeAndModes(new LightStateAttributePerObjectUniform({}, 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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include <osg/Light>
|
#include <osg/Light>
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ namespace osgUtil
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
class LightBuffer;
|
class LightBuffer;
|
||||||
class StateSetGenerator;
|
struct StateSetGenerator;
|
||||||
|
|
||||||
enum class LightingMethod
|
enum class LightingMethod
|
||||||
{
|
{
|
||||||
|
@ -33,8 +34,6 @@ namespace SceneUtil
|
||||||
SingleUBO,
|
SingleUBO,
|
||||||
};
|
};
|
||||||
|
|
||||||
void configureStateSetSunOverride(LightingMethod method, const osg::Light* light, osg::StateSet* stateset, int mode = osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
|
||||||
|
|
||||||
/// LightSource managed by a LightManager.
|
/// LightSource managed by a LightManager.
|
||||||
/// @par Typically used for point lights. Spot lights are not supported yet. Directional lights affect the whole scene
|
/// @par Typically used for point lights. Spot lights are not supported yet. Directional lights affect the whole scene
|
||||||
/// so do not need to be managed by a LightManager - so for directional lights use a plain osg::LightSource instead.
|
/// so do not need to be managed by a LightManager - so for directional lights use a plain osg::LightSource instead.
|
||||||
|
@ -130,6 +129,7 @@ namespace SceneUtil
|
||||||
};
|
};
|
||||||
|
|
||||||
using LightList = std::vector<const LightSourceViewBound*>;
|
using LightList = std::vector<const LightSourceViewBound*>;
|
||||||
|
using SupportedMethods = std::array<bool, 3>;
|
||||||
|
|
||||||
META_Node(SceneUtil, LightManager)
|
META_Node(SceneUtil, LightManager)
|
||||||
|
|
||||||
|
@ -178,6 +178,8 @@ namespace SceneUtil
|
||||||
osg::Matrixf getSunlightBuffer(size_t frameNum) const { return mSunlightBuffers[frameNum%2]; }
|
osg::Matrixf getSunlightBuffer(size_t frameNum) const { return mSunlightBuffers[frameNum%2]; }
|
||||||
void setSunlightBuffer(const osg::Matrixf& buffer, size_t frameNum) { mSunlightBuffers[frameNum%2] = buffer; }
|
void setSunlightBuffer(const osg::Matrixf& buffer, size_t frameNum) { mSunlightBuffers[frameNum%2] = buffer; }
|
||||||
|
|
||||||
|
SupportedMethods getSupportedLightingMethods() { return mSupported; }
|
||||||
|
|
||||||
std::map<std::string, std::string> getLightDefines() const;
|
std::map<std::string, std::string> getLightDefines() const;
|
||||||
|
|
||||||
void processChangedSettings(const Settings::CategorySettingVector& changed);
|
void processChangedSettings(const Settings::CategorySettingVector& changed);
|
||||||
|
@ -232,6 +234,8 @@ namespace SceneUtil
|
||||||
|
|
||||||
int mMaxLights;
|
int mMaxLights;
|
||||||
|
|
||||||
|
SupportedMethods mSupported;
|
||||||
|
|
||||||
static constexpr auto mMaxLightsLowerLimit = 2;
|
static constexpr auto mMaxLightsLowerLimit = 2;
|
||||||
static constexpr auto mMaxLightsUpperLimit = 64;
|
static constexpr auto mMaxLightsUpperLimit = 64;
|
||||||
static constexpr auto mFFPMaxLights = 8;
|
static constexpr auto mFFPMaxLights = 8;
|
||||||
|
@ -277,6 +281,8 @@ namespace SceneUtil
|
||||||
std::set<SceneUtil::LightSource*> mIgnoredLightSources;
|
std::set<SceneUtil::LightSource*> mIgnoredLightSources;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void configureStateSetSunOverride(LightManager* lightManager, const osg::Light* light, osg::StateSet* stateset, int mode = osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -174,12 +174,14 @@ this mode when supported and where the GPU is not a bottleneck. On some weaker
|
||||||
devices, using this mode along with :ref:`force per pixel lighting` can carry
|
devices, using this mode along with :ref:`force per pixel lighting` can carry
|
||||||
performance penalties.
|
performance penalties.
|
||||||
|
|
||||||
Note that when enabled, groundcover lighting is forced to be vertex lighting,
|
When enabled, groundcover lighting is forced to be vertex lighting, unless
|
||||||
unless normal maps are provided. This is due to some groundcover mods using the
|
normal maps are provided. This is due to some groundcover mods using the Z-Up
|
||||||
Z-Up normals technique to avoid some common issues with shading. As a
|
normals technique to avoid some common issues with shading. As a consequence,
|
||||||
consequence, per pixel lighting would give undesirable results.
|
per pixel lighting would give undesirable results.
|
||||||
|
|
||||||
This setting has no effect if :ref:`force shaders` is 'false'.
|
Note that the rendering will act as if you have 'force shaders' option enabled
|
||||||
|
when not set to 'legacy'. This means that shaders will be used to render all objects and
|
||||||
|
the terrain.
|
||||||
|
|
||||||
light bounds multiplier
|
light bounds multiplier
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
|
@ -460,15 +460,14 @@
|
||||||
|
|
||||||
<Widget type="TabItem" skin="" position="4 32 360 308">
|
<Widget type="TabItem" skin="" position="4 32 360 308">
|
||||||
<Property key="Caption" value=" Lights "/>
|
<Property key="Caption" value=" Lights "/>
|
||||||
<Widget type="Widget" skin="" position="0 0 360 315" align="Stretch">
|
|
||||||
<Widget type="Widget" skin="" position="0 0 360 315" align="Stretch" name="LightSettingOverlay">
|
|
||||||
<!-- Lighting Method -->
|
<!-- Lighting Method -->
|
||||||
<Widget type="TextBox" skin="NormalText" position="0 4 170 18" align="Left Top">
|
<Widget type="TextBox" skin="NormalText" position="0 4 170 18" align="Left Top">
|
||||||
<Property key="Caption" value="Lighting Method:"/>
|
<Property key="Caption" value="Lighting Method:"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="TextBox" skin="SandText" position="0 28 170 18" align="Left Top" name="LightingMethodText">
|
<Widget type="ComboBox" skin="MW_ComboBox" position="0 28 170 24" align="Left Top" name="LightingMethodButton">
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
<Property key="AddItem" value="legacy"/>
|
||||||
<UserString key="ToolTipLayout" value="TextToolTip"/>
|
<Property key="AddItem" value="shaders compatibility"/>
|
||||||
|
<Property key="AddItem" value="shaders"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<!-- Max Lights -->
|
<!-- Max Lights -->
|
||||||
<Widget type="TextBox" skin="NormalText" position="178 4 160 18" align="Left Top" name="MaxLightsText">
|
<Widget type="TextBox" skin="NormalText" position="178 4 160 18" align="Left Top" name="MaxLightsText">
|
||||||
|
@ -476,17 +475,19 @@
|
||||||
<UserString key="ToolTipLayout" value="TextToolTip"/>
|
<UserString key="ToolTipLayout" value="TextToolTip"/>
|
||||||
<UserString key="Caption_Text" value="Default: 8\nMaximum number of lights per object.\n\nA low number near default will cause light popping similar to what you would see with legacy lighting."/>
|
<UserString key="Caption_Text" value="Default: 8\nMaximum number of lights per object.\n\nA low number near default will cause light popping similar to what you would see with legacy lighting."/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="ScrollBar" skin="MW_HScroll" position="178 30 160 18" align="Right Top HStretch" name="MaxLightsSlider">
|
<Widget type="ScrollBar" skin="" position="0 0 0 0">
|
||||||
<Property key="Range" value="24"/>
|
|
||||||
<Property key="Page" value="1"/>
|
|
||||||
<UserString key="SettingType" value="Slider"/>
|
<UserString key="SettingType" value="Slider"/>
|
||||||
<UserString key="SettingMin" value="4"/>
|
|
||||||
<UserString key="SettingMax" value="32"/>
|
|
||||||
<UserString key="SettingCategory" value="Shaders"/>
|
<UserString key="SettingCategory" value="Shaders"/>
|
||||||
<UserString key="SettingName" value="max lights"/>
|
<UserString key="SettingName" value="max lights"/>
|
||||||
<UserString key="SettingValueType" value="Integer"/>
|
<UserString key="SettingValueType" value="Integer"/>
|
||||||
<UserString key="SettingLabelWidget" value="MaxLightsText"/>
|
<UserString key="SettingLabelWidget" value="MaxLightsText"/>
|
||||||
<UserString key="SettingLabelCaption" value="Max Lights (%s)"/>
|
<UserString key="SettingLabelCaption" value="Max Lights: (%s)"/>
|
||||||
|
</Widget>
|
||||||
|
<Widget type="ComboBox" skin="MW_ComboBox" position="178 28 170 24" align="Left Top" name="MaxLights">
|
||||||
|
<Property key="AddItem" value="8"/>
|
||||||
|
<Property key="AddItem" value="16"/>
|
||||||
|
<Property key="AddItem" value="24"/>
|
||||||
|
<Property key="AddItem" value="32"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="ImageBox" skin="MW_HLine" position="0 54 360 18" align="Top HStretch"/>
|
<Widget type="ImageBox" skin="MW_HLine" position="0 54 360 18" align="Top HStretch"/>
|
||||||
<!-- Light Fade Start -->
|
<!-- Light Fade Start -->
|
||||||
|
@ -511,7 +512,7 @@
|
||||||
<Widget type="TextBox" skin="NormalText" position="0 128 352 18" align="Left Top" name="LightFadeMultiplierText">
|
<Widget type="TextBox" skin="NormalText" position="0 128 352 18" align="Left Top" name="LightFadeMultiplierText">
|
||||||
<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.85\nFraction of maximum distance at which lights will start to fade.\n\nSet this to a low value for slower transitions or a high value of quicker transitions."/>
|
<UserString key="Caption_Text" value="Default: 0.85\nFraction of maximum distance at which lights will start to fade.\n\nSet this to a low value for slower transitions or a high value for quicker transitions."/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="ScrollBar" skin="MW_HScroll" position="0 152 352 18" align="HStretch Top">
|
<Widget type="ScrollBar" skin="MW_HScroll" position="0 152 352 18" align="HStretch Top">
|
||||||
<Property key="Range" value="10000"/>
|
<Property key="Range" value="10000"/>
|
||||||
|
@ -563,8 +564,6 @@
|
||||||
<Property key="Caption" value="Reset To Defaults"/>
|
<Property key="Caption" value="Reset To Defaults"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Widget>
|
|
||||||
</Widget>
|
|
||||||
<!--
|
<!--
|
||||||
<Widget type="TabItem" skin="" position="0 28 352 268">
|
<Widget type="TabItem" skin="" position="0 28 352 268">
|
||||||
<Widget type="Widget" skin="" position="0 28 352 268">
|
<Widget type="Widget" skin="" position="0 28 352 268">
|
||||||
|
|
Loading…
Reference in a new issue