1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 21:19:55 +00:00

Add more settings to water reflections in exteriors (feature #4859)

This commit is contained in:
Andrei Kortunov 2019-02-21 20:14:18 +04:00
parent 14d342558b
commit 00ab552184
14 changed files with 88 additions and 37 deletions

View file

@ -46,6 +46,7 @@
Feature #4730: Native animated containers support Feature #4730: Native animated containers support
Feature #4812: Support NiSwitchNode Feature #4812: Support NiSwitchNode
Feature #4836: Daytime node switch Feature #4836: Daytime node switch
Feature #4859: Make water reflections more configurable
Feature #4887: Add openmw command option to set initial random seed Feature #4887: Add openmw command option to set initial random seed
Feature #4890: Make Distant Terrain configurable Feature #4890: Make Distant Terrain configurable
Task #4686: Upgrade media decoder to a more current FFmpeg API Task #4686: Upgrade media decoder to a more current FFmpeg API

View file

@ -2,6 +2,7 @@
#include <components/esm/loadacti.hpp> #include <components/esm/loadacti.hpp>
#include <components/misc/rng.hpp> #include <components/misc/rng.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
@ -18,6 +19,7 @@
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
#include "../mwrender/vismask.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -29,8 +31,10 @@ namespace MWClass
void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
{ {
if (!model.empty()) { if (!model.empty())
{
renderingInterface.getObjects().insertModel(ptr, model, true); renderingInterface.getObjects().insertModel(ptr, model, true);
ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
} }
} }

View file

@ -2,6 +2,7 @@
#include <components/esm/loaddoor.hpp> #include <components/esm/loaddoor.hpp>
#include <components/esm/doorstate.hpp> #include <components/esm/doorstate.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -24,6 +25,7 @@
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
#include "../mwrender/animation.hpp" #include "../mwrender/animation.hpp"
#include "../mwrender/vismask.hpp"
#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/actorutil.hpp"
@ -53,8 +55,10 @@ namespace MWClass
void Door::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const void Door::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
{ {
if (!model.empty()) { if (!model.empty())
{
renderingInterface.getObjects().insertModel(ptr, model, true); renderingInterface.getObjects().insertModel(ptr, model, true);
ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
} }
} }

View file

@ -1,6 +1,7 @@
#include "static.hpp" #include "static.hpp"
#include <components/esm/loadstat.hpp> #include <components/esm/loadstat.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwphysics/physicssystem.hpp" #include "../mwphysics/physicssystem.hpp"
@ -8,14 +9,17 @@
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
#include "../mwrender/vismask.hpp"
namespace MWClass namespace MWClass
{ {
void Static::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const void Static::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
{ {
if (!model.empty()) { if (!model.empty())
{
renderingInterface.getObjects().insertModel(ptr, model); renderingInterface.getObjects().insertModel(ptr, model);
ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
} }
} }

View file

@ -193,6 +193,7 @@ namespace MWGui
getWidget(mKeyboardSwitch, "KeyboardButton"); getWidget(mKeyboardSwitch, "KeyboardButton");
getWidget(mControllerSwitch, "ControllerButton"); getWidget(mControllerSwitch, "ControllerButton");
getWidget(mWaterTextureSize, "WaterTextureSize"); getWidget(mWaterTextureSize, "WaterTextureSize");
getWidget(mWaterReflectionDetail, "WaterReflectionDetail");
#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
@ -216,6 +217,7 @@ namespace MWGui
mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected);
mWaterTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWaterTextureSizeChanged); mWaterTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWaterTextureSizeChanged);
mWaterReflectionDetail->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onWaterReflectionDetailChanged);
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);
@ -249,7 +251,7 @@ namespace MWGui
std::string tmip = Settings::Manager::getString("texture mipmap", "General"); std::string tmip = Settings::Manager::getString("texture mipmap", "General");
mTextureFilteringButton->setCaption(textureMipmappingToStr(tmip)); mTextureFilteringButton->setCaption(textureMipmappingToStr(tmip));
int waterTextureSize = Settings::Manager::getInt ("rtt size", "Water"); int waterTextureSize = Settings::Manager::getInt("rtt size", "Water");
if (waterTextureSize >= 512) if (waterTextureSize >= 512)
mWaterTextureSize->setIndexSelected(0); mWaterTextureSize->setIndexSelected(0);
if (waterTextureSize >= 1024) if (waterTextureSize >= 1024)
@ -257,6 +259,10 @@ namespace MWGui
if (waterTextureSize >= 2048) if (waterTextureSize >= 2048)
mWaterTextureSize->setIndexSelected(2); mWaterTextureSize->setIndexSelected(2);
int waterReflectionDetail = Settings::Manager::getInt("reflection detail", "Water");
waterReflectionDetail = std::min(3, std::max(0, waterReflectionDetail));
mWaterReflectionDetail->setIndexSelected(waterReflectionDetail);
mWindowBorderButton->setEnabled(!Settings::Manager::getBool("fullscreen", "Video")); mWindowBorderButton->setEnabled(!Settings::Manager::getBool("fullscreen", "Video"));
mKeyboardSwitch->setStateSelected(true); mKeyboardSwitch->setStateSelected(true);
@ -336,6 +342,13 @@ namespace MWGui
apply(); apply();
} }
void SettingsWindow::onWaterReflectionDetailChanged(MyGUI::ComboBox* _sender, size_t pos)
{
unsigned int level = std::min((unsigned int)3, (unsigned int)pos);
Settings::Manager::setInt("reflection detail", "Water", level);
apply();
}
void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender) void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender)
{ {
std::string on = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOn", "On"); std::string on = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOn", "On");

View file

@ -33,6 +33,7 @@ namespace MWGui
MyGUI::Widget* mAnisotropyBox; MyGUI::Widget* mAnisotropyBox;
MyGUI::ComboBox* mWaterTextureSize; MyGUI::ComboBox* mWaterTextureSize;
MyGUI::ComboBox* mWaterReflectionDetail;
// controls // controls
MyGUI::ScrollView* mControlsBox; MyGUI::ScrollView* mControlsBox;
@ -52,6 +53,7 @@ namespace MWGui
void highlightCurrentResolution(); void highlightCurrentResolution();
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 onRebindAction(MyGUI::Widget* _sender); void onRebindAction(MyGUI::Widget* _sender);
void onInputTabMouseWheel(MyGUI::Widget* _sender, int _rel); void onInputTabMouseWheel(MyGUI::Widget* _sender, int _rel);

View file

@ -178,7 +178,7 @@ osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, f
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
camera->setRenderOrder(osg::Camera::PRE_RENDER); camera->setRenderOrder(osg::Camera::PRE_RENDER);
camera->setCullMask(Mask_Scene | Mask_SimpleWater | Mask_Terrain | Mask_Object); camera->setCullMask(Mask_Scene | Mask_SimpleWater | Mask_Terrain | Mask_Object | Mask_Static);
camera->setNodeMask(Mask_RenderToTexture); camera->setNodeMask(Mask_RenderToTexture);
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet; osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
@ -380,7 +380,7 @@ void LocalMap::requestExteriorMap(const MWWorld::CellStore* cell)
void LocalMap::requestInteriorMap(const MWWorld::CellStore* cell) void LocalMap::requestInteriorMap(const MWWorld::CellStore* cell)
{ {
osg::ComputeBoundsVisitor computeBoundsVisitor; osg::ComputeBoundsVisitor computeBoundsVisitor;
computeBoundsVisitor.setTraversalMask(Mask_Scene | Mask_Terrain | Mask_Object); computeBoundsVisitor.setTraversalMask(Mask_Scene | Mask_Terrain | Mask_Object | Mask_Static);
mSceneRoot->accept(computeBoundsVisitor); mSceneRoot->accept(computeBoundsVisitor);
osg::BoundingBox bounds = computeBoundsVisitor.getBoundingBox(); osg::BoundingBox bounds = computeBoundsVisitor.getBoundingBox();

View file

@ -243,7 +243,7 @@ namespace MWRender
int indoorShadowCastingTraversalMask = shadowCastingTraversalMask; int indoorShadowCastingTraversalMask = shadowCastingTraversalMask;
if (Settings::Manager::getBool("object shadows", "Shadows")) if (Settings::Manager::getBool("object shadows", "Shadows"))
shadowCastingTraversalMask |= Mask_Object; shadowCastingTraversalMask |= (Mask_Object|Mask_Static);
mShadowManager.reset(new SceneUtil::ShadowManager(sceneRoot, mRootNode, shadowCastingTraversalMask, indoorShadowCastingTraversalMask, mResourceSystem->getSceneManager()->getShaderManager())); mShadowManager.reset(new SceneUtil::ShadowManager(sceneRoot, mRootNode, shadowCastingTraversalMask, indoorShadowCastingTraversalMask, mResourceSystem->getSceneManager()->getShaderManager()));

View file

@ -34,25 +34,26 @@ namespace MWRender
Mask_Terrain = (1<<8), Mask_Terrain = (1<<8),
Mask_FirstPerson = (1<<9), Mask_FirstPerson = (1<<9),
Mask_Object = (1<<10), Mask_Object = (1<<10),
Mask_Static = (1<<11),
// child of Sky // child of Sky
Mask_Sun = (1<<11), Mask_Sun = (1<<12),
Mask_WeatherParticles = (1<<12), Mask_WeatherParticles = (1<<13),
// top level masks // top level masks
Mask_Scene = (1<<13), Mask_Scene = (1<<14),
Mask_GUI = (1<<14), Mask_GUI = (1<<15),
// Set on a ParticleSystem Drawable // Set on a ParticleSystem Drawable
Mask_ParticleSystem = (1<<15), Mask_ParticleSystem = (1<<16),
// Set on cameras within the main scene graph // Set on cameras within the main scene graph
Mask_RenderToTexture = (1<<16), Mask_RenderToTexture = (1<<17),
Mask_PreCompile = (1<<17), Mask_PreCompile = (1<<18),
// Set on a camera's cull mask to enable the LightManager // Set on a camera's cull mask to enable the LightManager
Mask_Lighting = (1<<18) Mask_Lighting = (1<<19)
}; };
} }

