From 76105cc2d1efe12d736f9f3dec409bd1a8e04d90 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Fri, 29 Mar 2024 09:34:52 +0300 Subject: [PATCH] Make sunlight scattering and wobbly shores optional --- apps/openmw/mwgui/settingswindow.cpp | 17 +++++++++++ apps/openmw/mwgui/settingswindow.hpp | 4 +++ apps/openmw/mwrender/water.cpp | 2 ++ components/settings/categories/water.hpp | 2 ++ .../reference/modding/settings/water.rst | 28 +++++++++++++++++ files/data/l10n/OMWEngine/en.yaml | 2 ++ files/data/l10n/OMWEngine/ru.yaml | 2 ++ .../data/mygui/openmw_settings_window.layout | 30 ++++++++++++++++++- files/settings-default.cfg | 6 ++++ files/shaders/compatibility/water.frag | 17 ++++++++--- 10 files changed, 105 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index b569132141..396d0b18a3 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -266,6 +266,9 @@ namespace MWGui getWidget(mResetControlsButton, "ResetControlsButton"); getWidget(mKeyboardSwitch, "KeyboardButton"); getWidget(mControllerSwitch, "ControllerButton"); + getWidget(mWaterRefractionButton, "WaterRefractionButton"); + getWidget(mSunlightScatteringButton, "SunlightScatteringButton"); + getWidget(mWobblyShoresButton, "WobblyShoresButton"); getWidget(mWaterTextureSize, "WaterTextureSize"); getWidget(mWaterReflectionDetail, "WaterReflectionDetail"); getWidget(mWaterRainRippleDetail, "WaterRainRippleDetail"); @@ -306,6 +309,8 @@ namespace MWGui += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringChanged); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); + mWaterRefractionButton->eventMouseButtonClick + += MyGUI::newDelegate(this, &SettingsWindow::onRefractionButtonClicked); mWaterTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWaterTextureSizeChanged); mWaterReflectionDetail->eventComboChangePosition @@ -377,6 +382,10 @@ namespace MWGui const int waterRainRippleDetail = Settings::water().mRainRippleDetail; mWaterRainRippleDetail->setIndexSelected(waterRainRippleDetail); + const bool waterRefraction = Settings::water().mRefraction; + mSunlightScatteringButton->setEnabled(waterRefraction); + mWobblyShoresButton->setEnabled(waterRefraction); + updateMaxLightsComboBox(mMaxLights); const Settings::WindowMode windowMode = Settings::video().mWindowMode; @@ -504,6 +513,14 @@ namespace MWGui } } + void SettingsWindow::onRefractionButtonClicked(MyGUI::Widget* _sender) + { + const bool refractionEnabled = Settings::water().mRefraction; + + mSunlightScatteringButton->setEnabled(refractionEnabled); + mWobblyShoresButton->setEnabled(refractionEnabled); + } + void SettingsWindow::onWaterTextureSizeChanged(MyGUI::ComboBox* _sender, size_t pos) { int size = 0; diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 1f96f7de54..dc4e09f8ac 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -37,6 +37,9 @@ namespace MWGui MyGUI::Button* mWindowBorderButton; MyGUI::ComboBox* mTextureFilteringButton; + MyGUI::Button* mWaterRefractionButton; + MyGUI::Button* mSunlightScatteringButton; + MyGUI::Button* mWobblyShoresButton; MyGUI::ComboBox* mWaterTextureSize; MyGUI::ComboBox* mWaterReflectionDetail; MyGUI::ComboBox* mWaterRainRippleDetail; @@ -76,6 +79,7 @@ namespace MWGui void onResolutionCancel(); void highlightCurrentResolution(); + void onRefractionButtonClicked(MyGUI::Widget* _sender); void onWaterTextureSizeChanged(MyGUI::ComboBox* _sender, size_t pos); void onWaterReflectionDetailChanged(MyGUI::ComboBox* _sender, size_t pos); void onWaterRainRippleDetailChanged(MyGUI::ComboBox* _sender, size_t pos); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 2afaa06ad0..62266d6e2d 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -705,6 +705,8 @@ namespace MWRender defineMap["rain_ripple_detail"] = std::to_string(rippleDetail); defineMap["ripple_map_world_scale"] = std::to_string(RipplesSurface::sWorldScaleFactor); defineMap["ripple_map_size"] = std::to_string(RipplesSurface::sRTTSize) + ".0"; + defineMap["sunlightScattering"] = Settings::water().mSunlightScattering ? "1" : "0"; + defineMap["wobblyShores"] = Settings::water().mWobblyShores ? "1" : "0"; Stereo::shaderStereoDefines(defineMap); diff --git a/components/settings/categories/water.hpp b/components/settings/categories/water.hpp index 2e04114244..63adce4ee3 100644 --- a/components/settings/categories/water.hpp +++ b/components/settings/categories/water.hpp @@ -26,6 +26,8 @@ namespace Settings SettingValue mSmallFeatureCullingPixelSize{ mIndex, "Water", "small feature culling pixel size", makeMaxStrictSanitizerFloat(0) }; SettingValue mRefractionScale{ mIndex, "Water", "refraction scale", makeClampSanitizerFloat(0, 1) }; + SettingValue mSunlightScattering{ mIndex, "Water", "sunlight scattering" }; + SettingValue mWobblyShores{ mIndex, "Water", "wobbly shores" }; }; } diff --git a/docs/source/reference/modding/settings/water.rst b/docs/source/reference/modding/settings/water.rst index fe407071f2..b04b92de94 100644 --- a/docs/source/reference/modding/settings/water.rst +++ b/docs/source/reference/modding/settings/water.rst @@ -58,6 +58,34 @@ This setting has no effect if the shader setting is false. This setting can be toggled with the 'Refraction' button in the Water tab of the Video panel of the Options menu. +sunlight scattering +------------------- + +:Type: boolean +:Range: True/False +:Default: True + +This setting enables sunlight scattering. +This makes incident sunlight seemingly spread through water, simulating the optical property. + +This setting has no effect if refraction is turned off. + +This setting can be toggled with the 'Sunlight Scattering' button in the Water tab of the Video panel of the Options menu. + +wobbly shores +------------- + +:Type: boolean +:Range: True/False +:Default: True + +This setting makes shores wobbly. +The water surface will smoothly fade into the shoreline and wobble based on water normal-mapping, which avoids harsh transitions. + +This setting has no effect if refraction is turned off. + +This setting can be toggled with the 'Wobbly Shores' button in the Water tab of the Video panel of the Options menu. + reflection detail ----------------- diff --git a/files/data/l10n/OMWEngine/en.yaml b/files/data/l10n/OMWEngine/en.yaml index 55ebbf3e94..d14aaa78fa 100644 --- a/files/data/l10n/OMWEngine/en.yaml +++ b/files/data/l10n/OMWEngine/en.yaml @@ -154,6 +154,7 @@ SensitivityHigh: "High" SensitivityLow: "Low" SettingsWindow: "Options" Subtitles: "Subtitles" +SunlightScattering: "Sunlight Scattering" TestingExteriorCells: "Testing Exterior Cells" TestingInteriorCells: "Testing Interior Cells" TextureFiltering: "Texture Filtering" @@ -178,3 +179,4 @@ WindowModeFullscreen: "Fullscreen" WindowModeHint: "Hint: Windowed Fullscreen mode\nalways uses the native display resolution." WindowModeWindowed: "Windowed" WindowModeWindowedFullscreen: "Windowed Fullscreen" +WobblyShores: "Wobbly Shores" diff --git a/files/data/l10n/OMWEngine/ru.yaml b/files/data/l10n/OMWEngine/ru.yaml index 07fc376675..1edecbf8b0 100644 --- a/files/data/l10n/OMWEngine/ru.yaml +++ b/files/data/l10n/OMWEngine/ru.yaml @@ -154,6 +154,7 @@ SensitivityHigh: "Высокая" SensitivityLow: "Низкая" SettingsWindow: "Настройки" Subtitles: "Субтитры" +SunlightScattering: "Рассеяние солнечного света" TestingExteriorCells: "Проверка наружных ячеек" TestingInteriorCells: "Проверка ячеек-помещений" TextureFiltering: "Фильтрация текстур" @@ -178,3 +179,4 @@ WindowModeFullscreen: "Полный экран" WindowModeHint: "Подсказка: режим Оконный без полей\nвсегда использует родное разрешение экрана." WindowModeWindowed: "Оконный" WindowModeWindowedFullscreen: "Оконный без полей" +WobblyShores: "Колеблющиеся берега" diff --git a/files/data/mygui/openmw_settings_window.layout b/files/data/mygui/openmw_settings_window.layout index 9e2f707ef5..5a25a61936 100644 --- a/files/data/mygui/openmw_settings_window.layout +++ b/files/data/mygui/openmw_settings_window.layout @@ -457,7 +457,7 @@ - + @@ -467,6 +467,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 58f6c347f1..73331867a7 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -680,6 +680,12 @@ small feature culling pixel size = 20.0 # By what factor water downscales objects. Only works with water shader and refractions on. refraction scale = 1.0 +# Make incident sunlight spread through water. +sunlight scattering = true + +# Fade and wobble water plane edges to avoid harsh shoreline transitions. +wobbly shores = true + [Windows] # Location and sizes of windows as a fraction of the OpenMW window or diff --git a/files/shaders/compatibility/water.frag b/files/shaders/compatibility/water.frag index c971f92b99..2debf2fac0 100644 --- a/files/shaders/compatibility/water.frag +++ b/files/shaders/compatibility/water.frag @@ -41,12 +41,13 @@ const float BUMP_RAIN = 2.5; const float REFL_BUMP = 0.10; // reflection distortion amount const float REFR_BUMP = 0.07; // refraction distortion amount +#if @sunlightScattering const float SCATTER_AMOUNT = 0.3; // amount of sunlight scattering const vec3 SCATTER_COLOUR = vec3(0.0,1.0,0.95); // colour of sunlight scattering +const vec3 SUN_EXT = vec3(0.45, 0.55, 0.68); // sunlight extinction +#endif -const vec3 SUN_EXT = vec3(0.45, 0.55, 0.68); //sunlight extinction const float SUN_SPEC_FADING_THRESHOLD = 0.15; // visibility at which sun specularity starts to fade - const float SPEC_HARDNESS = 256.0; // specular highlights hardness const float BUMP_SUPPRESS_DEPTH = 300.0; // at what water depth bumpmap will be suppressed for reflections and refractions (prevents artifacts at shores) @@ -57,7 +58,9 @@ const float WIND_SPEED = 0.2f; const vec3 WATER_COLOR = vec3(0.090195, 0.115685, 0.12745); +#if @wobblyShores const float WOBBLY_SHORE_FADE_DISTANCE = 6200.0; // fade out wobbly shores to mask precision errors, the effect is almost impossible to see at a distance +#endif // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - @@ -213,7 +216,7 @@ void main(void) refraction = mix(refraction, waterColor, clamp(factor, 0.0, 1.0)); } - // sunlight scattering +#if @sunlightScattering // normal for sunlight scattering vec3 lNormal = (normal0 * bigWaves.x * 0.5 + normal1 * bigWaves.y * 0.5 + normal2 * midWaves.x * 0.2 + normal3 * midWaves.y * 0.2 + normal4 * smallWaves.x * 0.1 + normal5 * smallWaves.y * 0.1 + rippleAdd); @@ -222,9 +225,13 @@ void main(void) vec3 scatterColour = mix(SCATTER_COLOUR*vec3(1.0,0.4,0.0), SCATTER_COLOUR, clamp(1.0-exp(-sunHeight*SUN_EXT), 0.0, 1.0)); vec3 lR = reflect(lVec, lNormal); float lightScatter = clamp(dot(lVec,lNormal)*0.7+0.3, 0.0, 1.0) * clamp(dot(lR, vVec)*2.0-1.2, 0.0, 1.0) * SCATTER_AMOUNT * sunFade * sunSpec.a * clamp(1.0-exp(-sunHeight), 0.0, 1.0); - gl_FragData[0].xyz = mix(mix(refraction, scatterColour, lightScatter), reflection, fresnel) + specular * sunSpec.rgb * sunSpec.a + rainSpecular; + refraction = mix(refraction, scatterColour, lightScatter); +#endif + + gl_FragData[0].xyz = mix(refraction, reflection, fresnel) + specular * sunSpec.rgb * sunSpec.a + rainSpecular; gl_FragData[0].w = 1.0; +#if @wobblyShores // wobbly water: hard-fade into refraction texture at extremely low depth, with a wobble based on normal mapping vec3 normalShoreRippleRain = texture2D(normalMap,normalCoords(UV, 2.0, 2.7, -1.0*waterTimer, 0.05, 0.1, normal3)).rgb - 0.5 + texture2D(normalMap,normalCoords(UV, 2.0, 2.7, waterTimer, 0.04, -0.13, normal4)).rgb - 0.5; @@ -234,6 +241,8 @@ void main(void) shoreOffset *= fuzzFactor; shoreOffset = clamp(mix(shoreOffset, 1.0, clamp(linearDepth / WOBBLY_SHORE_FADE_DISTANCE, 0.0, 1.0)), 0.0, 1.0); gl_FragData[0].xyz = mix(rawRefraction, gl_FragData[0].xyz, shoreOffset); +#endif + #else gl_FragData[0].xyz = mix(reflection, waterColor, (1.0-fresnel)*0.5) + specular * sunSpec.rgb * sunSpec.a + rainSpecular; gl_FragData[0].w = clamp(fresnel*6.0 + specular * sunSpec.a, 0.0, 1.0); //clamp(fresnel*2.0 + specular * gl_LightSource[0].specular.a, 0.0, 1.0);