From 8f4ffe4ddc569127c5d7a0819798937b95ba11a4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 3 Dec 2013 15:55:31 +0100 Subject: [PATCH 01/10] Fix new window size not being written to settings when manually resizing window --- apps/openmw/mwrender/renderingmanager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 1b891368ff..26e88fb0dc 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -878,6 +878,8 @@ void RenderingManager::setMenuTransparency(float val) void RenderingManager::windowResized(int x, int y) { + Settings::Manager::setInt("resolution x", "Video", x); + Settings::Manager::setInt("resolution y", "Video", y); mRendering.adjustViewport(); mCompositors->recreate(); From 3a82f8c1934223a9fd10bf93558adc16d360bec1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 3 Dec 2013 15:56:00 +0100 Subject: [PATCH 02/10] Fix incorrect log file name for launcherOgre.log --- components/ogreinit/ogreinit.cpp | 2 +- libs/openengine/ogre/renderer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/ogreinit/ogreinit.cpp b/components/ogreinit/ogreinit.cpp index 92a6ed0123..c8fc621c78 100644 --- a/components/ogreinit/ogreinit.cpp +++ b/components/ogreinit/ogreinit.cpp @@ -36,7 +36,7 @@ namespace OgreInit { // Set up logging first new Ogre::LogManager; - Ogre::Log *log = Ogre::LogManager::getSingleton().createLog(logPath + std::string("Ogre.log")); + Ogre::Log *log = Ogre::LogManager::getSingleton().createLog(logPath); // Disable logging to cout/cerr log->setDebugOutputEnabled(false); diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 2a438e1fef..a0fe6ca849 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -50,7 +50,7 @@ void OgreRenderer::configure(const std::string &logPath, const std::string& rttMode ) { - mRoot = mOgreInit.init(logPath); + mRoot = mOgreInit.init(logPath + "/ogre.log"); RenderSystem* rs = mRoot->getRenderSystemByName(renderSystem); if (rs == 0) From 147bc447a5c1e469d3d321ecf442e2b2551fdf53 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 3 Dec 2013 16:07:07 +0100 Subject: [PATCH 03/10] Add specular lighting for directional light to objects shader --- files/materials/objects.mat | 2 +- files/materials/objects.shader | 65 +++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/files/materials/objects.mat b/files/materials/objects.mat index 10fb72740f..ffba6e7ea8 100644 --- a/files/materials/objects.mat +++ b/files/materials/objects.mat @@ -1,7 +1,7 @@ material openmw_objects_base { diffuse 1.0 1.0 1.0 1.0 - specular 0 0 0 0 + specular 0 0 0 0 1 ambient 1.0 1.0 1.0 emissive 0.0 0.0 0.0 vertmode 0 diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 9fc9fceaf0..4acc23b79d 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -32,6 +32,10 @@ #define ENV_MAP @shPropertyBool(env_map) +#define SPECULAR 1 + +#define NEED_NORMAL (!VERTEX_LIGHTING || ENV_MAP) || SPECULAR + #ifdef SH_VERTEX_SHADER // ------------------------------------- VERTEX --------------------------------------- @@ -63,15 +67,12 @@ shOutput(float3, tangentPassthrough) #endif -#if !VERTEX_LIGHTING || ENV_MAP +#if NEED_NORMAL shOutput(float3, normalPassthrough) #endif -#ifdef NEED_DEPTH - shOutput(float, depthPassthrough) -#endif - - shOutput(float3, objSpacePositionPassthrough) + // Depth in w + shOutput(float4, objSpacePositionPassthrough) #if VERTEXCOLOR_MODE != 0 shColourInput(float4) @@ -146,7 +147,7 @@ #if NORMAL_MAP tangentPassthrough = tangent.xyz; #endif -#if !VERTEX_LIGHTING || ENV_MAP +#if NEED_NORMAL normalPassthrough = normal.xyz; #endif #if VERTEXCOLOR_MODE != 0 && !VERTEX_LIGHTING @@ -169,14 +170,14 @@ float4x4 fixedWVP = shMatrixMult(vpFixed, worldMatrix); - depthPassthrough = shMatrixMult(fixedWVP, shInputPosition).z; + objSpacePositionPassthrough.w = shMatrixMult(fixedWVP, shInputPosition).z; #else - depthPassthrough = shOutputPosition.z; + objSpacePositionPassthrough.w = shOutputPosition.z; #endif #endif - objSpacePositionPassthrough = shInputPosition.xyz; + objSpacePositionPassthrough.xyz = shInputPosition.xyz; #if SHADOWS lightSpacePos0 = shMatrixMult(texViewProjMatrix0, shMatrixMult(worldMatrix, shInputPosition)); @@ -262,7 +263,16 @@ #if ENV_MAP shSampler2D(envMap) shUniform(float3, env_map_color) @shUniformProperty3f(env_map_color, env_map_color) - shUniform(float3, cameraPosObjSpace) @shAutoConstant(cameraPosObjSpace, camera_position_object_space) +#endif + +#if ENV_MAP || SPECULAR + shUniform(float3, cameraPosObjSpace) @shAutoConstant(cameraPosObjSpace, camera_position_object_space) +#endif +#if SPECULAR + shUniform(float3, lightSpec0) @shAutoConstant(lightSpec0, light_specular_colour, 0) + shUniform(float3, lightPosObjSpace0) @shAutoConstant(lightPosObjSpace0, light_position_object_space, 0) + shUniform(float, matShininess) @shAutoConstant(matShininess, surface_shininess) + shUniform(float3, matSpec) @shAutoConstant(matSpec, surface_specular_colour) #endif shInput(float4, UV) @@ -270,15 +280,11 @@ #if NORMAL_MAP shInput(float3, tangentPassthrough) #endif -#if !VERTEX_LIGHTING || ENV_MAP +#if NEED_NORMAL shInput(float3, normalPassthrough) #endif -#ifdef NEED_DEPTH - shInput(float, depthPassthrough) -#endif - - shInput(float3, objSpacePositionPassthrough) + shInput(float4, objSpacePositionPassthrough) #if VERTEXCOLOR_MODE != 0 && !VERTEX_LIGHTING shInput(float4, colourPassthrough) @@ -340,6 +346,10 @@ SH_START_PROGRAM { +#ifdef NEED_DEPTH + float depthPassthrough = objSpacePositionPassthrough.w; +#endif + shOutputColour(0) = shSample(diffuseMap, UV.xy); #if DETAIL_MAP @@ -350,7 +360,7 @@ #endif #endif -#if !VERTEX_LIGHTING || ENV_MAP +#if NEED_NORMAL float3 normal = normalPassthrough; #endif @@ -368,7 +378,7 @@ #endif #if !VERTEX_LIGHTING - float3 viewPos = shMatrixMult(worldView, float4(objSpacePositionPassthrough,1)).xyz; + float3 viewPos = shMatrixMult(worldView, float4(objSpacePositionPassthrough.xyz,1)).xyz; float3 viewNormal = normalize(shMatrixMult(worldView, float4(normal.xyz, 0)).xyz); float3 lightDir; @@ -433,7 +443,7 @@ #if (UNDERWATER) || (FOG) - float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePositionPassthrough,1)).xyz; + float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePositionPassthrough.xyz,1)).xyz; #endif #if UNDERWATER @@ -454,15 +464,28 @@ #endif #endif +#if ENV_MAP || SPECULAR + float3 eyeDir = normalize(cameraPosObjSpace.xyz - objSpacePositionPassthrough.xyz); +#endif + #if ENV_MAP // Everything looks better with fresnel - float3 eyeDir = normalize(cameraPosObjSpace.xyz - objSpacePositionPassthrough.xyz); float facing = 1.0 - max(abs(dot(-eyeDir, normal)), 0); float envFactor = shSaturate(0.25 + 0.75 * pow(facing, 1)); shOutputColour(0).xyz += shSample(envMap, UV.zw).xyz * envFactor * env_map_color; #endif +#if SPECULAR + float3 light0Dir = normalize(lightPosObjSpace0.xyz); + + float NdotL = max(dot(normal, light0Dir), 0); + float3 halfVec = normalize (light0Dir + eyeDir); + + float3 specular = pow(max(dot(normal, halfVec), 0), matShininess) * lightSpec0 * matSpec; + shOutputColour(0).xyz += specular * shadow; +#endif + #if FOG float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w); From 5f1878eb54257d54e9507d3df7d664e96b501f71 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 3 Dec 2013 18:41:45 +0100 Subject: [PATCH 04/10] Add specular mapping (uses alpha channel of diffuse texture) --- files/materials/objects.shader | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 4acc23b79d..20abe5b7ce 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -350,7 +350,8 @@ float depthPassthrough = objSpacePositionPassthrough.w; #endif - shOutputColour(0) = shSample(diffuseMap, UV.xy); + float4 diffuse = shSample(diffuseMap, UV.xy); + shOutputColour(0) = diffuse; #if DETAIL_MAP #if @shPropertyString(detailMapUVSet) @@ -483,7 +484,7 @@ float3 halfVec = normalize (light0Dir + eyeDir); float3 specular = pow(max(dot(normal, halfVec), 0), matShininess) * lightSpec0 * matSpec; - shOutputColour(0).xyz += specular * shadow; + shOutputColour(0).xyz += specular * shadow * diffuse.a; #endif #if FOG From f695deb29dc01c33433502bfa3c9c50ca520da51 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 3 Dec 2013 18:42:35 +0100 Subject: [PATCH 05/10] Remember window positions --- apps/openmw/mwgui/inventorywindow.cpp | 67 +++++++++++++++++--------- apps/openmw/mwgui/inventorywindow.hpp | 7 +-- apps/openmw/mwgui/messagebox.cpp | 4 -- apps/openmw/mwgui/statswindow.hpp | 2 + apps/openmw/mwgui/windowmanagerimp.cpp | 51 ++++++++++++++++++++ apps/openmw/mwgui/windowmanagerimp.hpp | 5 ++ files/mygui/openmw_stats_window.layout | 2 +- files/settings-default.cfg | 66 +++++++++++++++++++++++++ libs/openengine/gui/layout.hpp | 2 +- 9 files changed, 172 insertions(+), 34 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 022e0a47d8..56c474c89a 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -37,10 +37,6 @@ namespace MWGui , mPreviewDirty(true) , mDragAndDrop(dragAndDrop) , mSelectedItem(-1) - , mPositionInventory(0, 342, 498, 258) - , mPositionContainer(0, 342, 498, 258) - , mPositionCompanion(0, 342, 498, 258) - , mPositionBarter(0, 342, 498, 258) , mGuiMode(GM_Inventory) { static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); @@ -71,8 +67,19 @@ namespace MWGui mFilterAll->setStateSelected(true); - setCoord(mPositionInventory.left, mPositionInventory.top, mPositionInventory.width, mPositionInventory.height); - onWindowResize(static_cast(mMainWidget)); + setGuiMode(mGuiMode); + + adjustPanes(); + } + + void InventoryWindow::adjustPanes() + { + const float aspect = 0.5; // fixed aspect ratio for the left pane + mLeftPane->setSize( (mMainWidget->getSize().height-44) * aspect, mMainWidget->getSize().height-44 ); + mRightPane->setCoord( mLeftPane->getPosition().left + (mMainWidget->getSize().height-44) * aspect + 4, + mRightPane->getPosition().top, + mMainWidget->getSize().width - 12 - (mMainWidget->getSize().height-44) * aspect - 15, + mMainWidget->getSize().height-44 ); } void InventoryWindow::updatePlayer() @@ -87,27 +94,36 @@ namespace MWGui void InventoryWindow::setGuiMode(GuiMode mode) { + std::string setting = "inventory"; mGuiMode = mode; switch(mode) { case GM_Container: setPinButtonVisible(false); - mMainWidget->setCoord(mPositionContainer); + setting += " container"; break; case GM_Companion: setPinButtonVisible(false); - mMainWidget->setCoord(mPositionCompanion); + setting += " companion"; break; case GM_Barter: setPinButtonVisible(false); - mMainWidget->setCoord(mPositionBarter); + setting += " barter"; break; case GM_Inventory: default: setPinButtonVisible(true); - mMainWidget->setCoord(mPositionInventory); break; } - onWindowResize(static_cast(mMainWidget)); + + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + MyGUI::IntPoint pos (Settings::Manager::getFloat(setting + " x", "Windows") * viewSize.width, + Settings::Manager::getFloat(setting + " y", "Windows") * viewSize.height); + MyGUI::IntSize size (Settings::Manager::getFloat(setting + " w", "Windows") * viewSize.width, + Settings::Manager::getFloat(setting + " h", "Windows") * viewSize.height); + mMainWidget->setPosition(pos); + mMainWidget->setSize(size); + adjustPanes(); + mPreviewDirty = true; } TradeItemModel* InventoryWindow::getTradeModel() @@ -256,32 +272,37 @@ namespace MWGui mItemView->update(); notifyContentChanged(); + adjustPanes(); } void InventoryWindow::onWindowResize(MyGUI::Window* _sender) { - const float aspect = 0.5; // fixed aspect ratio for the left pane - mLeftPane->setSize( (_sender->getSize().height-44) * aspect, _sender->getSize().height-44 ); - mRightPane->setCoord( mLeftPane->getPosition().left + (_sender->getSize().height-44) * aspect + 4, - mRightPane->getPosition().top, - _sender->getSize().width - 12 - (_sender->getSize().height-44) * aspect - 15, - _sender->getSize().height-44 ); - + adjustPanes(); + std::string setting = "inventory"; switch(mGuiMode) { case GM_Container: - mPositionContainer = _sender->getCoord(); + setting += " container"; break; case GM_Companion: - mPositionCompanion = _sender->getCoord(); + setting += " companion"; break; case GM_Barter: - mPositionBarter = _sender->getCoord(); + setting += " barter"; break; - case GM_Inventory: default: - mPositionInventory = _sender->getCoord(); + break; } + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + float x = _sender->getPosition().left / float(viewSize.width); + float y = _sender->getPosition().top / float(viewSize.height); + float w = _sender->getSize().width / float(viewSize.width); + float h = _sender->getSize().height / float(viewSize.height); + Settings::Manager::setFloat(setting + " x", "Windows", x); + Settings::Manager::setFloat(setting + " y", "Windows", y); + Settings::Manager::setFloat(setting + " w", "Windows", w); + Settings::Manager::setFloat(setting + " h", "Windows", h); + if (mMainWidget->getSize().width != mLastXSize || mMainWidget->getSize().height != mLastYSize) { mLastXSize = mMainWidget->getSize().width; diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 78d00fd1e7..94ecfd4c8a 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -76,11 +76,6 @@ namespace MWGui MyGUI::Button* mFilterMagic; MyGUI::Button* mFilterMisc; - MyGUI::IntCoord mPositionInventory; - MyGUI::IntCoord mPositionContainer; - MyGUI::IntCoord mPositionCompanion; - MyGUI::IntCoord mPositionBarter; - GuiMode mGuiMode; int mLastXSize; @@ -105,6 +100,8 @@ namespace MWGui void updateEncumbranceBar(); void notifyContentChanged(); + + void adjustPanes(); }; } diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 0a9ee01888..8486218f0b 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -154,10 +154,6 @@ namespace MWGui size.width = mFixedWidth; size.height = 100; // dummy - MyGUI::IntCoord coord; - coord.left = 10; // dummy - coord.top = 10; // dummy - mMessageWidget->setSize(size); MyGUI::IntSize textSize = mMessageWidget->getTextSize(); diff --git a/apps/openmw/mwgui/statswindow.hpp b/apps/openmw/mwgui/statswindow.hpp index ac8319bdcd..49b44a2e16 100644 --- a/apps/openmw/mwgui/statswindow.hpp +++ b/apps/openmw/mwgui/statswindow.hpp @@ -37,6 +37,8 @@ namespace MWGui void setBounty (int bounty) { if (bounty != mBounty) mChanged = true; this->mBounty = bounty; } void updateSkillArea(); + virtual void open() { onWindowResize(static_cast(mMainWidget)); } + private: void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 2bcfdfb62d..78986a0522 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -203,16 +203,22 @@ namespace MWGui mRecharge = new Recharge(); mMenu = new MainMenu(w,h); mMap = new MapWindow(""); + trackWindow(mMap, "map"); mStatsWindow = new StatsWindow(); + trackWindow(mStatsWindow, "stats"); mConsole = new Console(w,h, mConsoleOnlyScripts); + trackWindow(mConsole, "console"); mJournal = JournalWindow::create(JournalViewModel::create ()); mMessageBoxManager = new MessageBoxManager(); mInventoryWindow = new InventoryWindow(mDragAndDrop); mTradeWindow = new TradeWindow(); + trackWindow(mTradeWindow, "barter"); mSpellBuyingWindow = new SpellBuyingWindow(); mTravelWindow = new TravelWindow(); mDialogueWindow = new DialogueWindow(); + trackWindow(mDialogueWindow, "dialogue"); mContainerWindow = new ContainerWindow(mDragAndDrop); + trackWindow(mContainerWindow, "container"); mHud = new HUD(w,h, mShowFPSLevel, mDragAndDrop); mToolTips = new ToolTips(); mScrollWindow = new ScrollWindow(); @@ -221,7 +227,9 @@ namespace MWGui mSettingsWindow = new SettingsWindow(); mConfirmationDialog = new ConfirmationDialog(); mAlchemyWindow = new AlchemyWindow(); + trackWindow(mAlchemyWindow, "alchemy"); mSpellWindow = new SpellWindow(); + trackWindow(mSpellWindow, "spells"); mQuickKeysMenu = new QuickKeysMenu(); mLevelupDialog = new LevelupDialog(); mWaitDialog = new WaitDialog(); @@ -232,6 +240,7 @@ namespace MWGui mRepair = new Repair(); mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager); + trackWindow(mCompanionWindow, "companion"); mInputBlocker = mGui->createWidget("",0,0,w,h,MyGUI::Align::Default,"Windows",""); @@ -926,6 +935,17 @@ namespace MWGui mLoadingScreen->onResChange (x,y); if (!mHud) return; // UI not initialized yet + + for (std::map::iterator it = mTrackedWindows.begin(); it != mTrackedWindows.end(); ++it) + { + MyGUI::IntPoint pos (Settings::Manager::getFloat(it->second + " x", "Windows") * x, + Settings::Manager::getFloat(it->second+ " y", "Windows") * y); + MyGUI::IntSize size (Settings::Manager::getFloat(it->second + " w", "Windows") * x, + Settings::Manager::getFloat(it->second + " h", "Windows") * y); + it->first->setPosition(pos); + it->first->setSize(size); + } + mHud->onResChange(x, y); mConsole->onResChange(x, y); mMenu->onResChange(x, y); @@ -1364,4 +1384,35 @@ namespace MWGui return mCursorVisible; } + void WindowManager::trackWindow(OEngine::GUI::Layout *layout, const std::string &name) + { + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + MyGUI::IntPoint pos (Settings::Manager::getFloat(name + " x", "Windows") * viewSize.width, + Settings::Manager::getFloat(name + " y", "Windows") * viewSize.height); + MyGUI::IntSize size (Settings::Manager::getFloat(name + " w", "Windows") * viewSize.width, + Settings::Manager::getFloat(name + " h", "Windows") * viewSize.height); + layout->mMainWidget->setPosition(pos); + layout->mMainWidget->setSize(size); + + MyGUI::Window* window = dynamic_cast(layout->mMainWidget); + if (!window) + throw std::runtime_error("Attempting to track size of a non-resizable window"); + window->eventWindowChangeCoord += MyGUI::newDelegate(this, &WindowManager::onWindowChangeCoord); + mTrackedWindows[window] = name; + } + + void WindowManager::onWindowChangeCoord(MyGUI::Window *_sender) + { + std::string setting = mTrackedWindows[_sender]; + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + float x = _sender->getPosition().left / float(viewSize.width); + float y = _sender->getPosition().top / float(viewSize.height); + float w = _sender->getSize().width / float(viewSize.width); + float h = _sender->getSize().height / float(viewSize.height); + Settings::Manager::setFloat(setting + " x", "Windows", x); + Settings::Manager::setFloat(setting + " y", "Windows", y); + Settings::Manager::setFloat(setting + " w", "Windows", w); + Settings::Manager::setFloat(setting + " h", "Windows", h); + } + } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index c5b6ff2beb..4f19602958 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -16,6 +16,7 @@ namespace MyGUI { class Gui; class Widget; + class Window; class UString; } @@ -283,6 +284,10 @@ namespace MWGui private: bool mConsoleOnlyScripts; + std::map mTrackedWindows; + void trackWindow(OEngine::GUI::Layout* layout, const std::string& name); + void onWindowChangeCoord(MyGUI::Window* _sender); + OEngine::GUI::MyGUIManager *mGuiManager; OEngine::Render::OgreRenderer *mRendering; HUD *mHud; diff --git a/files/mygui/openmw_stats_window.layout b/files/mygui/openmw_stats_window.layout index 5ae3f96caf..36c28c450e 100644 --- a/files/mygui/openmw_stats_window.layout +++ b/files/mygui/openmw_stats_window.layout @@ -2,7 +2,7 @@ - + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index f191430df1..94bdd8c9df 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -169,3 +169,69 @@ ui y multiplier = 1.0 [Game] # Always use the most powerful attack when striking with a weapon (chop, slash or thrust) best attack = false + +[Windows] +inventory x = 0 +inventory y = 0.4275 +inventory w = 0.6225 +inventory h = 0.5725 + +inventory container x = 0 +inventory container y = 0.4275 +inventory container w = 0.6225 +inventory container h = 0.5725 + +inventory barter x = 0 +inventory barter y = 0.4275 +inventory barter w = 0.6225 +inventory barter h = 0.5725 + +inventory companion x = 0 +inventory companion y = 0.4275 +inventory companion w = 0.6225 +inventory companion h = 0.5725 + +container x = 0.25 +container y = 0 +container w = 0.75 +container h = 0.375 + +companion x = 0.25 +companion y = 0 +companion w = 0.75 +companion h = 0.375 + +map x = 0.625 +map y = 0 +map w = 0.375 +map h = 0.5725 + +barter x = 0.25 +barter y = 0 +barter w = 0.75 +barter h = 0.375 + +alchemy x = 0.25 +alchemy y = 0.25 +alchemy w = 0.5 +alchemy h = 0.5 + +stats x = 0 +stats y = 0 +stats w = 0.375 +stats h = 0.4275 + +spells x = 0.3775 +spells y = 0.4275 +spells w = 0.375 +spells h = 0.5725 + +console x = 0 +console y = 0 +console w = 1 +console h = 0.5 + +dialogue h = 0.810 +dialogue w = 0.810 +dialogue x = 0.095 +dialogue y = 0.095 diff --git a/libs/openengine/gui/layout.hpp b/libs/openengine/gui/layout.hpp index 9040dfb90e..26a3fdab84 100644 --- a/libs/openengine/gui/layout.hpp +++ b/libs/openengine/gui/layout.hpp @@ -150,10 +150,10 @@ namespace GUI MyGUI::IntSize size = button->getTextSize(); button->setSize(size.width + 24, button->getSize().height); } + MyGUI::Widget* mMainWidget; protected: - MyGUI::Widget* mMainWidget; std::string mPrefix; std::string mLayoutName; MyGUI::VectorWidgetPtr mListWindowRoot; From 9ab8fe10388bfda90aef06c762095d48b97ed830 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 4 Dec 2013 16:03:32 +0100 Subject: [PATCH 06/10] Fix bsatool warning --- apps/bsatool/bsatool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bsatool/bsatool.cpp b/apps/bsatool/bsatool.cpp index e6fcc2567d..3781dd066e 100644 --- a/apps/bsatool/bsatool.cpp +++ b/apps/bsatool/bsatool.cpp @@ -184,7 +184,7 @@ int list(Bsa::BSAFile& bsa, Arguments& info) { // List all files const Bsa::BSAFile::FileList &files = bsa.getList(); - for(int i=0; i Date: Wed, 4 Dec 2013 21:43:10 +0100 Subject: [PATCH 07/10] Add normal, specular & parallax mapping for terrain --- components/terrain/material.cpp | 53 +++++++++- components/terrain/material.hpp | 10 +- components/terrain/quadtreenode.cpp | 12 ++- components/terrain/storage.cpp | 36 ++++++- components/terrain/storage.hpp | 13 ++- files/materials/objects.shader | 1 - files/materials/terrain.shader | 155 +++++++++++++++++++++++++--- 7 files changed, 251 insertions(+), 29 deletions(-) diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index ebf6046ff6..b421de5a28 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include namespace @@ -36,6 +38,8 @@ namespace Terrain : mShaders(shaders) , mShadows(false) , mSplitShadows(false) + , mNormalMapping(true) + , mParallaxMapping(true) { } @@ -85,7 +89,7 @@ namespace Terrain { assert(mLayerList.size() == mBlendmapList.size()+1); std::vector::iterator blend = mBlendmapList.begin(); - for (std::vector::iterator layer = mLayerList.begin(); layer != mLayerList.end(); ++layer) + for (std::vector::iterator layer = mLayerList.begin(); layer != mLayerList.end(); ++layer) { Ogre::Pass* pass = technique->createPass(); pass->setLightingEnabled(false); @@ -117,7 +121,7 @@ namespace Terrain } // Add the actual layer texture on top of the alpha map. - tus = pass->createTextureUnitState("textures\\" + *layer); + tus = pass->createTextureUnitState(layer->mDiffuseMap); if (!first) tus->setColourOperationEx(Ogre::LBX_BLEND_DIFFUSE_ALPHA, Ogre::LBS_TEXTURE, @@ -156,6 +160,10 @@ namespace Terrain p->mShaderProperties.setProperty ("display_composite_map", sh::makeProperty(new sh::BooleanValue(true))); p->mShaderProperties.setProperty ("num_layers", sh::makeProperty (new sh::StringValue("0"))); p->mShaderProperties.setProperty ("num_blendmaps", sh::makeProperty (new sh::StringValue("0"))); + p->mShaderProperties.setProperty ("normal_map_enabled", sh::makeProperty (new sh::BooleanValue(false))); + p->mShaderProperties.setProperty ("parallax_enabled", sh::makeProperty (new sh::BooleanValue(false))); + p->mShaderProperties.setProperty ("normal_maps", + sh::makeProperty (new sh::IntValue(0))); sh::MaterialInstanceTextureUnit* tex = p->createTextureUnit ("compositeMap"); tex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(mCompositeMap))); @@ -210,6 +218,11 @@ namespace Terrain } } ++neededTextureUnits; // layer texture + + // Check if this layer has a normal map + if (mNormalMapping && !mLayerList[layerOffset].mNormalMap.empty()) + ++neededTextureUnits; // normal map + if (neededTextureUnits <= remainingTextureUnits) { // We can fit another! @@ -238,6 +251,8 @@ namespace Terrain p->mShaderProperties.setProperty ("num_layers", sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(numLayersInThisPass)))); p->mShaderProperties.setProperty ("num_blendmaps", sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(numBlendTextures)))); + p->mShaderProperties.setProperty ("normal_map_enabled", + sh::makeProperty (new sh::BooleanValue(false))); // blend maps // the index of the first blend map used in this pass @@ -254,17 +269,39 @@ namespace Terrain } // layer maps + bool anyNormalMaps = false; + bool anyParallax = false; + size_t normalMaps = 0; for (int i = 0; i < numLayersInThisPass; ++i) { + const LayerInfo& layer = mLayerList[layerOffset+i]; + // diffuse map sh::MaterialInstanceTextureUnit* diffuseTex = p->createTextureUnit ("diffuseMap" + Ogre::StringConverter::toString(i)); - diffuseTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue("textures\\"+mLayerList[layerOffset+i]))); + diffuseTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(layer.mDiffuseMap))); + + // normal map (optional) + bool useNormalMap = mNormalMapping && !mLayerList[layerOffset+i].mNormalMap.empty() && !renderCompositeMap; + bool useParallax = useNormalMap && mParallaxMapping && layer.mParallax; + if (useNormalMap) + { + anyNormalMaps = true; + anyParallax = anyParallax || useParallax; + sh::MaterialInstanceTextureUnit* normalTex = p->createTextureUnit ("normalMap" + Ogre::StringConverter::toString(i)); + normalTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(layer.mNormalMap))); + } + p->mShaderProperties.setProperty ("use_normal_map_" + Ogre::StringConverter::toString(i), + sh::makeProperty (new sh::BooleanValue(useNormalMap))); + p->mShaderProperties.setProperty ("use_parallax_" + Ogre::StringConverter::toString(i), + sh::makeProperty (new sh::BooleanValue(useParallax))); + boost::hash_combine(normalMaps, useNormalMap); + boost::hash_combine(normalMaps, useNormalMap && layer.mParallax); if (i+layerOffset > 0) { int blendTextureIndex = getBlendmapIndexForLayer(layerOffset+i); std::string blendTextureComponent = getBlendmapComponentForLayer(layerOffset+i); p->mShaderProperties.setProperty ("blendmap_component_" + Ogre::StringConverter::toString(i), - sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(blendTextureIndex-blendmapStart) + "." + blendTextureComponent))); + sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(blendTextureIndex-blendmapStart) + "." + blendTextureComponent))); } else { @@ -274,6 +311,14 @@ namespace Terrain sh::makeProperty (new sh::StringValue(""))); } } + p->mShaderProperties.setProperty ("normal_map_enabled", + sh::makeProperty (new sh::BooleanValue(anyNormalMaps))); + p->mShaderProperties.setProperty ("parallax_enabled", + sh::makeProperty (new sh::BooleanValue(anyParallax))); + // Since the permutation handler can't handle dynamic property names, + // combine normal map settings for all layers into one value + p->mShaderProperties.setProperty ("normal_maps", + sh::makeProperty (new sh::IntValue(normalMaps))); // shadow if (shadows) diff --git a/components/terrain/material.hpp b/components/terrain/material.hpp index 330ed3d147..e7e0678991 100644 --- a/components/terrain/material.hpp +++ b/components/terrain/material.hpp @@ -3,6 +3,8 @@ #include +#include "storage.hpp" + namespace Terrain { @@ -15,13 +17,15 @@ namespace Terrain /// so if this parameter is true, then the supplied blend maps are expected to be packed. MaterialGenerator (bool shaders); - void setLayerList (const std::vector& layerList) { mLayerList = layerList; } + void setLayerList (const std::vector& layerList) { mLayerList = layerList; } bool hasLayers() { return mLayerList.size(); } void setBlendmapList (const std::vector& blendmapList) { mBlendmapList = blendmapList; } const std::vector& getBlendmapList() { return mBlendmapList; } void setCompositeMap (const std::string& name) { mCompositeMap = name; } void enableShadows(bool shadows) { mShadows = shadows; } + void enableNormalMapping(bool normalMapping) { mNormalMapping = normalMapping; } + void enableParallaxMapping(bool parallaxMapping) { mParallaxMapping = parallaxMapping; } void enableSplitShadows(bool splitShadows) { mSplitShadows = splitShadows; } /// Creates a material suitable for displaying a chunk of terrain using alpha-blending. @@ -43,12 +47,14 @@ namespace Terrain private: Ogre::MaterialPtr create (Ogre::MaterialPtr mat, bool renderCompositeMap, bool displayCompositeMap); - std::vector mLayerList; + std::vector mLayerList; std::vector mBlendmapList; std::string mCompositeMap; bool mShaders; bool mShadows; bool mSplitShadows; + bool mNormalMapping; + bool mParallaxMapping; }; } diff --git a/components/terrain/quadtreenode.cpp b/components/terrain/quadtreenode.cpp index ef2c610138..e16ae55ddb 100644 --- a/components/terrain/quadtreenode.cpp +++ b/components/terrain/quadtreenode.cpp @@ -371,7 +371,7 @@ void QuadTreeNode::destroyChunks(bool children) for (std::vector::const_iterator it = list.begin(); it != list.end(); ++it) Ogre::TextureManager::getSingleton().remove((*it)->getName()); mMaterialGenerator->setBlendmapList(std::vector()); - mMaterialGenerator->setLayerList(std::vector()); + mMaterialGenerator->setLayerList(std::vector()); mMaterialGenerator->setCompositeMap(""); } @@ -414,7 +414,7 @@ void QuadTreeNode::ensureLayerInfo() return; std::vector blendmaps; - std::vector layerList; + std::vector layerList; mTerrain->getStorage()->getBlendmaps(mSize, mCenter, mTerrain->getShadersEnabled(), blendmaps, layerList); mMaterialGenerator->setLayerList(layerList); @@ -427,11 +427,13 @@ void QuadTreeNode::prepareForCompositeMap(Ogre::TRect area) if (mIsDummy) { - // TODO - why is this completely black? // TODO - store this default material somewhere instead of creating one for each empty cell MaterialGenerator matGen(mTerrain->getShadersEnabled()); - std::vector layer; - layer.push_back("_land_default.dds"); + std::vector layer; + LayerInfo info; + info.mDiffuseMap = "textures\\_land_default.dds"; + info.mParallax = false; + layer.push_back(info); matGen.setLayerList(layer); makeQuad(sceneMgr, area.left, area.top, area.right, area.bottom, matGen.generateForCompositeMapRTT(Ogre::MaterialPtr())); return; diff --git a/components/terrain/storage.cpp b/components/terrain/storage.cpp index f00677e97f..9d6b44de8d 100644 --- a/components/terrain/storage.cpp +++ b/components/terrain/storage.cpp @@ -4,9 +4,10 @@ #include #include #include +#include #include -#include +#include namespace Terrain { @@ -302,7 +303,7 @@ namespace Terrain } void Storage::getBlendmaps(float chunkSize, const Ogre::Vector2 &chunkCenter, - bool pack, std::vector &blendmaps, std::vector &layerList) + bool pack, std::vector &blendmaps, std::vector &layerList) { // TODO - blending isn't completely right yet; the blending radius appears to be // different at a cell transition (2 vertices, not 4), so we may need to create a larger blendmap @@ -336,7 +337,7 @@ namespace Terrain { int size = textureIndicesMap.size(); textureIndicesMap[*it] = size; - layerList.push_back(getTextureName(*it)); + layerList.push_back(getLayerInfo(getTextureName(*it))); } int numTextures = textureIndices.size(); @@ -466,5 +467,34 @@ namespace Terrain return land->mLandData->mHeights[y * ESM::Land::LAND_SIZE + x]; } + LayerInfo Storage::getLayerInfo(const std::string& texture) + { + // Already have this cached? + if (mLayerInfoMap.find(texture) != mLayerInfoMap.end()) + return mLayerInfoMap[texture]; + + LayerInfo info; + info.mParallax = false; + info.mDiffuseMap = "textures\\" + texture; + std::string texture_ = texture; + boost::replace_last(texture_, ".", "_nh."); + if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup("textures\\" + texture_)) + { + info.mNormalMap = "textures\\" + texture_; + info.mParallax = true; + } + else + { + texture_ = texture; + boost::replace_last(texture_, ".", "_n."); + if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup("textures\\" + texture_)) + info.mNormalMap = "textures\\" + texture_; + } + + mLayerInfoMap[texture] = info; + + return info; + } + } diff --git a/components/terrain/storage.hpp b/components/terrain/storage.hpp index b82f6bbb62..68fae01afa 100644 --- a/components/terrain/storage.hpp +++ b/components/terrain/storage.hpp @@ -11,6 +11,13 @@ namespace Terrain { + struct LayerInfo + { + std::string mDiffuseMap; + std::string mNormalMap; + bool mParallax; // Height info in normal map alpha channel? + }; + /// We keep storage of terrain data abstract here since we need different implementations for game and editor class Storage { @@ -58,7 +65,7 @@ namespace Terrain /// @param layerList names of the layer textures used will be written here void getBlendmaps (float chunkSize, const Ogre::Vector2& chunkCenter, bool pack, std::vector& blendmaps, - std::vector& layerList); + std::vector& layerList); float getHeightAt (const Ogre::Vector3& worldPos); @@ -77,6 +84,10 @@ namespace Terrain UniqueTextureId getVtexIndexAt(int cellX, int cellY, int x, int y); std::string getTextureName (UniqueTextureId id); + + std::map mLayerInfoMap; + + LayerInfo getLayerInfo(const std::string& texture); }; } diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 20abe5b7ce..fb2b304262 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -327,7 +327,6 @@ shInput(float4, lightResult) shInput(float3, directionalResult) #else - shUniform(float, lightCount) @shAutoConstant(lightCount, light_count) shUniform(float4, lightPosition[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightPosition, light_position_view_space_array, @shGlobalSettingString(num_lights)) shUniform(float4, lightDiffuse[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightDiffuse, light_diffuse_colour_array, @shGlobalSettingString(num_lights)) shUniform(float4, lightAttenuation[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightAttenuation, light_attenuation_array, @shGlobalSettingString(num_lights)) diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 861841a84c..eda80c9e30 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -27,6 +27,16 @@ #define COMPOSITE_MAP @shPropertyBool(display_composite_map) +#define NORMAL_MAP @shPropertyBool(normal_map_enabled) +#define PARALLAX @shPropertyBool(parallax_enabled) + +#define VERTEX_LIGHTING (!NORMAL_MAP) + +#define PARALLAX_SCALE 0.04 +#define PARALLAX_BIAS -0.02 + +// This is just for the permutation handler +#define NORMAL_MAPS @shPropertyString(normal_maps) #if NEED_DEPTH @shAllocatePassthrough(1, depth) @@ -37,8 +47,13 @@ @shAllocatePassthrough(3, worldPos) #if LIGHTING +@shAllocatePassthrough(3, normalPassthrough) +#if VERTEX_LIGHTING @shAllocatePassthrough(3, lightResult) @shAllocatePassthrough(3, directionalResult) +#else +@shAllocatePassthrough(3, colourPassthrough) +#endif #if SHADOWS @shAllocatePassthrough(4, lightSpacePos0) @@ -69,12 +84,13 @@ shNormalInput(float4) shColourInput(float4) - shUniform(float, lightCount) @shAutoConstant(lightCount, light_count) +#if VERTEX_LIGHTING shUniform(float4, lightPosition[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightPosition, light_position_object_space_array, @shGlobalSettingString(num_lights)) shUniform(float4, lightDiffuse[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightDiffuse, light_diffuse_colour_array, @shGlobalSettingString(num_lights)) shUniform(float4, lightAttenuation[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightAttenuation, light_attenuation_array, @shGlobalSettingString(num_lights)) shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) - +#endif + #if SHADOWS shUniform(float4x4, texViewProjMatrix0) @shAutoConstant(texViewProjMatrix0, texture_viewproj_matrix) #endif @@ -122,6 +138,13 @@ @shPassthroughAssign(worldPos, worldPos.xyz); +#if LIGHTING + @shPassthroughAssign(normalPassthrough, normal.xyz); +#endif +#if LIGHTING && !VERTEX_LIGHTING + @shPassthroughAssign(colourPassthrough, colour.xyz); +#endif + #if LIGHTING #if SHADOWS @@ -139,6 +162,7 @@ #endif +#if VERTEX_LIGHTING // Lighting float3 lightDir; float d; @@ -164,6 +188,7 @@ @shPassthroughAssign(lightResult, lightResult); @shPassthroughAssign(directionalResult, directionalResult); +#endif #endif } @@ -189,6 +214,9 @@ @shForeach(@shPropertyString(num_layers)) shSampler2D(diffuseMap@shIterator) +#if @shPropertyBool(use_normal_map_@shIterator) + shSampler2D(normalMap@shIterator) +#endif @shEndForeach #endif @@ -201,6 +229,15 @@ @shPassthroughFragmentInputs #if LIGHTING + +#if !VERTEX_LIGHTING +shUniform(float4, lightPosition[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightPosition, light_position_array, @shGlobalSettingString(num_lights)) +shUniform(float4, lightDiffuse[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightDiffuse, light_diffuse_colour_array, @shGlobalSettingString(num_lights)) +shUniform(float4, lightAttenuation[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightAttenuation, light_attenuation_array, @shGlobalSettingString(num_lights)) +shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) +shUniform(float4x4, worldView) @shAutoConstant(worldView, worldview_matrix) +#endif + #if SHADOWS shSampler2D(shadowMap0) shUniform(float2, invShadowmapSize0) @shAutoConstant(invShadowmapSize0, inverse_texture_size, @shPropertyString(shadowtexture_offset)) @@ -220,13 +257,21 @@ #if (UNDERWATER) || (FOG) shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) - shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position) #endif #if UNDERWATER shUniform(float, waterLevel) @shSharedParameter(waterLevel) #endif + +// For specular +#if LIGHTING + shUniform(float3, lightSpec0) @shAutoConstant(lightSpec0, light_specular_colour, 0) + shUniform(float3, lightPos0) @shAutoConstant(lightPos0, light_position, 0) +#endif + +shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position) + SH_START_PROGRAM { @@ -237,12 +282,32 @@ float2 UV = @shPassthroughReceive(UV); float3 worldPos = @shPassthroughReceive(worldPos); - - + +#if LIGHTING + float3 normal = @shPassthroughReceive(normalPassthrough); +#endif + +#if LIGHTING && !VERTEX_LIGHTING + +#if NORMAL_MAP + // derive the tangent space basis + float3 tangent = float3(1,0, 0); + + float3 binormal = normalize(cross(tangent, normal)); + tangent = normalize(cross(normal, binormal)); // note, now we need to re-cross to derive tangent again because it wasn't orthonormal + + // derive final matrix + float3x3 tbn = float3x3(tangent, binormal, normal); + #if SH_GLSL + tbn = transpose(tbn); + #endif +#endif + +#endif + #if UNDERWATER float3 waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,0,1), waterLevel); #endif - #if !IS_FIRST_PASS // Opacity the previous passes should have, i.e. 1 - (opacity of this pass) @@ -252,6 +317,8 @@ float previousAlpha = 1.f; shOutputColour(0) = float4(1,1,1,1); +float3 TSnormal = float3(0,0,1); + #if COMPOSITE_MAP shOutputColour(0).xyz = shSample(compositeMap, UV).xyz; #else @@ -266,39 +333,90 @@ float2 blendUV = (UV - 0.5) * (16.0 / (16.0+1.0)) + 0.5; @shEndForeach - float3 albedo = float3(0,0,0); + float4 albedo = float4(0,0,0,1); float2 layerUV = UV * 16; + float2 thisLayerUV; + float4 normalTex; + + float3 eyeDir = normalize(cameraPos.xyz - worldPos); +#if PARALLAX + float3 TSeyeDir = normalize(shMatrixMult(tbn, eyeDir)); +#endif @shForeach(@shPropertyString(num_layers)) +#if @shPropertyBool(use_normal_map_@shIterator) + normalTex = shSample(normalMap@shIterator, thisLayerUV); +#if @shIterator == 0 && IS_FIRST_PASS + TSnormal = normalize(normalTex.xyz * 2 - 1); +#else + TSnormal = shLerp(TSnormal, normalTex.xyz * 2 - 1, blendValues@shPropertyString(blendmap_component_@shIterator)); +#endif +#endif + thisLayerUV = layerUV; + // required to play nicely with the tangents + thisLayerUV.y *= -1; +#if @shPropertyBool(use_parallax_@shIterator) + thisLayerUV += TSeyeDir.xy * ( normalTex.a * PARALLAX_SCALE + PARALLAX_BIAS ); +#endif #if IS_FIRST_PASS #if @shIterator == 0 // first layer of first pass is the base layer and doesn't need a blend map - albedo = shSample(diffuseMap0, layerUV).rgb; + albedo = shSample(diffuseMap0, layerUV); #else - albedo = shLerp(albedo, shSample(diffuseMap@shIterator, layerUV).rgb, blendValues@shPropertyString(blendmap_component_@shIterator)); + albedo = shLerp(albedo, shSample(diffuseMap@shIterator, thisLayerUV), blendValues@shPropertyString(blendmap_component_@shIterator)); #endif #else #if @shIterator == 0 - albedo = shSample(diffuseMap@shIterator, layerUV).rgb, blendValues@shPropertyString(blendmap_component_@shIterator); + albedo = shSample(diffuseMap@shIterator, layerUV); #else - albedo = shLerp(albedo, shSample(diffuseMap@shIterator, layerUV).rgb, blendValues@shPropertyString(blendmap_component_@shIterator)); + albedo = shLerp(albedo, shSample(diffuseMap@shIterator, thisLayerUV), blendValues@shPropertyString(blendmap_component_@shIterator)); #endif previousAlpha *= 1.f-blendValues@shPropertyString(blendmap_component_@shIterator); #endif + + @shEndForeach - shOutputColour(0).rgb *= albedo; + shOutputColour(0).rgb *= albedo.xyz; #endif #if LIGHTING + +#if VERTEX_LIGHTING // Lighting float3 lightResult = @shPassthroughReceive(lightResult); float3 directionalResult = @shPassthroughReceive(directionalResult); - +#else + +#if NORMAL_MAP + normal = normalize (shMatrixMult( transpose(tbn), TSnormal )); +#endif + + float3 colour = @shPassthroughReceive(colourPassthrough); + float3 lightDir; + float d; + float3 lightResult = float3(0,0,0); + @shForeach(@shGlobalSettingString(num_lights)) + lightDir = lightPosition[@shIterator].xyz - (worldPos * lightPosition[@shIterator].w); + d = length(lightDir); + lightDir = normalize(lightDir); + + lightResult.xyz += lightDiffuse[@shIterator].xyz + * shSaturate(1.0 / ((lightAttenuation[@shIterator].y) + (lightAttenuation[@shIterator].z * d) + (lightAttenuation[@shIterator].w * d * d))) + * max(dot(normal.xyz, lightDir), 0); +#if @shIterator == 0 + float3 directionalResult = lightResult.xyz; +#endif + @shEndForeach + lightResult.xyz += lightAmbient.xyz; + lightResult.xyz *= colour.xyz; + directionalResult.xyz *= colour.xyz; +#endif + // shadows only for the first (directional) light #if SHADOWS float4 lightSpacePos0 = @shPassthroughReceive(lightSpacePos0); @@ -325,6 +443,17 @@ float2 blendUV = (UV - 0.5) * (16.0 / (16.0+1.0)) + 0.5; shOutputColour(0).xyz *= (lightResult - directionalResult * (1.0-shadow)); #endif +#if LIGHTING && !COMPOSITE_MAP + // Specular + float3 light0Dir = normalize(lightPos0.xyz); + + float NdotL = max(dot(normal, light0Dir), 0); + float3 halfVec = normalize (light0Dir + eyeDir); + + float3 specular = pow(max(dot(normal, halfVec), 0), 32) * lightSpec0; + shOutputColour(0).xyz += specular * (1.f-albedo.a) * shadow; +#endif + #if FOG float fogValue = shSaturate((depth - fogParams.y) * fogParams.w); From afa71bb622df10872c2d997731c30b409b4cb374 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Dec 2013 14:23:39 +0100 Subject: [PATCH 08/10] Throw an exception if a BSA is not found --- apps/openmw/engine.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index a729bdda1e..02e7a59550 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -1,6 +1,6 @@ #include "engine.hpp" -#include "components/esm/loadcell.hpp" +#include #include #include @@ -18,6 +18,8 @@ #include #include +#include + #include "mwinput/inputmanagerimp.hpp" #include "mwgui/windowmanagerimp.hpp" @@ -211,7 +213,9 @@ void OMW::Engine::loadBSA() } else { - std::cout << "Archive " << *archive << " not found" << std::endl; + std::stringstream message; + message << "Archive '" << *archive << "' not found"; + throw std::runtime_error(message.str()); } } } From 845bc5f7ebbc82604edef8ee1359d95cb6819220 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Dec 2013 14:28:39 +0100 Subject: [PATCH 09/10] Show fatal exceptions in a message box instead of cerr when running without a terminal --- apps/openmw/main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 42815e330b..b1bbb14f23 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -1,7 +1,9 @@ #include +#include #include +#include #include #include "engine.hpp" @@ -280,7 +282,11 @@ int main(int argc, char**argv) } catch (std::exception &e) { - std::cout << "\nERROR: " << e.what() << std::endl; + if (isatty(fileno(stdin))) + std::cerr << "\nERROR: " << e.what() << std::endl; + else + SDL_ShowSimpleMessageBox(0, "OpenMW: Fatal error", e.what(), NULL); + return 1; } From 062ea627b37d099e6e5749abd3735a07943fe570 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 5 Dec 2013 15:45:39 +0100 Subject: [PATCH 10/10] Add parallax mapping for objects --- components/nifogre/material.cpp | 4 +++ files/materials/core.h | 2 +- files/materials/objects.mat | 2 ++ files/materials/objects.shader | 53 ++++++++++++++++++++------------- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/components/nifogre/material.cpp b/components/nifogre/material.cpp index 55f064c555..8398dbc2ed 100644 --- a/components/nifogre/material.cpp +++ b/components/nifogre/material.cpp @@ -334,6 +334,10 @@ Ogre::String NIFMaterialLoader::getMaterial(const Nif::ShapeData *shapedata, instance->setProperty("detailMapUVSet", sh::makeProperty(new sh::IntValue(texprop->textures[Nif::NiTexturingProperty::DetailTexture].uvSet))); } + bool useParallax = !texName[Nif::NiTexturingProperty::BumpTexture].empty() + && texName[Nif::NiTexturingProperty::BumpTexture].find("_nh.") != std::string::npos; + instance->setProperty("use_parallax", sh::makeProperty(new sh::BooleanValue(useParallax))); + for(int i = 0;i < 7;i++) { if(i == Nif::NiTexturingProperty::BaseTexture || diff --git a/files/materials/core.h b/files/materials/core.h index 6f8179c08d..a912e23562 100644 --- a/files/materials/core.h +++ b/files/materials/core.h @@ -91,7 +91,7 @@ precision mediump float; #define shSamplerCube(name) uniform samplerCube name; @shUseSampler(name) - #define shMatrixMult(m, v) (m * v) + #define shMatrixMult(m, v) ((m) * (v)) #define shOutputPosition gl_Position diff --git a/files/materials/objects.mat b/files/materials/objects.mat index ffba6e7ea8..32787e159b 100644 --- a/files/materials/objects.mat +++ b/files/materials/objects.mat @@ -12,6 +12,7 @@ material openmw_objects_base use_detail_map false emissiveMapUVSet 0 detailMapUVSet 0 + use_parallax false scene_blend default depth_write default @@ -37,6 +38,7 @@ material openmw_objects_base detailMap $detailMap env_map $env_map env_map_color $env_map_color + use_parallax $use_parallax } diffuse $diffuse diff --git a/files/materials/objects.shader b/files/materials/objects.shader index fb2b304262..5a3d872a5b 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -18,6 +18,10 @@ #define EMISSIVE_MAP @shPropertyHasValue(emissiveMap) #define DETAIL_MAP @shPropertyHasValue(detailMap) +#define PARALLAX @shPropertyBool(use_parallax) +#define PARALLAX_SCALE 0.04 +#define PARALLAX_BIAS -0.02 + // right now we support 2 UV sets max. implementing them is tedious, and we're probably not going to need more #define SECOND_UV_SET (@shPropertyString(emissiveMapUVSet) || @shPropertyString(detailMapUVSet)) @@ -265,7 +269,7 @@ shUniform(float3, env_map_color) @shUniformProperty3f(env_map_color, env_map_color) #endif -#if ENV_MAP || SPECULAR +#if ENV_MAP || SPECULAR || PARALLAX shUniform(float3, cameraPosObjSpace) @shAutoConstant(cameraPosObjSpace, camera_position_object_space) #endif #if SPECULAR @@ -345,21 +349,12 @@ SH_START_PROGRAM { + float4 newUV = UV; + #ifdef NEED_DEPTH float depthPassthrough = objSpacePositionPassthrough.w; #endif - float4 diffuse = shSample(diffuseMap, UV.xy); - shOutputColour(0) = diffuse; - -#if DETAIL_MAP -#if @shPropertyString(detailMapUVSet) - shOutputColour(0) *= shSample(detailMap, UV.zw)*2; -#else - shOutputColour(0) *= shSample(detailMap, UV.xy)*2; -#endif -#endif - #if NEED_NORMAL float3 normal = normalPassthrough; #endif @@ -372,10 +367,32 @@ tbn = transpose(tbn); #endif - float3 TSnormal = shSample(normalMap, UV.xy).xyz * 2 - 1; + float4 normalTex = shSample(normalMap, UV.xy); + + normal = normalize (shMatrixMult( transpose(tbn), normalTex.xyz * 2 - 1 )); +#endif + +#if ENV_MAP || SPECULAR || PARALLAX + float3 eyeDir = normalize(cameraPosObjSpace.xyz - objSpacePositionPassthrough.xyz); +#endif + +#if PARALLAX + float3 TSeyeDir = normalize(shMatrixMult(tbn, eyeDir)); + + newUV += (TSeyeDir.xyxy * ( normalTex.a * PARALLAX_SCALE + PARALLAX_BIAS )).xyxy; +#endif - normal = normalize (shMatrixMult( transpose(tbn), TSnormal )); + float4 diffuse = shSample(diffuseMap, newUV.xy); + shOutputColour(0) = diffuse; + +#if DETAIL_MAP +#if @shPropertyString(detailMapUVSet) + shOutputColour(0) *= shSample(detailMap, newUV.zw)*2; +#else + shOutputColour(0) *= shSample(detailMap, newUV.xy)*2; #endif +#endif + #if !VERTEX_LIGHTING float3 viewPos = shMatrixMult(worldView, float4(objSpacePositionPassthrough.xyz,1)).xyz; @@ -458,16 +475,12 @@ #if EMISSIVE_MAP #if @shPropertyString(emissiveMapUVSet) - shOutputColour(0).xyz += shSample(emissiveMap, UV.zw).xyz; + shOutputColour(0).xyz += shSample(emissiveMap, newUV.zw).xyz; #else - shOutputColour(0).xyz += shSample(emissiveMap, UV.xy).xyz; + shOutputColour(0).xyz += shSample(emissiveMap, newUV.xy).xyz; #endif #endif -#if ENV_MAP || SPECULAR - float3 eyeDir = normalize(cameraPosObjSpace.xyz - objSpacePositionPassthrough.xyz); -#endif - #if ENV_MAP // Everything looks better with fresnel float facing = 1.0 - max(abs(dot(-eyeDir, normal)), 0);