View file

@ -225,7 +225,7 @@ public:
setSmallFeatureCullingPixelSize(Settings::Manager::getInt("small feature culling pixel size", "Water")); setSmallFeatureCullingPixelSize(Settings::Manager::getInt("small feature culling pixel size", "Water"));
setName("RefractionCamera"); setName("RefractionCamera");
setCullMask(Mask_Effect|Mask_Scene|Mask_Object|Mask_Terrain|Mask_Actor|Mask_ParticleSystem|Mask_Sky|Mask_Sun|Mask_Player|Mask_Lighting); setCullMask(Mask_Effect|Mask_Scene|Mask_Object|Mask_Static|Mask_Terrain|Mask_Actor|Mask_ParticleSystem|Mask_Sky|Mask_Sun|Mask_Player|Mask_Lighting);
setNodeMask(Mask_RenderToTexture); setNodeMask(Mask_RenderToTexture);
setViewport(0, 0, rttSize, rttSize); setViewport(0, 0, rttSize, rttSize);
@ -307,7 +307,7 @@ private:
class Reflection : public osg::Camera class Reflection : public osg::Camera
{ {
public: public:
Reflection() Reflection(bool isInterior)
{ {
setRenderOrder(osg::Camera::PRE_RENDER); setRenderOrder(osg::Camera::PRE_RENDER);
setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -316,9 +316,13 @@ public:
setSmallFeatureCullingPixelSize(Settings::Manager::getInt("small feature culling pixel size", "Water")); setSmallFeatureCullingPixelSize(Settings::Manager::getInt("small feature culling pixel size", "Water"));
setName("ReflectionCamera"); setName("ReflectionCamera");
bool reflectActors = Settings::Manager::getBool("reflect actors", "Water"); unsigned int reflectionDetail = Settings::Manager::getInt("reflection detail", "Water");
reflectionDetail = std::max((unsigned int)isInterior, reflectionDetail);
setCullMask(Mask_Effect|Mask_Scene|Mask_Object|Mask_Terrain|Mask_ParticleSystem|Mask_Sky|Mask_Player|Mask_Lighting|(reflectActors ? Mask_Actor : 0)); unsigned int extraMask = 0;
if(reflectionDetail >= 1) extraMask |= Mask_Static;
if(reflectionDetail >= 2) extraMask |= Mask_Effect|Mask_ParticleSystem|Mask_Object;
if(reflectionDetail >= 3) extraMask |= Mask_Actor;
setCullMask(Mask_Scene|Mask_Terrain|Mask_Sky|Mask_Player|Mask_Lighting|extraMask);
setNodeMask(Mask_RenderToTexture); setNodeMask(Mask_RenderToTexture);
unsigned int rttSize = Settings::Manager::getInt("rtt size", "Water"); unsigned int rttSize = Settings::Manager::getInt("rtt size", "Water");
@ -405,6 +409,7 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
, mEnabled(true) , mEnabled(true)
, mToggled(true) , mToggled(true)
, mTop(0) , mTop(0)
, mInterior(false)
{ {
mSimulation.reset(new RippleSimulation(parent, resourceSystem, fallback)); mSimulation.reset(new RippleSimulation(parent, resourceSystem, fallback));
@ -457,7 +462,7 @@ void Water::updateWaterMaterial()
if (Settings::Manager::getBool("shader", "Water")) if (Settings::Manager::getBool("shader", "Water"))
{ {
mReflection = new Reflection; mReflection = new Reflection(mInterior);
mReflection->setWaterLevel(mTop); mReflection->setWaterLevel(mTop);
mReflection->setScene(mSceneRoot); mReflection->setScene(mSceneRoot);
mParent->addChild(mReflection); mParent->addChild(mReflection);
@ -630,10 +635,20 @@ void Water::setEnabled(bool enabled)
void Water::changeCell(const MWWorld::CellStore* store) void Water::changeCell(const MWWorld::CellStore* store)
{ {
if (store->getCell()->isExterior()) bool isInterior = !store->getCell()->isExterior();
bool wasInterior = mInterior;
if (!isInterior)
{
mWaterNode->setPosition(getSceneNodeCoordinates(store->getCell()->mData.mX, store->getCell()->mData.mY)); mWaterNode->setPosition(getSceneNodeCoordinates(store->getCell()->mData.mX, store->getCell()->mData.mY));
mInterior = false;
}
else else
{
mWaterNode->setPosition(osg::Vec3f(0,0,mTop)); mWaterNode->setPosition(osg::Vec3f(0,0,mTop));
mInterior = true;
}
if(mInterior != wasInterior)
updateWaterMaterial();
// create a new StateSet to prevent threading issues // create a new StateSet to prevent threading issues
osg::ref_ptr<osg::StateSet> nodeStateSet (new osg::StateSet); osg::ref_ptr<osg::StateSet> nodeStateSet (new osg::StateSet);

View file

@ -70,6 +70,7 @@ namespace MWRender
bool mEnabled; bool mEnabled;
bool mToggled; bool mToggled;
float mTop; float mTop;
bool mInterior;
osg::Vec3f getSceneNodeCoordinates(int gridX, int gridY); osg::Vec3f getSceneNodeCoordinates(int gridX, int gridY);
void updateVisible(); void updateVisible();

View file

@ -58,17 +58,22 @@ 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. This setting can be toggled with the 'Refraction' button in the Water tab of the Video panel of the Options menu.
reflect actors reflection detail
-------------- --------------
:Type: boolean :Type: integer
:Range: True/False :Range: 0, 1, 2, 3
:Default: False :Default: 1
This setting controls whether or not NPCs and creatures are drawn in water reflections. Controls what kinds of things are rendered in water reflections.
Setting this to true will enable actors in reflections and increase realism with a likely decrease in performance.
This setting can be toggled with the 'Reflect actors' button in the Water tab of the Video panel of the Options menu. 0: only terrain and the sky are reflected (acts like level 1 in interiors)
1: statics, activators, and doors are also reflected
2: items, containers, and particles are also reflected
3: actors are also reflected
The player is always reflected in third-person mode.
This setting can be changed ingame with the "Reflection shader detail" dropdown under the Water tab of the Video panel in the Options menu.
small feature culling pixel size small feature culling pixel size
-------------------------------- --------------------------------

View file

@ -428,13 +428,14 @@
</Widget> </Widget>
</Widget> </Widget>
<Widget type="HBox" skin="" position="4 56 350 24"> <Widget type="HBox" skin="" position="4 56 350 24">
<Widget type="AutoSizedButton" skin="MW_Button" position="0 0 24 24" align="Left Top"> <Widget type="ComboBox" skin="MW_ComboBox" position="0 0 115 24" align="Left Top" name="WaterReflectionDetail">
<UserString key="SettingCategory" value="Water"/> <Property key="AddItem" value="Terrain"/>
<UserString key="SettingName" value="reflect actors"/> <Property key="AddItem" value="World"/>
<UserString key="SettingType" value="CheckButton"/> <Property key="AddItem" value="Objects"/>
<Property key="AddItem" value="Everything"/>
</Widget> </Widget>
<Widget type="AutoSizedTextBox" skin="SandText" position="28 4 79 16" align="Left Top"> <Widget type="AutoSizedTextBox" skin="SandText" position="64 4 90 16" align="Left Top">
<Property key="Caption" value="Reflect actors"/> <Property key="Caption" value="Reflection shader detail"/>
</Widget> </Widget>
</Widget> </Widget>
</Widget> </Widget>

View file

@ -462,8 +462,8 @@ rtt size = 512
# Enable refraction which affects visibility through water plane. # Enable refraction which affects visibility through water plane.
refraction = false refraction = false
# Draw NPCs and creatures on water reflections. # Draw objects on water reflections.
reflect actors = false reflection detail = 1
# Overrides the value in '[Camera] small feature culling pixel size' specifically for water reflection/refraction textures. # Overrides the value in '[Camera] small feature culling pixel size' specifically for water reflection/refraction textures.
small feature culling pixel size = 20.0 small feature culling pixel size = 20.0