diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 0c002a718..3473d0b29 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -208,6 +208,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) OMW::Engine::~Engine() { + mOgre->restoreWindowGammaRamp(); mEnvironment.cleanup(); delete mScriptContext; delete mOgre; @@ -382,6 +383,8 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) // Create sound system mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); + mOgre->setWindowGammaContrast(Settings::Manager::getFloat("gamma", "General"), Settings::Manager::getFloat("contrast", "General")); + if (!mSkipMenu) { std::string logo = mFallbackMap["Movies_Company_Logo"]; diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index ce2a20d8b..05664386b 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -182,6 +182,20 @@ namespace MWGui getWidget(mRefractionButton, "RefractionButton"); getWidget(mDifficultySlider, "DifficultySlider"); +#ifndef WIN32 + // hide gamma controls since it currently does not work under Linux + MyGUI::ScrollBar *gammaSlider; + getWidget(gammaSlider, "GammaSlider"); + gammaSlider->setVisible(false); + MyGUI::TextBox *textBox; + getWidget(textBox, "GammaText"); + textBox->setVisible(false); + getWidget(textBox, "GammaTextDark"); + textBox->setVisible(false); + getWidget(textBox, "GammaTextLight"); + textBox->setVisible(false); +#endif + mMainWidget->castType()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SettingsWindow::onWindowResize); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 33649ea7c..4a87104ad 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -757,6 +757,10 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec changeRes = true; else if (it->second == "field of view" && it->first == "General") mRendering.setFov(Settings::Manager::getFloat("field of view", "General")); + else if (it->second == "gamma" && it->first == "General") + { + mRendering.setWindowGammaContrast(Settings::Manager::getFloat("gamma", "General"), Settings::Manager::getFloat("contrast", "General")); + } else if ((it->second == "texture filtering" && it->first == "General") || (it->second == "anisotropy" && it->first == "General")) { diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index e2f46f2d1..4a993e140 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -1,8 +1,8 @@  - + - + @@ -214,7 +214,7 @@ - + @@ -292,6 +292,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -470,7 +491,7 @@ - + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 9f2a01354..39232c95c 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -48,6 +48,8 @@ werewolf overlay = true [General] # Camera field of view field of view = 55 +gamma = 1.00 +contrast = 1.00 # Texture filtering mode. valid values: # none diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index c2074a79d..0e37d2802 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -23,6 +23,11 @@ using namespace Ogre; using namespace OEngine::Render; +OgreRenderer::~OgreRenderer() +{ + cleanup(); + restoreWindowGammaRamp(); +} void OgreRenderer::cleanup() { @@ -140,6 +145,7 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& helper.setWindowIcon(settings.icon); mWindow = helper.getWindow(); + SDL_GetWindowGammaRamp(mSDLWindow, mOldSystemGammaRamp, &mOldSystemGammaRamp[256], &mOldSystemGammaRamp[512]); // create the semi-transparent black background texture used by the GUI. // has to be created in code with TU_DYNAMIC_WRITE_ONLY param @@ -163,6 +169,35 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); } +void OgreRenderer::setWindowGammaContrast(float gamma, float contrast) +{ + if (mSDLWindow == NULL) return; + + Uint16 red[256], green[256], blue[256]; + for (int i = 0; i < 256; i++) + { + float k = i/256.0f; + k = (k - 0.5f) * contrast + 0.5f; + k = pow(k, 1.f/gamma); + k *= 256; + float value = k*256; + if (value > 65535) value = 65535; + else if (value < 0) value = 0; + + red[i] = green[i] = blue[i] = value; + } + if (SDL_SetWindowGammaRamp(mSDLWindow, red, green, blue) < 0) + std::cout << "Couldn't set gamma: " << SDL_GetError() << std::endl; +} + +void OgreRenderer::restoreWindowGammaRamp() +{ + if (mSDLWindow != NULL) + { + SDL_SetWindowGammaRamp(mSDLWindow, mOldSystemGammaRamp, &mOldSystemGammaRamp[256], &mOldSystemGammaRamp[512]); + } +} + void OgreRenderer::adjustCamera(float fov, float nearClip) { mCamera->setNearClipDistance(nearClip); diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index 70cc3db60..1b18a7b0b 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -67,6 +67,9 @@ namespace OEngine int mWindowHeight; bool mOutstandingResize; + // Store system gamma ramp on window creation. Restore system gamma ramp on exit + uint16_t mOldSystemGammaRamp[256*3]; + public: OgreRenderer() : mRoot(NULL) @@ -83,7 +86,7 @@ namespace OEngine { } - ~OgreRenderer() { cleanup(); } + ~OgreRenderer(); /** Configure the renderer. This will load configuration files and set up the Root and logging classes. */ @@ -95,6 +98,9 @@ namespace OEngine /// Create a window with the given title void createWindow(const std::string &title, const WindowSettings& settings); + void setWindowGammaContrast(float gamma, float contrast); + void restoreWindowGammaRamp(); + /// Set up the scene manager, camera and viewport void adjustCamera( float fov=55, // Field of view angle