diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 82c8b554f..67ccf9d53 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -64,9 +64,17 @@ namespace MWGui getWidget(mTextureFilteringButton, "TextureFilteringButton"); getWidget(mAnisotropyLabel, "AnisotropyLabel"); getWidget(mAnisotropyBox, "AnisotropyBox"); + getWidget(mWaterShaderButton, "WaterShaderButton"); + getWidget(mReflectObjectsButton, "ReflectObjectsButton"); + getWidget(mReflectActorsButton, "ReflectActorsButton"); + getWidget(mReflectTerrainButton, "ReflectTerrainButton"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mWaterShaderButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mReflectObjectsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mReflectTerrainButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mReflectActorsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mTextureFilteringButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringToggled); mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); @@ -127,6 +135,19 @@ namespace MWGui mFootstepsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("footsteps volume", "Sound") * (mFootstepsVolumeSlider->getScrollRange()-1)); mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1)); + mWaterShaderButton->setCaptionWithReplacing(Settings::Manager::getBool("shader", "Water") ? "#{sOn}" : "#{sOff}"); + mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect objects", "Water") ? "#{sOn}" : "#{sOff}"); + mReflectActorsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect actors", "Water") ? "#{sOn}" : "#{sOff}"); + mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "Water") ? "#{sOn}" : "#{sOff}"); + + if (!MWRender::RenderingManager::waterShaderSupported()) + { + mWaterShaderButton->setEnabled(false); + mReflectObjectsButton->setEnabled(false); + mReflectActorsButton->setEnabled(false); + mReflectTerrainButton->setEnabled(false); + } + mFullscreenButton->setCaptionWithReplacing(Settings::Manager::getBool("fullscreen", "Video") ? "#{sOn}" : "#{sOff}"); mVSyncButton->setCaptionWithReplacing(Settings::Manager::getBool("vsync", "Video") ? "#{sOn}": "#{sOff}"); mFPSButton->setCaptionWithReplacing(fpsLevelToStr(Settings::Manager::getInt("fps", "HUD"))); @@ -228,6 +249,23 @@ namespace MWGui MWBase::Environment::get().getWindowManager()-> messageBox("VSync will be applied after a restart", std::vector()); } + else + { + if (_sender == mWaterShaderButton) + Settings::Manager::setBool("shader", "Water", newState); + else if (_sender == mReflectObjectsButton) + { + Settings::Manager::setBool("reflect misc", "Water", newState); + Settings::Manager::setBool("reflect statics", "Water", newState); + Settings::Manager::setBool("reflect statics small", "Water", newState); + } + else if (_sender == mReflectActorsButton) + Settings::Manager::setBool("reflect actors", "Water", newState); + else if (_sender == mReflectTerrainButton) + Settings::Manager::setBool("reflect terrain", "Water", newState); + + apply(); + } } void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 8924375d9..ce95edbd2 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -38,6 +38,10 @@ namespace MWGui MyGUI::Button* mTextureFilteringButton; MyGUI::TextBox* mAnisotropyLabel; MyGUI::Widget* mAnisotropyBox; + MyGUI::Button* mWaterShaderButton; + MyGUI::Button* mReflectObjectsButton; + MyGUI::Button* mReflectActorsButton; + MyGUI::Button* mReflectTerrainButton; // audio MyGUI::ScrollBar* mMasterVolumeSlider; diff --git a/apps/openmw/mwrender/compositors.cpp b/apps/openmw/mwrender/compositors.cpp index d786c263b..6f97269ab 100644 --- a/apps/openmw/mwrender/compositors.cpp +++ b/apps/openmw/mwrender/compositors.cpp @@ -62,3 +62,10 @@ void Compositors::setCompositorEnabled (const std::string& name, const bool enab mCompositors[name].first = enabled; Ogre::CompositorManager::getSingleton().setCompositorEnabled (mViewport, name, enabled && mEnabled); } + +void Compositors::removeAll() +{ + Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport); + + mCompositors.clear(); +} diff --git a/apps/openmw/mwrender/compositors.hpp b/apps/openmw/mwrender/compositors.hpp index f249ece42..bbd838b8e 100644 --- a/apps/openmw/mwrender/compositors.hpp +++ b/apps/openmw/mwrender/compositors.hpp @@ -44,6 +44,8 @@ namespace MWRender */ void addCompositor (const std::string& name, const int priority); + void removeAll (); + protected: /// maps compositor name to its "enabled" state CompositorMap mCompositors; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 89f42a5f1..a6f10fcd2 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -67,25 +67,13 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const // disable unsupported effects const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); - if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects")) + if (!waterShaderSupported()) Settings::Manager::setBool("shader", "Water", false); if ( !(caps->isShaderProfileSupported("fp40") || caps->isShaderProfileSupported("ps_4_0")) || !Settings::Manager::getBool("shaders", "Objects")) Settings::Manager::setBool("enabled", "Shadows", false); - // note that the order is important here - if (useMRT()) - { - mCompositors->addCompositor("gbuffer", 0); - mCompositors->setCompositorEnabled("gbuffer", true); - mCompositors->addCompositor("Underwater", 1); - mCompositors->addCompositor("gbufferFinalizer", 2); - mCompositors->setCompositorEnabled("gbufferFinalizer", true); - } - else - { - mCompositors->addCompositor("UnderwaterNoMRT", 0); - } + applyCompositors(); // Turn the entire scene (represented by the 'root' node) -90 // degrees around the x axis. This makes Z go upwards, and Y go into @@ -605,6 +593,11 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec MaterialManager::getSingleton().setDefaultTextureFiltering(tfo); MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 ); } + else if (it->second == "shader" && it->first == "Water") + { + applyCompositors(); + mShaderHelper->applyShaders(); + } } if (changeRes) @@ -618,6 +611,9 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec } mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y); } + + if (mWater) + mWater->processChangedSettings(settings); } void RenderingManager::setMenuTransparency(float val) @@ -649,4 +645,32 @@ void RenderingManager::windowClosed(Ogre::RenderWindow* rw) { } +bool RenderingManager::waterShaderSupported() +{ + const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); + if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects")) + return false; + return true; +} + +void RenderingManager::applyCompositors() +{ + mCompositors->removeAll(); + if (useMRT()) + { + mCompositors->addCompositor("gbuffer", 0); + mCompositors->setCompositorEnabled("gbuffer", true); + mCompositors->addCompositor("Underwater", 1); + mCompositors->addCompositor("gbufferFinalizer", 2); + mCompositors->setCompositorEnabled("gbufferFinalizer", true); + } + else + { + mCompositors->addCompositor("UnderwaterNoMRT", 0); + } + + if (mWater) + mWater->assignTextures(); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 562184c62..642c42930 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -165,6 +165,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList Ogre::Viewport* getViewport() { return mRendering.getViewport(); } + static bool waterShaderSupported(); + protected: virtual void windowResized(Ogre::RenderWindow* rw); virtual void windowClosed(Ogre::RenderWindow* rw); @@ -175,6 +177,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList void setMenuTransparency(float val); + void applyCompositors(); + bool mSunEnabled; SkyManager* mSkyManager; diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 981343e91..b4486a0ca 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -1,5 +1,5 @@ #include "water.hpp" -#include + #include "sky.hpp" #include "renderingmanager.hpp" #include "compositors.hpp" @@ -30,13 +30,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mWater->setRenderQueueGroup(RQG_Water); mWater->setCastShadows(false); - mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water") - + RV_Statics * Settings::Manager::getBool("reflect statics", "Water") - + RV_StaticsSmall * Settings::Manager::getBool("reflect small statics", "Water") - + RV_Actors * Settings::Manager::getBool("reflect actors", "Water") - + RV_Misc * Settings::Manager::getBool("reflect misc", "Water") - + RV_Sky; - mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode(); mWaterNode->setPosition(0, mTop, 0); @@ -48,30 +41,9 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel } mWaterNode->attachObject(mWater); - // Create rendertarget for reflection - int rttsize = Settings::Manager::getInt("rtt size", "Water"); + applyRTT(); + applyVisibilityMask(); - TexturePtr tex; - if (Settings::Manager::getBool("shader", "Water")) - { - tex = TextureManager::getSingleton().createManual("WaterReflection", - ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_FLOAT16_RGBA, TU_RENDERTARGET); - - RenderTarget* rtt = tex->getBuffer()->getRenderTarget(); - Viewport* vp = rtt->addViewport(mReflectionCamera); - vp->setOverlaysEnabled(false); - vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f)); - vp->setShadowsEnabled(false); - vp->setVisibilityMask( mVisibilityFlags ); - // use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain) - //vp->setMaterialScheme("Fallback"); - rtt->addListener(this); - rtt->setActive(true); - - mReflectionTarget = rtt; - } - - mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT"; createMaterial(); mWater->setMaterial(mMaterial); @@ -251,7 +223,15 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt) void Water::createMaterial() { - mMaterial = MaterialManager::getSingleton().getByName("Water"); + if (mReflectionTarget == 0) + { + mMaterial = MaterialManager::getSingleton().getByName("Water_Fallback"); + } + else + { + mMaterial = MaterialManager::getSingleton().getByName("Water"); + mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(mReflectionTexture); + } // these have to be set in code std::string textureNames[32]; @@ -259,11 +239,13 @@ void Water::createMaterial() { textureNames[i] = "textures\\water\\water" + StringConverter::toString(i, 2, '0') + ".dds"; } - mMaterial->getTechnique(1)->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2); - - // use technique without shaders if reflection is disabled + Ogre::Technique* tech; if (mReflectionTarget == 0) - mMaterial->removeTechnique(0); + tech = mMaterial->getTechnique(0); + else + tech = mMaterial->getTechnique(1); + + tech->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2); } void Water::assignTextures() @@ -320,4 +302,84 @@ void Water::update() { } +void Water::applyRTT() +{ + if (mReflectionTarget) + { + TextureManager::getSingleton().remove("WaterReflection"); + mReflectionTarget = 0; + } + + // Create rendertarget for reflection + int rttsize = Settings::Manager::getInt("rtt size", "Water"); + + if (Settings::Manager::getBool("shader", "Water")) + { + mReflectionTexture = TextureManager::getSingleton().createManual("WaterReflection", + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_FLOAT16_RGBA, TU_RENDERTARGET); + + RenderTarget* rtt = mReflectionTexture->getBuffer()->getRenderTarget(); + Viewport* vp = rtt->addViewport(mReflectionCamera); + vp->setOverlaysEnabled(false); + vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f)); + vp->setShadowsEnabled(false); + // use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain) + //vp->setMaterialScheme("Fallback"); + rtt->addListener(this); + rtt->setActive(true); + + mReflectionTarget = rtt; + } + + mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT"; +} + +void Water::applyVisibilityMask() +{ + mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water") + + RV_Statics * Settings::Manager::getBool("reflect statics", "Water") + + RV_StaticsSmall * Settings::Manager::getBool("reflect small statics", "Water") + + RV_Actors * Settings::Manager::getBool("reflect actors", "Water") + + RV_Misc * Settings::Manager::getBool("reflect misc", "Water") + + RV_Sky; + + if (mReflectionTarget) + { + mReflectionTexture->getBuffer()->getRenderTarget()->getViewport(0)->setVisibilityMask(mVisibilityFlags); + } +} + +void Water::processChangedSettings(const Settings::CategorySettingVector& settings) +{ + bool applyRT = false; + bool applyVisMask = false; + for (Settings::CategorySettingVector::const_iterator it=settings.begin(); + it != settings.end(); ++it) + { + if ( it->first == "Water" && ( + it->second == "shader" + || it->second == "rtt size")) + applyRT = true; + + if ( it->first == "Water" && ( + it->second == "reflect actors" + || it->second == "reflect terrain" + || it->second == "reflect misc" + || it->second == "reflect small statics" + || it->second == "reflect statics")) + applyVisMask = true; + } + + if(applyRT) + { + applyRTT(); + applyVisibilityMask(); + createMaterial(); + mWater->setMaterial(mMaterial); + assignTextures(); + } + if (applyVisMask) + applyVisibilityMask(); +} + } // namespace diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index edd217e84..4d617ea47 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -3,9 +3,11 @@ #include #include +#include #include "renderconst.hpp" + namespace MWRender { class SkyManager; @@ -38,6 +40,9 @@ namespace MWRender { void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); void renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation); + void applyRTT(); + void applyVisibilityMask(); + void updateVisible(); RenderingManager* mRendering; @@ -50,6 +55,7 @@ namespace MWRender { Ogre::Camera* mReflectionCamera; + Ogre::TexturePtr mReflectionTexture; Ogre::RenderTarget* mReflectionTarget; bool mUnderwaterEffect; @@ -68,6 +74,8 @@ namespace MWRender { void setViewportBackground(const Ogre::ColourValue& bg); + void processChangedSettings(const Settings::CategorySettingVector& settings); + void checkUnderwater(float y); void changeCell(const ESM::Cell* cell); void setHeight(const float height); diff --git a/files/mygui/openmw_settings_window_layout.xml b/files/mygui/openmw_settings_window_layout.xml index 107e883c4..7c508b1e9 100644 --- a/files/mygui/openmw_settings_window_layout.xml +++ b/files/mygui/openmw_settings_window_layout.xml @@ -153,6 +153,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/water/water.material b/files/water/water.material index 8b4ff96f5..a2a6b3e2d 100644 --- a/files/water/water.material +++ b/files/water/water.material @@ -90,6 +90,31 @@ material Water } } } + + technique + { + scheme Fallback + pass + { + cull_hardware none + scene_blend alpha_blend + depth_write off + diffuse 0 0 0 1 + emissive 0.6 0.7 1.0 + ambient 0 0 0 + texture_unit + { + // texture names set via code + scale 0.1 0.1 + alpha_op_ex source1 src_manual src_current 0.7 + } + } + } + +} + +material Water_Fallback +{ technique { scheme Fallback