diff --git a/CMakeLists.txt b/CMakeLists.txt index aee073d3ef..614a840c4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -633,7 +633,7 @@ if (APPLE) include(CPack) endif (APPLE) -if (NOT WIN32 AND NOT DPKG_PROGRAM) +if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE) ## Non Debian based Linux building # paths set(BINDIR "${CMAKE_INSTALL_PREFIX}/usr/bin" CACHE PATH "Where to install binaries") @@ -664,4 +664,4 @@ if (NOT WIN32 AND NOT DPKG_PROGRAM) # Install resources INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" ) INSTALL(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${DATADIR}/resources" ) -endif(NOT WIN32 AND NOT DPKG_PROGRAM) +endif(NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index db6edf397d..d10ae99794 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -299,6 +299,7 @@ void OMW::Engine::go() mOgre->configure( mCfgMgr.getLogPath().string(), renderSystem, + Settings::Manager::getString("opengl rtt mode", "Video"), false); // This has to be added BEFORE MyGUI is initialized, as it needs diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index d1e206a957..cdfe4d2b68 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -122,6 +122,7 @@ namespace MWGui getWidget(mInvertYButton, "InvertYButton"); getWidget(mUISensitivitySlider, "UISensitivitySlider"); getWidget(mCameraSensitivitySlider, "CameraSensitivitySlider"); + getWidget(mGammaSlider, "GammaSlider"); mSubtitlesButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mCrosshairButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -143,6 +144,7 @@ namespace MWGui mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mGammaSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mShadowsEnabledButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mShadowsLargeDistance->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -200,6 +202,14 @@ namespace MWGui getWidget(fovText, "FovText"); fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int(Settings::Manager::getFloat("field of view", "General"))) + ")"); + float gammaVal = (Settings::Manager::getFloat("gamma", "Video")-0.1f)/(3.f-0.1f); + mGammaSlider->setScrollPosition(gammaVal * (mGammaSlider->getScrollRange()-1)); + MyGUI::TextBox* gammaText; + getWidget(gammaText, "GammaText"); + std::stringstream gamma; + gamma << std::setprecision (2) << Settings::Manager::getFloat("gamma", "Video"); + gammaText->setCaption("Gamma (" + gamma.str() + ")"); + float anisotropyVal = Settings::Manager::getInt("anisotropy", "General") / 16.0; mAnisotropySlider->setScrollPosition(anisotropyVal * (mAnisotropySlider->getScrollRange()-1)); std::string tf = Settings::Manager::getString("texture filtering", "General"); @@ -511,6 +521,15 @@ namespace MWGui fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int((1-val) * sFovMin + val * sFovMax)) + ")"); Settings::Manager::setFloat("field of view", "General", (1-val) * sFovMin + val * sFovMax); } + else if (scroller == mGammaSlider) + { + Settings::Manager::setFloat("gamma", "Video", (1-val) * 0.1f + val * 3.f); + MyGUI::TextBox* gammaText; + getWidget(gammaText, "GammaText"); + std::stringstream gamma; + gamma << std::setprecision (2) << Settings::Manager::getFloat("gamma", "Video"); + gammaText->setCaption("Gamma (" + gamma.str() + ")"); + } else if (scroller == mAnisotropySlider) { mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(int(val*16)) + ")"); diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index d1f35ed710..e878d0abea 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -40,6 +40,7 @@ namespace MWGui MyGUI::Button* mFPSButton; MyGUI::ScrollBar* mViewDistanceSlider; MyGUI::ScrollBar* mFOVSlider; + MyGUI::ScrollBar* mGammaSlider; MyGUI::ScrollBar* mAnisotropySlider; MyGUI::Button* mTextureFilteringButton; MyGUI::TextBox* mAnisotropyLabel; diff --git a/apps/openmw/mwgui/text_input.cpp b/apps/openmw/mwgui/text_input.cpp index 9d5ba98963..3dbe751659 100644 --- a/apps/openmw/mwgui/text_input.cpp +++ b/apps/openmw/mwgui/text_input.cpp @@ -47,10 +47,22 @@ void TextInputDialog::open() void TextInputDialog::onOkClicked(MyGUI::Widget* _sender) { - eventDone(this); + if (mTextEdit->getCaption() == "") + { + mWindowManager.messageBox ("#{sNotifyMessage37}", std::vector<std::string>()); + MyGUI::InputManager::getInstance ().setKeyFocusWidget (mTextEdit); + } + else + eventDone(this); } void TextInputDialog::onTextAccepted(MyGUI::Edit* _sender) { - eventDone(this); + if (mTextEdit->getCaption() == "") + { + mWindowManager.messageBox ("#{sNotifyMessage37}", std::vector<std::string>()); + MyGUI::InputManager::getInstance ().setKeyFocusWidget (mTextEdit); + } + else + eventDone(this); } diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 01c5d594a7..c8852bff52 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -72,6 +72,8 @@ namespace MWRender CharacterPreview::~CharacterPreview () { Ogre::TextureManager::getSingleton().remove(mName); + mSceneMgr->destroyCamera (mName); + delete mAnimation; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 3636436fc5..1b78844492 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -129,6 +129,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(0))); sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty<sh::Vector3>(new sh::Vector3(0.5, -0.8, 0.2))); sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty<sh::Vector2>(new sh::Vector2(1, 0.6))); + sh::Factory::getInstance ().setSharedParameter ("gammaCorrection", sh::makeProperty<sh::FloatValue>(new sh::FloatValue( + Settings::Manager::getFloat ("gamma", "Video")))); applyCompositors(); @@ -749,6 +751,11 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec sh::Factory::getInstance ().setShadersEnabled (Settings::Manager::getBool("shaders", "Objects")); mObjects.rebuildStaticGeometry (); } + else if (it->second == "gamma" && it->first == "Video") + { + sh::Factory::getInstance ().setSharedParameter ("gammaCorrection", sh::makeProperty<sh::FloatValue>(new sh::FloatValue( + Settings::Manager::getFloat ("gamma", "Video")))); + } else if (it->second == "shader mode" && it->first == "General") { sh::Language lang; diff --git a/files/materials/core.h b/files/materials/core.h index cba7167770..e9577bbf3c 100644 --- a/files/materials/core.h +++ b/files/materials/core.h @@ -1,3 +1,7 @@ +#define gammaCorrectRead(v) pow(v, float3(gammaCorrection,gammaCorrection,gammaCorrection)) +#define gammaCorrectOutput(v) pow(v, float3(1.f/gammaCorrection,1.f/gammaCorrection,1.f/gammaCorrection)) + + #if SH_HLSL == 1 || SH_CG == 1 #define shTexture2D sampler2D diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 8e5cbf76ef..45f33774db 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -112,6 +112,8 @@ shUniform(float, far) @shAutoConstant(far, far_clip_distance) #endif + shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection) + #if LIGHTING shInput(float3, normalPassthrough) shInput(float3, objSpacePositionPassthrough) @@ -173,7 +175,8 @@ SH_START_PROGRAM { shOutputColour(0) = shSample(diffuseMap, UV); - + shOutputColour(0).xyz = gammaCorrectRead(shOutputColour(0).xyz); + #if LIGHTING float3 normal = normalize(normalPassthrough); float3 lightDir; @@ -259,7 +262,7 @@ // regular fog only if fragment is above water if (worldPos.y > waterLevel) #endif - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, gammaCorrectRead(fogColour), fogValue); #endif // prevent negative colour output (for example with negative lights) @@ -274,12 +277,11 @@ float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); - float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; + float3 waterSunColour = gammaCorrectRead(float3(0.0,1.0,0.85)) *waterSunGradient * 0.5; float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0)); waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); - float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; - float3 waterext = float3(0.6, 0.9, 1.0);//water extinction + float3 watercolour = ( gammaCorrectRead(float3(0.0078, 0.5176, 0.700))+waterSunColour)*waterGradient*2.0; watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); watercolour = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3; @@ -292,6 +294,8 @@ shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater * waterEnabled); #endif + shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz); + #if MRT shOutputColour(1) = float4(depthPassthrough / far,1,1,1); #endif diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 7ef26d0359..9183595e34 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -137,6 +137,8 @@ shSampler2D(normalMap) // global normal map + shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection) + @shForeach(@shPropertyString(num_blendmaps)) shSampler2D(blendMap@shIterator) @@ -247,9 +249,9 @@ #if IS_FIRST_PASS == 1 && @shIterator == 0 // first layer of first pass doesn't need a blend map - albedo = shSample(diffuseMap0, UV * 10).rgb; + albedo = gammaCorrectRead(shSample(diffuseMap0, UV * 10).rgb); #else - albedo = shLerp(albedo, shSample(diffuseMap@shIterator, UV * 10).rgb, blendValues@shPropertyString(blendmap_component_@shIterator)); + albedo = shLerp(albedo, gammaCorrectRead(shSample(diffuseMap@shIterator, UV * 10).rgb), blendValues@shPropertyString(blendmap_component_@shIterator)); #endif @shEndForeach @@ -336,7 +338,7 @@ // regular fog only if fragment is above water if (worldPos.y > waterLevel) #endif - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, gammaCorrectRead(fogColour), fogValue); #endif // prevent negative colour output (for example with negative lights) @@ -351,12 +353,12 @@ float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); - float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; + float3 waterSunColour = gammaCorrectRead(float3(0.0,1.0,0.85))*waterSunGradient * 0.5; float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0)); waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); - float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; - float3 waterext = float3(0.6, 0.9, 1.0);//water extinction + float3 watercolour = (gammaCorrectRead(float3(0.0078, 0.5176, 0.700))+waterSunColour)*waterGradient*2.0; + float3 waterext = gammaCorrectRead(float3(0.6, 0.9, 1.0));//water extinction watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); watercolour = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3; @@ -369,6 +371,8 @@ shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater); #endif + shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz); + #if MRT shOutputColour(1) = float4(depth / far,1,1,1); diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 38d2786e51..2f9b5a67f1 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -157,7 +157,7 @@ <Widget type="TabItem" skin="" position="4 28 344 272"> <Property key="Caption" value=" Video "/> - <Widget type="ListBox" skin="MW_List" position="4 4 200 150" align="Left Top" name="ResolutionList"/> + <Widget type="ListBox" skin="MW_List" position="4 4 200 120" align="Left Top" name="ResolutionList"/> <Widget type="HBox" position="212 4 300 24"> @@ -174,20 +174,37 @@ </Widget> </Widget> - <Widget type="HBox" position="212 104 300 24"> + <Widget type="HBox" position="212 64 300 24"> <Widget type="AutoSizedButton" skin="MW_Button" align="Left Top" name="ShadersButton"/> <Widget type="AutoSizedTextBox" skin="SandText" align="Left Top"> <Property key="Caption" value="Shaders"/> </Widget> </Widget> - <Widget type="HBox" position="4 163 300 24"> + <Widget type="HBox" position="212 94 300 24"> <Widget type="AutoSizedButton" skin="MW_Button" align="Left Top" name="FPSButton"/> <Widget type="AutoSizedTextBox" skin="SandText" align="Left Top"> - <Property key="Caption" value="Show frames per second"/> + <Property key="Caption" value="FPS"/> </Widget> </Widget> + + <Widget type="TextBox" skin="NormalText" position="4 128 329 18" align="Left Top" name="GammaText"> + <Property key="Caption" value="Gamma"/> + </Widget> + <Widget type="ScrollBar" skin="MW_HSlider" position="4 152 329 18" align="Left Top" name="GammaSlider"> + <Property key="Range" value="1000000"/> + </Widget> + <Widget type="TextBox" skin="SandText" position="4 176 329 18" align="Left Top"> + <Property key="Caption" value="#{sDark_Gamma}"/> + <Property key="TextAlign" value="Left"/> + </Widget> + <Widget type="TextBox" skin="SandText" position="4 176 329 18" align="Left Top"> + <Property key="Caption" value="#{sLight_Gamma}"/> + <Property key="TextAlign" value="Right"/> + </Widget> + + <Widget type="TextBox" skin="NormalText" position="4 198 329 18" align="Left Top" name="FovText"> <Property key="Caption" value="Field of View"/> </Widget> diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 8fab98da24..1768b2f5ec 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -24,6 +24,12 @@ antialiasing = none vsync = false +# opengl render to texture mode, valid options: +# PBuffer, FBO, Copy +opengl rtt mode = FBO + +gamma = 2.2 + [GUI] # 1 is fully opaque menu transparency = 0.84 diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index ec68c37ab8..87ebe11397 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -145,6 +145,7 @@ float OgreRenderer::getFPS() void OgreRenderer::configure(const std::string &logPath, const std::string& renderSystem, + const std::string& rttMode, bool _logging) { // Set up logging first @@ -198,6 +199,9 @@ void OgreRenderer::configure(const std::string &logPath, if (rs == 0) throw std::runtime_error ("RenderSystem with name " + renderSystem + " not found, make sure the plugins are loaded"); mRoot->setRenderSystem(rs); + + if (rs->getName().find("OpenGL") != std::string::npos) + rs->setConfigOption ("RTT Preferred Mode", rttMode); } void OgreRenderer::createWindow(const std::string &title, const WindowSettings& settings) diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 95bcac3b87..a8788dfcaf 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -132,6 +132,7 @@ namespace OEngine void configure( const std::string &logPath, // Path to directory where to store log files const std::string &renderSystem, + const std::string &rttMode, bool _logging); // Enable or disable logging /// Create a window with the given title