diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ce7fe801a..9e72448d28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ Feature #7058: Implement TestModels (T3D) console command Feature #7087: Block resolution change in the Windowed Fullscreen mode Feature #7125: Remembering console commands between sessions + Feature #7129: Add support for non-adaptive VSync Feature #7130: Ability to set MyGUI logging verbosity Feature #7148: Optimize string literal lookup in mwscript Feature #7194: Ori to show texture paths diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index e545340c83..5f37c0defe 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -93,13 +93,18 @@ bool Launcher::GraphicsPage::loadSettings() return false; // Visuals - if (Settings::Manager::getBool("vsync", "Video")) - vSyncCheckBox->setCheckState(Qt::Checked); + + int vsync = Settings::Manager::getInt("vsync mode", "Video"); + if (vsync < 0 || vsync > 2) + vsync = 0; + + vSyncComboBox->setCurrentIndex(vsync); size_t windowMode = static_cast(Settings::Manager::getInt("window mode", "Video")); if (windowMode > static_cast(Settings::WindowMode::Windowed)) windowMode = 0; windowModeComboBox->setCurrentIndex(windowMode); + slotFullScreenChanged(windowMode); if (Settings::Manager::getBool("window border", "Video")) windowBorderCheckBox->setCheckState(Qt::Checked); @@ -185,9 +190,9 @@ void Launcher::GraphicsPage::saveSettings() // Ensure we only set the new settings if they changed. This is to avoid cluttering the // user settings file (which by definition should only contain settings the user has touched) - bool cVSync = vSyncCheckBox->checkState(); - if (cVSync != Settings::Manager::getBool("vsync", "Video")) - Settings::Manager::setBool("vsync", "Video", cVSync); + int cVSync = vSyncComboBox->currentIndex(); + if (cVSync != Settings::Manager::getInt("vsync mode", "Video")) + Settings::Manager::setInt("vsync mode", "Video", cVSync); int cWindowMode = windowModeComboBox->currentIndex(); if (cWindowMode != Settings::Manager::getInt("window mode", "Video")) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index d56ae789e6..409f530d0b 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -473,7 +473,7 @@ void OMW::Engine::createWindow() Settings::WindowMode windowMode = static_cast(Settings::Manager::getInt("window mode", "Video")); bool windowBorder = Settings::Manager::getBool("window border", "Video"); - bool vsync = Settings::Manager::getBool("vsync", "Video"); + int vsync = Settings::Manager::getInt("vsync mode", "Video"); unsigned int antialiasing = std::max(0, Settings::Manager::getInt("antialiasing", "Video")); int pos_x = SDL_WINDOWPOS_CENTERED_DISPLAY(screen), pos_y = SDL_WINDOWPOS_CENTERED_DISPLAY(screen); @@ -560,10 +560,10 @@ void OMW::Engine::createWindow() traits->windowName = SDL_GetWindowTitle(mWindow); traits->windowDecoration = !(SDL_GetWindowFlags(mWindow) & SDL_WINDOW_BORDERLESS); traits->screenNum = SDL_GetWindowDisplayIndex(mWindow); - traits->vsync = vsync; + traits->vsync = 0; traits->inheritedWindowData = new SDLUtil::GraphicsWindowSDL2::WindowData(mWindow); - graphicsWindow = new SDLUtil::GraphicsWindowSDL2(traits); + graphicsWindow = new SDLUtil::GraphicsWindowSDL2(traits, vsync); if (!graphicsWindow->valid()) throw std::runtime_error("Failed to create GraphicsContext"); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index d7031fffef..819a2f1328 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -256,6 +256,7 @@ namespace MWGui getWidget(mOkButton, "OkButton"); getWidget(mResolutionList, "ResolutionList"); getWidget(mWindowModeList, "WindowModeList"); + getWidget(mVSyncModeList, "VSyncModeList"); getWidget(mWindowBorderButton, "WindowBorderButton"); getWidget(mTextureFilteringButton, "TextureFilteringButton"); getWidget(mControlsBox, "ControlsBox"); @@ -315,6 +316,7 @@ namespace MWGui mMaxLights->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onMaxLightsChanged); mWindowModeList->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWindowModeChanged); + mVSyncModeList->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onVSyncModeChanged); mKeyboardSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onKeyboardSwitchClicked); mControllerSwitch->eventMouseButtonClick @@ -562,6 +564,16 @@ namespace MWGui Settings::Manager::setStringArray("preferred locales", "General", currentLocales); } + void SettingsWindow::onVSyncModeChanged(MyGUI::ComboBox* _sender, size_t pos) + { + if (pos == MyGUI::ITEM_NONE) + return; + + int index = static_cast(_sender->getIndexSelected()); + Settings::Manager::setInt("vsync mode", "Video", index); + apply(); + } + void SettingsWindow::onWindowModeChanged(MyGUI::ComboBox* _sender, size_t pos) { if (pos == MyGUI::ITEM_NONE) @@ -870,6 +882,16 @@ namespace MWGui mResolutionList->setEnabled(false); } + void SettingsWindow::updateVSyncModeSettings() + { + int index = static_cast(Settings::Manager::getInt("vsync mode", "Video")); + + if (index < 0 || index > 2) + index = 0; + + mVSyncModeList->setIndexSelected(index); + } + void SettingsWindow::layoutControlsBox() { const int h = MWBase::Environment::get().getWindowManager()->getFontHeight() + 2; @@ -1033,6 +1055,7 @@ namespace MWGui updateControlsBox(); updateLightSettings(); updateWindowModeSettings(); + updateVSyncModeSettings(); resetScrollbars(); renderScriptSettings(); MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton); diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index f75e911633..d5c3bfac1f 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -18,6 +18,8 @@ namespace MWGui void updateLightSettings(); + void updateVSyncModeSettings(); + void updateWindowModeSettings(); void onResChange(int, int) override; @@ -29,6 +31,7 @@ namespace MWGui // graphics MyGUI::ListBox* mResolutionList; MyGUI::ComboBox* mWindowModeList; + MyGUI::ComboBox* mVSyncModeList; MyGUI::Button* mWindowBorderButton; MyGUI::ComboBox* mTextureFilteringButton; @@ -83,6 +86,7 @@ namespace MWGui void onLanguageChanged(size_t langPriority, MyGUI::ComboBox* _sender, size_t pos); void onWindowModeChanged(MyGUI::ComboBox* _sender, size_t pos); + void onVSyncModeChanged(MyGUI::ComboBox* _sender, size_t pos); void onRebindAction(MyGUI::Widget* _sender); void onInputTabMouseWheel(MyGUI::Widget* _sender, int _rel); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 45efe08bd5..103ee340f3 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1148,8 +1148,8 @@ namespace MWGui || setting.second == "window mode" || setting.second == "window border")) changeRes = true; - else if (setting.first == "Video" && setting.second == "vsync") - mVideoWrapper->setSyncToVBlank(Settings::Manager::getBool("vsync", "Video")); + else if (setting.first == "Video" && setting.second == "vsync mode") + mVideoWrapper->setSyncToVBlank(Settings::Manager::getInt("vsync mode", "Video")); else if (setting.first == "Video" && (setting.second == "gamma" || setting.second == "contrast")) mVideoWrapper->setGammaContrast( Settings::Manager::getFloat("gamma", "Video"), Settings::Manager::getFloat("contrast", "Video")); diff --git a/components/sdlutil/sdlgraphicswindow.cpp b/components/sdlutil/sdlgraphicswindow.cpp index 61ade61a35..3c2efc3728 100644 --- a/components/sdlutil/sdlgraphicswindow.cpp +++ b/components/sdlutil/sdlgraphicswindow.cpp @@ -14,7 +14,7 @@ namespace SDLUtil close(true); } - GraphicsWindowSDL2::GraphicsWindowSDL2(osg::GraphicsContext::Traits* traits) + GraphicsWindowSDL2::GraphicsWindowSDL2(osg::GraphicsContext::Traits* traits, int vsync) : mWindow(nullptr) , mContext(nullptr) , mValid(false) @@ -23,6 +23,13 @@ namespace SDLUtil { _traits = traits; + if (vsync == 2) + mVSyncMode = VSyncMode::Adaptive; + else if (vsync == 1) + mVSyncMode = VSyncMode::Enabled; + else + mVSyncMode = VSyncMode::Disabled; + init(); if (GraphicsWindowSDL2::valid()) { @@ -134,7 +141,7 @@ namespace SDLUtil openmw_gl4es_init(mWindow); #endif - setSwapInterval(_traits->vsync); + setSwapInterval(mVSyncMode); // Update traits with what we've actually been given // Use intermediate to avoid signed/unsigned mismatch @@ -233,29 +240,41 @@ namespace SDLUtil } void GraphicsWindowSDL2::setSyncToVBlank(bool on) + { + throw std::runtime_error( + "setSyncToVBlank with bool argument is not supported. Use the VSyncMode argument instead."); + } + + void GraphicsWindowSDL2::setSyncToVBlank(VSyncMode mode) { SDL_Window* oldWin = SDL_GL_GetCurrentWindow(); SDL_GLContext oldCtx = SDL_GL_GetCurrentContext(); SDL_GL_MakeCurrent(mWindow, mContext); - setSwapInterval(on); + setSwapInterval(mode); SDL_GL_MakeCurrent(oldWin, oldCtx); } - void GraphicsWindowSDL2::setSwapInterval(bool enable) + void GraphicsWindowSDL2::setSwapInterval(VSyncMode mode) { - if (enable) + mVSyncMode = mode; + + if (mode == VSyncMode::Adaptive) { if (SDL_GL_SetSwapInterval(-1) == -1) { OSG_NOTICE << "Adaptive vsync unsupported" << std::endl; - if (SDL_GL_SetSwapInterval(1) == -1) - { - OSG_NOTICE << "Vertical synchronization unsupported, disabling" << std::endl; - SDL_GL_SetSwapInterval(0); - } + setSwapInterval(VSyncMode::Enabled); + } + } + else if (mode == VSyncMode::Enabled) + { + if (SDL_GL_SetSwapInterval(1) == -1) + { + OSG_NOTICE << "Vertical synchronization unsupported, disabling" << std::endl; + setSwapInterval(VSyncMode::Disabled); } } else diff --git a/components/sdlutil/sdlgraphicswindow.hpp b/components/sdlutil/sdlgraphicswindow.hpp index 366ac55f4d..3af6ef9276 100644 --- a/components/sdlutil/sdlgraphicswindow.hpp +++ b/components/sdlutil/sdlgraphicswindow.hpp @@ -7,6 +7,12 @@ namespace SDLUtil { + enum VSyncMode + { + Disabled = 0, + Enabled = 1, + Adaptive = 2 + }; class GraphicsWindowSDL2 : public osgViewer::GraphicsWindow { @@ -16,13 +22,14 @@ namespace SDLUtil bool mValid; bool mRealized; bool mOwnsWindow; + VSyncMode mVSyncMode; void init(); virtual ~GraphicsWindowSDL2(); public: - GraphicsWindowSDL2(osg::GraphicsContext::Traits* traits); + GraphicsWindowSDL2(osg::GraphicsContext::Traits* traits, int vsync); bool isSameKindAs(const Object* object) const override { @@ -53,6 +60,7 @@ namespace SDLUtil /** Set sync-to-vblank. */ void setSyncToVBlank(bool on) override; + void setSyncToVBlank(VSyncMode mode); /** Set Window decoration.*/ bool setWindowDecorationImplementation(bool flag) override; @@ -87,7 +95,7 @@ namespace SDLUtil }; private: - void setSwapInterval(bool enable); + void setSwapInterval(VSyncMode mode); }; } diff --git a/components/sdlutil/sdlvideowrapper.cpp b/components/sdlutil/sdlvideowrapper.cpp index 17c67154ad..714c11d079 100644 --- a/components/sdlutil/sdlvideowrapper.cpp +++ b/components/sdlutil/sdlvideowrapper.cpp @@ -1,6 +1,7 @@ #include "sdlvideowrapper.hpp" #include +#include #include #include @@ -29,15 +30,24 @@ namespace SDLUtil SDL_SetWindowGammaRamp(mWindow, mOldSystemGammaRamp, &mOldSystemGammaRamp[256], &mOldSystemGammaRamp[512]); } - void VideoWrapper::setSyncToVBlank(bool sync) + void VideoWrapper::setSyncToVBlank(int mode) { + VSyncMode vsyncMode = VSyncMode::Disabled; + if (mode == 1) + vsyncMode = VSyncMode::Enabled; + else if (mode == 2) + vsyncMode = VSyncMode::Adaptive; + osgViewer::Viewer::Windows windows; mViewer->getWindows(windows); mViewer->stopThreading(); for (osgViewer::Viewer::Windows::iterator it = windows.begin(); it != windows.end(); ++it) { osgViewer::GraphicsWindow* win = *it; - win->setSyncToVBlank(sync); + if (GraphicsWindowSDL2* sdl2win = dynamic_cast(win)) + sdl2win->setSyncToVBlank(vsyncMode); + else + win->setSyncToVBlank(static_cast(mode)); } mViewer->startThreading(); } diff --git a/components/sdlutil/sdlvideowrapper.hpp b/components/sdlutil/sdlvideowrapper.hpp index ace3be6276..9ed6ff1252 100644 --- a/components/sdlutil/sdlvideowrapper.hpp +++ b/components/sdlutil/sdlvideowrapper.hpp @@ -26,7 +26,7 @@ namespace SDLUtil VideoWrapper(SDL_Window* window, osg::ref_ptr viewer); ~VideoWrapper(); - void setSyncToVBlank(bool sync); + void setSyncToVBlank(int mode); void setGammaContrast(float gamma, float contrast); diff --git a/docs/source/reference/modding/settings/video.rst b/docs/source/reference/modding/settings/video.rst index b05fbf0380..94fb54be18 100644 --- a/docs/source/reference/modding/settings/video.rst +++ b/docs/source/reference/modding/settings/video.rst @@ -125,22 +125,25 @@ This setting can be configured from a list of valid choices in the Graphics pane but cannot be changed during game play due to a technical limitation that may be addressed in a future version of OpenMW. -vsync ------ +vsync mode +---------- -:Type: boolean -:Range: True/False -:Default: False +:Type: integer +:Range: 0, 1, 2 +:Default: 0 This setting determines whether frame draws are synchronized with the vertical refresh rate of your monitor. Enabling this setting can reduce screen tearing, a visual defect caused by updating the image buffer in the middle of a screen draw. -Enabling this option typically implies limiting the framerate to the refresh rate of your monitor, +Enabling this option (1 or 2) typically implies limiting the framerate to the refresh rate of your monitor, but may also introduce additional delays caused by having to wait until the appropriate time (the vertical blanking interval) to draw a frame, and a loss in mouse responsiveness known as 'input lag'. +Mode 2 of this option corresponds to the use of adaptive vsync. Adaptive vsync is turned off if the framerate +cannot reach your display's refresh rate. This prevents the input lag from becoming unbearable but may lead to tearing. +Some hardware might not support this mode, in which case traditional vsync will be used. -This setting can be adjusted in game using the VSync button in the Video tab of the Video panel in the Options menu. -It can also be changed by toggling the Vertical Sync check box in the Graphics tab of the OpenMW Launcher. +This setting can be adjusted in game using the VSync combo box in the Video tab of the Video panel in the Options menu. +It can also be changed by toggling the Vertical Sync combo box in the Graphics tab of the OpenMW Launcher. framerate limit --------------- diff --git a/files/data/l10n/OMWEngine/en.yaml b/files/data/l10n/OMWEngine/en.yaml index 49725aba2a..be91a446cc 100644 --- a/files/data/l10n/OMWEngine/en.yaml +++ b/files/data/l10n/OMWEngine/en.yaml @@ -77,6 +77,7 @@ TextureFilteringTrilinear: "Trilinear" ToggleHUD: "Toggle HUD" TogglePostProcessorHUD: "Toggle Post Processor HUD" VSync: "VSync" +VSyncAdaptive: "Adaptive" Water: "Water" WaterShader: "Water shader" WaterShaderTextureQuality: "Texture quality" diff --git a/files/data/l10n/OMWEngine/ru.yaml b/files/data/l10n/OMWEngine/ru.yaml index 35beec7f32..11e93dd031 100644 --- a/files/data/l10n/OMWEngine/ru.yaml +++ b/files/data/l10n/OMWEngine/ru.yaml @@ -77,6 +77,7 @@ TextureFilteringTrilinear: "Трилинейная" ToggleHUD: "Переключить HUD" TogglePostProcessorHUD: "Меню настроек постобработки" VSync: "Вертикальная синхронизация" +VSyncAdaptive: "Адаптивная" Water: "Вода" WaterShader: "Шейдер воды" WaterShaderTextureQuality: "Качество текстуры воды" diff --git a/files/data/mygui/openmw_settings_window.layout b/files/data/mygui/openmw_settings_window.layout index 59e9d44ecc..61a25cf2f6 100644 --- a/files/data/mygui/openmw_settings_window.layout +++ b/files/data/mygui/openmw_settings_window.layout @@ -275,28 +275,28 @@ - - + + - + - - - - - - - - + + + + + + + + - + @@ -306,7 +306,7 @@ - + @@ -320,11 +320,11 @@ - + - - + + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 3c6395a63e..f615ab443d 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -627,8 +627,11 @@ window border = true # Anti-aliasing reduces jagged polygon edges. (0, 2, 4, 8, 16). antialiasing = 0 -# Enable vertical syncing to reduce tearing defects. -vsync = false +# Vertical syncing to reduce tearing defects. +# 0 = Off +# 1 = On +# 2 = Adaptive +vsync mode = 0 # Maximum frames per second. 0.0 is unlimited, or >0.0 to limit. framerate limit = 300 diff --git a/files/ui/graphicspage.ui b/files/ui/graphicspage.ui index 8cf26aa1e2..bb900ccb2d 100644 --- a/files/ui/graphicspage.ui +++ b/files/ui/graphicspage.ui @@ -7,7 +7,7 @@ 0 0 650 - 340 + 358 @@ -22,190 +22,210 @@ - - - - + + + + + Screen: + + + + + + - Anti-aliasing: + 0 - - - - + + - Framerate Limit: + 2 - - - - - - - - - - 800 - - - - - - - x - - - - - - - 600 - - - - - - - - - Custom: - - - - - - - Standard: - - - true - - - - - - - - - - - - false - - - FPS - - - 1 - - - 1 - - - 1000 - - - 15 - - - 300 + + + + 4 - - - - + + - Window Border + 8 - - - - - - 0 + + + + 16 - - - Fullscreen - - - - - Windowed Fullscreen - - - - - Windowed - - + + + + + + + + + + Window Mode: + + + + + + + Resolution: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Vertical Sync: + + + + + + + Anti-aliasing: + + + + + + + + + + + 800 + + + + + + + x + + + + + + + 600 + + + + + + + + + Custom: + - - - + + + + + Standard: + + + true + + + + + + + + + + + + 0 + + - Window Mode: + Fullscreen - - - - + + - Resolution: + Windowed Fullscreen - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + Windowed - - - - - - - + + + + + + + Window Border + + + + + + + 0 + + - Screen: + Disabled - - - - - - - 0 - - - - - 2 - - - - - 4 - - - - - 8 - - - - - 16 - - - - - - + + - Vertical Sync + Enabled - - - - + + + + Adaptive + + + + + + + + Framerate Limit: + + + + + + + false + + + FPS + + + 1 + + + 1.000000000000000 + + + 1000.000000000000000 + + + 15.000000000000000 + + + 300.000000000000000 + + + + @@ -265,192 +285,182 @@ - - - - 1 - 1 - - - - - - - - <html><head/><body><p>Enable shadows exclusively for the player character. May have a very minor performance impact.</p></body></html> - - - Enable Player Shadows - - - - - - - <html><head/><body><p>Enable shadows for NPCs and creatures besides the player character. May have a minor performance impact.</p></body></html> - - - Enable Actor Shadows - - - - - - - <html><head/><body><p>Enable shadows for primarily inanimate objects. May have a significant performance impact.</p></body></html> - + + + + + <html><head/><body><p>Enable shadows exclusively for the player character. May have a very minor performance impact.</p></body></html> + + + Enable Player Shadows + + + + + + + <html><head/><body><p>Enable shadows for NPCs and creatures besides the player character. May have a minor performance impact.</p></body></html> + + + Enable Actor Shadows + + + + + + + <html><head/><body><p>Enable shadows for primarily inanimate objects. May have a significant performance impact.</p></body></html> + + + Enable Object Shadows + + + + + + + <html><head/><body><p>Enable shadows for the terrain including distant terrain. May have a significant performance and shadow quality impact.</p></body></html> + + + Enable Terrain Shadows + + + + + + + <html><head/><body><p>Due to limitations with Morrowind's data, only actors can cast shadows indoors, which some might feel is distracting.</p><p>Has no effect if actor/player shadows are not enabled.</p></body></html> + + + Enable Indoor Shadows + + + + + + + <html><head/><body><p>Type of "compute scene bounds" computation method to be used. Bounds (default) for good balance between performance and shadow quality, primitives for better looking shadows or none for no computation.</p></body></html> + + + Shadow Near Far Computation Method: + + + + + + - Enable Object Shadows - - - - - - - <html><head/><body><p>Enable shadows for the terrain including distant terrain. May have a significant performance and shadow quality impact.</p></body></html> + bounds + + - Enable Terrain Shadows - - - - - - - <html><head/><body><p>Due to limitations with Morrowind's data, only actors can cast shadows indoors, which some might feel is distracting.</p><p>Has no effect if actor/player shadows are not enabled.</p></body></html> + primitives + + - Enable Indoor Shadows - - - - - - - <html><head/><body><p>Type of "compute scene bounds" computation method to be used. Bounds (default) for good balance between performance and shadow quality, primitives for better looking shadows or none for no computation.</p></body></html> + none + + + + + + + <html><head/><body><p>The resolution of each individual shadow map. Increasing it significantly improves shadow quality but may have a minor performance impact.</p></body></html> + + + Shadow Map Resolution: + + + + + + - Shadow Near Far Computation Method: - - - - compute scene bounds - - - - bounds - - - - - primitives - - - - - none - - - - - - - - <html><head/><body><p>The resolution of each individual shadow map. Increasing it significantly improves shadow quality but may have a minor performance impact.</p></body></html> + 512 + + - Shadow Map Resolution: - - - - - - - - 512 - - - - - 1024 - - - - - 2048 - - - - - 4096 - - - - - - - - <html><head/><body><p>The distance from the camera at which shadows completely disappear.</p></body></html> + 1024 + + - Shadow Distance Limit: - - - - - - - false - - - <html><head/><body><p>64 game units is 1 real life yard or about 0.9 m</p></body></html> - - - unit(s) - - - 512 - - - 81920 - - - 8192 - - - - - - - <html><head/><body><p>The fraction of the limit above at which shadows begin to gradually fade away.</p></body></html> + 2048 + + - Fade Start Multiplier: + 4096 - - - - - - false - - - 2 - - - 0 - - - 1 - - - 0.90 - - - - - - + + + + + + + <html><head/><body><p>The distance from the camera at which shadows completely disappear.</p></body></html> + + + Shadow Distance Limit: + + + + + + + false + + + <html><head/><body><p>64 game units is 1 real life yard or about 0.9 m</p></body></html> + + + unit(s) + + + 512 + + + 81920 + + + 8192 + + + + + + + <html><head/><body><p>The fraction of the limit above at which shadows begin to gradually fade away.</p></body></html> + + + Fade Start Multiplier: + + + + + + + false + + + 2 + + + 0.000000000000000 + + + 1.000000000000000 + + + 0.900000000000000 + + + +