diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..f53c976772 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "extern/shiny"] + path = extern/shiny + url = git@github.com:scrawl/shiny.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cc741c678..c0b5bf4511 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,14 +20,6 @@ set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") -# Debug suffix for plugins -set(DEBUG_SUFFIX "") -if (DEFINED CMAKE_BUILD_TYPE) - if (CMAKE_BUILD_TYPE STREQUAL "Debug") - set(DEBUG_SUFFIX "_d") - endif() -endif() - # doxygen main page configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp") @@ -194,14 +186,25 @@ if (UNIX AND NOT APPLE) find_package (Threads) endif() +set(BOOST_COMPONENTS system filesystem program_options thread) + +if (Boost_VERSION LESS 104900) + set(SHINY_USE_WAVE_SYSTEM_INSTALL TRUE) + set(BOOST_COMPONENTS ${BOOST_COMPONENTS} wave) +else() + set(SHINY_USE_WAVE_SYSTEM_INSTALL FALSE) +endif() + +MESSAGE(STATUS ${BOOST_COMPONENTS}) + find_package(OGRE REQUIRED) find_package(MyGUI REQUIRED) -find_package(Boost REQUIRED COMPONENTS system filesystem program_options thread) +find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) find_package(OIS REQUIRED) find_package(OpenAL REQUIRED) find_package(Bullet REQUIRED) IF(OGRE_STATIC) -find_package(Cg REQUIRED) +find_package(Cg) IF(WIN32) set(OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_Plugin_CgProgramManager_INCLUDE_DIRS} ${OGRE_Plugin_OctreeSceneManager_INCLUDE_DIRS} ${OGRE_Plugin_ParticleFX_INCLUDE_DIRS} ${OGRE_RenderSystem_Direct3D9_INCLUDE_DIRS} ${OGRE_RenderSystem_GL_INCLUDE_DIRS}) ELSE(WIN32) @@ -230,6 +233,22 @@ if (APPLE) ${OGRE_Plugin_ParticleFX_LIBRARY_REL}) endif (APPLE) + +# Set up Ogre plugin folder & debug suffix +set(DEBUG_SUFFIX "") +if (DEFINED CMAKE_BUILD_TYPE) + if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(DEBUG_SUFFIX "_d") + add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d") + else() + add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="") + endif() +endif() +add_definitions(-DOGRE_PLUGIN_DIR_REL="${OGRE_PLUGIN_DIR_REL}") +add_definitions(-DOGRE_PLUGIN_DIR_DBG="${OGRE_PLUGIN_DIR_DBG}") +add_definitions(-DOGRE_PLUGIN_DIR="${OGRE_PLUGIN_DIR}") + + add_subdirectory(files/) add_subdirectory(files/mygui) @@ -254,15 +273,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg "${OpenMW_BINARY_DIR}/openmw.cfg.install") -if (WIN32) - configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.win32 - "${OpenMW_BINARY_DIR}/plugins.cfg" COPYONLY) -endif (WIN32) if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.linux - "${OpenMW_BINARY_DIR}/plugins.cfg") - configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop "${OpenMW_BINARY_DIR}/openmw.desktop") endif() @@ -284,13 +296,8 @@ if (APPLE) set(OGRE_PLUGIN_DIR "${OGRE_PLUGIN_DIR}/") - configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.mac - "${OpenMW_BINARY_DIR}/plugins.cfg") - set(OGRE_PLUGIN_DIR_2 ${OGRE_PLUGIN_DIR}) set(OGRE_PLUGIN_DIR "") - configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.mac - "${OpenMW_BINARY_DIR}/plugins.cfg.install") set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_2}) configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist @@ -337,7 +344,6 @@ if(DPKG_PROGRAM) INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "../etc/openmw/" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") - INSTALL(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") #Install resources INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "share/games/openmw/" FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT "Resources") @@ -354,7 +360,7 @@ if(DPKG_PROGRAM) SET(CPACK_DEBIAN_PACKAGE_NAME "openmw") SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}") SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher mwiniimporter;MWiniImporter") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "nvidia-cg-toolkit (>= 2.1), libboost-filesystem1.46.1 (>= 1.46.1), libboost-program-options1.46.1 (>= 1.46.1), libboost-system1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libboost-filesystem1.46.1 (>= 1.46.1), libboost-program-options1.46.1 (>= 1.46.1), libboost-system1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)") SET(CPACK_DEBIAN_PACKAGE_SECTION "Games") @@ -375,7 +381,6 @@ if(WIN32) INSTALL(FILES ${dll_files} DESTINATION ".") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg") INSTALL(FILES - "${OpenMW_BINARY_DIR}/plugins.cfg" "${OpenMW_SOURCE_DIR}/readme.txt" "${OpenMW_SOURCE_DIR}/GPL3.txt" "${OpenMW_SOURCE_DIR}/OFL.txt" @@ -439,6 +444,9 @@ if(WIN32) include(CPack) endif(WIN32) +# Extern +add_subdirectory (extern/shiny) + # Components add_subdirectory (components) @@ -544,7 +552,6 @@ if (APPLE) install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg.install" RENAME "plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index fb798fee89..3c1d76f3d3 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -1,6 +1,9 @@ #include +#include + #include +#include #include #include @@ -70,20 +73,13 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent) bool GraphicsPage::setupOgre() { - QString pluginCfg = mCfgMgr.getPluginsConfigPath().string().c_str(); - QFile file(pluginCfg); - // Create a log manager so we can surpress debug text to stdout/stderr Ogre::LogManager* logMgr = OGRE_NEW Ogre::LogManager; logMgr->createLog((mCfgMgr.getLogPath().string() + "/launcherOgre.log"), true, false, false); try { -#if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) mOgre = new Ogre::Root("", "", "./launcherOgre.log"); -#else - mOgre = new Ogre::Root(pluginCfg.toStdString(), "", "./launcherOgre.log"); -#endif } catch(Ogre::Exception &ex) { @@ -93,7 +89,6 @@ bool GraphicsPage::setupOgre() msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
Failed to create the Ogre::Root object

\ - Make sure the plugins.cfg is present and valid.

\ Press \"Show Details...\" for more information.
")); msgBox.setDetailedText(ogreError); msgBox.exec(); @@ -102,6 +97,32 @@ bool GraphicsPage::setupOgre() return false; } + + std::string pluginDir; + const char* pluginEnv = getenv("OPENMW_OGRE_PLUGIN_DIR"); + if (pluginEnv) + pluginDir = pluginEnv; + else + { +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + pluginDir = ".\\"; +#endif +#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE + pluginDir = OGRE_PLUGIN_DIR; +#endif +#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX + pluginDir = OGRE_PLUGIN_DIR_REL; +#endif + } + + std::string glPlugin = std::string(pluginDir) + "/RenderSystem_GL" + OGRE_PLUGIN_DEBUG_SUFFIX; + if (boost::filesystem::exists(glPlugin + ".so") || boost::filesystem::exists(glPlugin + ".dll")) + mOgre->loadPlugin (glPlugin); + + std::string dxPlugin = std::string(pluginDir) + "/RenderSystem_Direct3D9" + OGRE_PLUGIN_DEBUG_SUFFIX; + if (boost::filesystem::exists(dxPlugin + ".so") || boost::filesystem::exists(dxPlugin + ".dll")) + mOgre->loadPlugin (dxPlugin); + #ifdef ENABLE_PLUGIN_GL mGLPlugin = new Ogre::GLPlugin(); mOgre->installPlugin(mGLPlugin); diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index cf331e7dd4..8e424ad56c 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -15,7 +15,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender renderingmanager debugging sky player animation npcanimation creatureanimation actors objects - renderinginterface localmap occlusionquery terrain terrainmaterial water shadows shaderhelper + renderinginterface localmap occlusionquery terrain terrainmaterial water shadows compositors ) @@ -100,6 +100,8 @@ target_link_libraries(openmw ${BULLET_LIBRARIES} ${MYGUI_LIBRARIES} ${MYGUI_PLATFORM_LIBRARIES} + "shiny" + "shiny.OgrePlatform" components ) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 7966639a6b..96fbeb9e26 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -292,7 +292,6 @@ void OMW::Engine::go() } mOgre->configure( mCfgMgr.getLogPath().string(), - mCfgMgr.getPluginsConfigPath().string(), renderSystem, false); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 5e25d5ece5..4f8ad77c98 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -74,6 +74,14 @@ namespace return "16 : 10"; return boost::lexical_cast(xaspect) + " : " + boost::lexical_cast(yaspect); } + + std::string hlslGlsl () + { + if (Ogre::Root::getSingleton ().getRenderSystem ()->getName ().find("OpenGL") == std::string::npos) + return "hlsl"; + else + return "glsl"; + } } namespace MWGui @@ -103,8 +111,19 @@ namespace MWGui getWidget(mReflectObjectsButton, "ReflectObjectsButton"); getWidget(mReflectActorsButton, "ReflectActorsButton"); getWidget(mReflectTerrainButton, "ReflectTerrainButton"); + getWidget(mShadersButton, "ShadersButton"); + getWidget(mShadowsEnabledButton, "ShadowsEnabledButton"); + getWidget(mShadowsLargeDistance, "ShadowsLargeDistance"); + getWidget(mShadowsTextureSize, "ShadowsTextureSize"); + getWidget(mActorShadows, "ActorShadows"); + getWidget(mStaticsShadows, "StaticsShadows"); + getWidget(mMiscShadows, "MiscShadows"); + getWidget(mShadowsDebug, "ShadowsDebug"); + getWidget(mUnderwaterButton, "UnderwaterButton"); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); + mUnderwaterButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mShadersButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShadersToggled); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mWaterShaderButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mReflectObjectsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -120,6 +139,14 @@ namespace MWGui mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mShadowsEnabledButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mShadowsLargeDistance->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mShadowsTextureSize->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShadowTextureSize); + mActorShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mStaticsShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mMiscShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mShadowsDebug->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + mMasterVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mVoiceVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mEffectsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); @@ -172,7 +199,6 @@ namespace MWGui std::string tf = Settings::Manager::getString("texture filtering", "General"); mTextureFilteringButton->setCaption(textureFilteringToStr(tf)); mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast(Settings::Manager::getInt("anisotropy", "General")) + ")"); - mAnisotropyBox->setVisible(tf == "anisotropic"); float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-sViewDistMin)/(sViewDistMax-sViewDistMin); int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val; @@ -185,9 +211,27 @@ namespace MWGui mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1)); mWaterShaderButton->setCaptionWithReplacing(Settings::Manager::getBool("shader", "Water") ? "#{sOn}" : "#{sOff}"); - mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect objects", "Water") ? "#{sOn}" : "#{sOff}"); + mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect statics", "Water") ? "#{sOn}" : "#{sOff}"); mReflectActorsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect actors", "Water") ? "#{sOn}" : "#{sOff}"); mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "Water") ? "#{sOn}" : "#{sOff}"); + mUnderwaterButton->setCaptionWithReplacing(Settings::Manager::getBool("underwater effect", "Water") ? "#{sOn}" : "#{sOff}"); + + mShadowsTextureSize->setCaption (Settings::Manager::getString ("texture size", "Shadows")); + mShadowsLargeDistance->setCaptionWithReplacing(Settings::Manager::getBool("split", "Shadows") ? "#{sOn}" : "#{sOff}"); + mShadowsEnabledButton->setCaptionWithReplacing(Settings::Manager::getBool("enabled", "Shadows") ? "#{sOn}" : "#{sOff}"); + mActorShadows->setCaptionWithReplacing(Settings::Manager::getBool("actor shadows", "Shadows") ? "#{sOn}" : "#{sOff}"); + mStaticsShadows->setCaptionWithReplacing(Settings::Manager::getBool("statics shadows", "Shadows") ? "#{sOn}" : "#{sOff}"); + mMiscShadows->setCaptionWithReplacing(Settings::Manager::getBool("misc shadows", "Shadows") ? "#{sOn}" : "#{sOff}"); + mShadowsDebug->setCaptionWithReplacing(Settings::Manager::getBool("debug", "Shadows") ? "#{sOn}" : "#{sOff}"); + + std::string shaders; + if (!Settings::Manager::getBool("shaders", "Objects")) + shaders = "off"; + else + { + shaders = Settings::Manager::getString("shader mode", "General"); + } + mShadersButton->setCaption (shaders); if (!MWRender::RenderingManager::waterShaderSupported()) { @@ -237,6 +281,25 @@ namespace MWGui mResolutionList->setIndexSelected(MyGUI::ITEM_NONE); } + void SettingsWindow::onShadowTextureSize(MyGUI::Widget* _sender) + { + std::string size = mShadowsTextureSize->getCaption(); + + if (size == "512") + size = "1024"; + else if (size == "1024") + size = "2048"; + else if (size == "2048") + size = "4096"; + else + size = "512"; + + mShadowsTextureSize->setCaption(size); + + Settings::Manager::setString("texture size", "Shadows", size); + apply(); + } + void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender) { std::string on = mWindowManager.getGameSettingString("sOn", "On"); @@ -291,6 +354,10 @@ namespace MWGui { if (_sender == mWaterShaderButton) Settings::Manager::setBool("shader", "Water", newState); + else if (_sender == mUnderwaterButton) + { + Settings::Manager::setBool("underwater effect", "Water", newState); + } else if (_sender == mReflectObjectsButton) { Settings::Manager::setBool("reflect misc", "Water", newState); @@ -301,11 +368,68 @@ namespace MWGui Settings::Manager::setBool("reflect actors", "Water", newState); else if (_sender == mReflectTerrainButton) Settings::Manager::setBool("reflect terrain", "Water", newState); + else if (_sender == mShadowsEnabledButton) + Settings::Manager::setBool("enabled", "Shadows", newState); + else if (_sender == mShadowsLargeDistance) + Settings::Manager::setBool("split", "Shadows", newState); + else if (_sender == mActorShadows) + Settings::Manager::setBool("actor shadows", "Shadows", newState); + else if (_sender == mStaticsShadows) + Settings::Manager::setBool("statics shadows", "Shadows", newState); + else if (_sender == mMiscShadows) + Settings::Manager::setBool("misc shadows", "Shadows", newState); + else if (_sender == mShadowsDebug) + Settings::Manager::setBool("debug", "Shadows", newState); apply(); } } + void SettingsWindow::onShadersToggled(MyGUI::Widget* _sender) + { + std::string val = static_cast(_sender)->getCaption(); + if (val == "off") + val = hlslGlsl(); + else if (val == hlslGlsl()) + val = "cg"; + else + val = "off"; + + static_cast(_sender)->setCaption(val); + + if (val == "off") + { + Settings::Manager::setBool("shaders", "Objects", false); + + // water shader not supported with object shaders off + mWaterShaderButton->setCaptionWithReplacing("#{sOff}"); + mWaterShaderButton->setEnabled(false); + mReflectObjectsButton->setEnabled(false); + mReflectActorsButton->setEnabled(false); + mReflectTerrainButton->setEnabled(false); + Settings::Manager::setBool("shader", "Water", false); + + // shadows not supported + mShadowsEnabledButton->setEnabled(false); + mShadowsEnabledButton->setCaptionWithReplacing("#{sOff}"); + Settings::Manager::setBool("enabled", "Shadows", false); + } + else + { + // re-enable + mWaterShaderButton->setEnabled(true); + mReflectObjectsButton->setEnabled(true); + mReflectActorsButton->setEnabled(true); + mReflectTerrainButton->setEnabled(true); + mShadowsEnabledButton->setEnabled(true); + + Settings::Manager::setBool("shaders", "Objects", true); + Settings::Manager::setString("shader mode", "General", val); + } + + apply(); + } + void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender) { int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 3; @@ -328,7 +452,6 @@ namespace MWGui next = "none"; mTextureFilteringButton->setCaption(textureFilteringToStr(next)); - mAnisotropyBox->setVisible(next == "anisotropic"); Settings::Manager::setString("texture filtering", "General", next); apply(); diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index e3827c7b03..63fbed46b6 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -42,6 +42,16 @@ namespace MWGui MyGUI::Button* mReflectObjectsButton; MyGUI::Button* mReflectActorsButton; MyGUI::Button* mReflectTerrainButton; + MyGUI::Button* mShadersButton; + MyGUI::Button* mUnderwaterButton; + + MyGUI::Button* mShadowsEnabledButton; + MyGUI::Button* mShadowsLargeDistance; + MyGUI::Button* mShadowsTextureSize; + MyGUI::Button* mActorShadows; + MyGUI::Button* mStaticsShadows; + MyGUI::Button* mMiscShadows; + MyGUI::Button* mShadowsDebug; // audio MyGUI::ScrollBar* mMasterVolumeSlider; @@ -59,6 +69,9 @@ namespace MWGui void onResolutionAccept(); void onResolutionCancel(); + void onShadersToggled(MyGUI::Widget* _sender); + void onShadowTextureSize(MyGUI::Widget* _sender); + void apply(); }; } diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index dd0351721c..962f19a57f 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -229,7 +229,7 @@ void LocalMap::render(const float x, const float y, vp->setVisibilityMask(RV_Map); // use fallback techniques without shadows and without mrt - vp->setMaterialScheme("Fallback"); + vp->setMaterialScheme("local_map"); rtt->update(); diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index fb2bfb3c5e..b3457a5fae 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -450,3 +450,18 @@ void Objects::update(const float dt) it = mLights.erase(it); } } + +void Objects::rebuildStaticGeometry() +{ + for (std::map::iterator it = mStaticGeometry.begin(); it != mStaticGeometry.end(); ++it) + { + it->second->destroy(); + it->second->build(); + } + + for (std::map::iterator it = mStaticGeometrySmall.begin(); it != mStaticGeometrySmall.end(); ++it) + { + it->second->destroy(); + it->second->build(); + } +} diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp index e240b11c9e..443f25ecf3 100644 --- a/apps/openmw/mwrender/objects.hpp +++ b/apps/openmw/mwrender/objects.hpp @@ -93,6 +93,8 @@ public: void removeCell(MWWorld::CellStore* store); void buildStaticGeometry(MWWorld::CellStore &cell); void setMwRoot(Ogre::SceneNode* root); + + void rebuildStaticGeometry(); }; } #endif diff --git a/apps/openmw/mwrender/renderconst.hpp b/apps/openmw/mwrender/renderconst.hpp index c4aa093c0d..9f57833bb7 100644 --- a/apps/openmw/mwrender/renderconst.hpp +++ b/apps/openmw/mwrender/renderconst.hpp @@ -14,14 +14,14 @@ enum RenderQueueGroups RQG_Main = Ogre::RENDER_QUEUE_MAIN, + RQG_Alpha = Ogre::RENDER_QUEUE_MAIN+1, + + RQG_OcclusionQuery = Ogre::RENDER_QUEUE_6, + + RQG_UnderWater = Ogre::RENDER_QUEUE_4, + RQG_Water = Ogre::RENDER_QUEUE_7+1, - RQG_Alpha = Ogre::RENDER_QUEUE_MAIN, - - RQG_UnderWater = Ogre::RENDER_QUEUE_7+1, - - RQG_OcclusionQuery = Ogre::RENDER_QUEUE_8, - // Sky late (sun & sun flare) RQG_SkiesLate = Ogre::RENDER_QUEUE_SKIES_LATE }; @@ -49,12 +49,12 @@ enum VisibilityFlags RV_Sky = 64, - // Sun glare (not visible in reflection) - RV_Glare = 128, + // not visible in reflection + RV_NoReflection = 128, RV_OcclusionQuery = 256, - RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water, + RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water /// \todo markers (normally hidden) }; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 5b76f5ae21..852288d146 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -14,6 +14,9 @@ #include #include +#include +#include + #include #include @@ -27,7 +30,6 @@ #include "../mwinput/inputmanager.hpp" // FIXME #include "shadows.hpp" -#include "shaderhelper.hpp" #include "localmap.hpp" #include "water.hpp" #include "compositors.hpp" @@ -40,6 +42,15 @@ namespace MWRender { RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine) :mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0) { + // select best shader mode + if (Settings::Manager::getString("shader mode", "General") == "") + { + if (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") == std::string::npos) + Settings::Manager::setString("shader mode", "General", "hlsl"); + else + Settings::Manager::setString("shader mode", "General", "glsl"); + } + mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5); mRendering.setWindowEventListener(this); @@ -47,6 +58,21 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mWater = 0; + // material system + sh::OgrePlatform* platform = new sh::OgrePlatform("General", (resDir / "materials").string()); + platform->setCacheFolder ("./"); + mFactory = new sh::Factory(platform); + + sh::Language lang; + std::string l = Settings::Manager::getString("shader mode", "General"); + if (l == "glsl") + lang = sh::Language_GLSL; + else if (l == "hlsl") + lang = sh::Language_HLSL; + else + lang = sh::Language_CG; + mFactory->setCurrentLanguage (lang); + //The fog type must be set before any terrain objects are created as if the //fog type is set to FOG_NONE then the initially created terrain won't have any fog configureFog(1, ColourValue(1,1,1)); @@ -68,18 +94,26 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const // Load resources ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); - // Due to the huge world size of MW, we'll want camera-relative rendering. - // This prevents precision artifacts when moving very far from the origin. - mRendering.getScene()->setCameraRelativeRendering(true); + // causes light flicker in opengl when moving.. + //mRendering.getScene()->setCameraRelativeRendering(true); // disable unsupported effects - const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); + //const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); if (!waterShaderSupported()) Settings::Manager::setBool("shader", "Water", false); - if ( !(caps->isShaderProfileSupported("fp40") || caps->isShaderProfileSupported("ps_4_0")) - || !Settings::Manager::getBool("shaders", "Objects")) + if (!Settings::Manager::getBool("shaders", "Objects")) Settings::Manager::setBool("enabled", "Shadows", false); + sh::Factory::getInstance ().setGlobalSetting ("mrt_output", useMRT() ? "true" : "false"); + sh::Factory::getInstance ().setGlobalSetting ("fog", "true"); + sh::Factory::getInstance ().setGlobalSetting ("lighting", "true"); + sh::Factory::getInstance ().setGlobalSetting ("num_lights", Settings::Manager::getString ("num lights", "Objects")); + sh::Factory::getInstance ().setGlobalSetting ("underwater_effects", Settings::Manager::getString("underwater effect", "Water")); + sh::Factory::getInstance ().setGlobalSetting ("simple_water", Settings::Manager::getBool("shader", "Water") ? "false" : "true"); + + sh::Factory::getInstance ().setSharedParameter ("viewportBackground", sh::makeProperty (new sh::Vector3(0,0,0))); + sh::Factory::getInstance ().setSharedParameter ("waterEnabled", sh::makeProperty (new sh::FloatValue(0.0))); + applyCompositors(); // Turn the entire scene (represented by the 'root' node) -90 @@ -100,7 +134,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const cameraPitchNode->attachObject(mRendering.getCamera()); mShadows = new Shadows(&mRendering); - mShaderHelper = new ShaderHelper(this); mTerrainManager = new TerrainManager(mRendering.getScene(), this); @@ -124,7 +157,6 @@ RenderingManager::~RenderingManager () delete mPlayer; delete mSkyManager; delete mDebugging; - delete mShaderHelper; delete mShadows; delete mTerrainManager; delete mLocalMap; @@ -237,7 +269,7 @@ void RenderingManager::update (float duration){ checkUnderwater(); - mWater->update(); + mWater->update(duration); } void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){ if(store->cell->data.flags & store->cell->HasWater @@ -350,11 +382,9 @@ void RenderingManager::configureFog(const float density, const Ogre::ColourValue mRendering.getCamera()->setFarClipDistance ( max / density ); mRendering.getViewport()->setBackgroundColour (colour); - CompositorInstance* inst = CompositorManager::getSingleton().getCompositorChain(mRendering.getViewport())->getCompositor("gbuffer"); - if (inst != 0) - inst->getCompositor()->getTechnique(0)->getTargetPass(0)->getPass(0)->setClearColour(colour); - if (mWater) - mWater->setViewportBackground(colour); + sh::Factory::getInstance ().setSharedParameter ("viewportBackground", + sh::makeProperty (new sh::Vector3(colour.r, colour.g, colour.b))); + } @@ -517,12 +547,14 @@ Shadows* RenderingManager::getShadows() void RenderingManager::switchToInterior() { - mRendering.getScene()->setCameraRelativeRendering(false); + // causes light flicker in opengl when moving.. + //mRendering.getScene()->setCameraRelativeRendering(false); } void RenderingManager::switchToExterior() { - mRendering.getScene()->setCameraRelativeRendering(true); + // causes light flicker in opengl when moving.. + //mRendering.getScene()->setCameraRelativeRendering(true); } Ogre::Vector4 RenderingManager::boundingBoxToScreen(Ogre::AxisAlignedBox bounds) @@ -607,7 +639,38 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec else if (it->second == "shader" && it->first == "Water") { applyCompositors(); - mShaderHelper->applyShaders(); + sh::Factory::getInstance ().setGlobalSetting ("mrt_output", useMRT() ? "true" : "false"); + sh::Factory::getInstance ().setGlobalSetting ("simple_water", Settings::Manager::getBool("shader", "Water") ? "false" : "true"); + mObjects.rebuildStaticGeometry (); + } + else if (it->second == "underwater effect" && it->first == "Water") + { + sh::Factory::getInstance ().setGlobalSetting ("underwater_effects", Settings::Manager::getString("underwater effect", "Water")); + mObjects.rebuildStaticGeometry (); + } + else if (it->second == "shaders" && it->first == "Objects") + { + sh::Factory::getInstance ().setShadersEnabled (Settings::Manager::getBool("shaders", "Objects")); + mObjects.rebuildStaticGeometry (); + } + else if (it->second == "shader mode" && it->first == "General") + { + sh::Language lang; + std::string l = Settings::Manager::getString("shader mode", "General"); + if (l == "glsl") + lang = sh::Language_GLSL; + else if (l == "hlsl") + lang = sh::Language_HLSL; + else + lang = sh::Language_CG; + sh::Factory::getInstance ().setCurrentLanguage (lang); + mObjects.rebuildStaticGeometry (); + } + else if (it->first == "Shadows") + { + mShadows->recreate (); + + mObjects.rebuildStaticGeometry (); } } @@ -671,14 +734,9 @@ void RenderingManager::applyCompositors() { mCompositors->addCompositor("gbuffer", 0); mCompositors->setCompositorEnabled("gbuffer", true); - mCompositors->addCompositor("Underwater", 1); mCompositors->addCompositor("gbufferFinalizer", 2); mCompositors->setCompositorEnabled("gbufferFinalizer", true); } - else - { - mCompositors->addCompositor("UnderwaterNoMRT", 0); - } if (mWater) mWater->assignTextures(); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index c30f529793..d6a372d102 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -32,10 +32,14 @@ namespace MWWorld class CellStore; } +namespace sh +{ + class Factory; +} + namespace MWRender { class Shadows; - class ShaderHelper; class LocalMap; class Water; class Compositors; @@ -162,6 +166,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList private: + sh::Factory* mFactory; + void setAmbientMode(); void setMenuTransparency(float val); @@ -204,8 +210,6 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList MWRender::Shadows* mShadows; - MWRender::ShaderHelper* mShaderHelper; - MWRender::Compositors* mCompositors; }; diff --git a/apps/openmw/mwrender/shaderhelper.cpp b/apps/openmw/mwrender/shaderhelper.cpp deleted file mode 100644 index 1f9086db45..0000000000 --- a/apps/openmw/mwrender/shaderhelper.cpp +++ /dev/null @@ -1,309 +0,0 @@ -#include "shaderhelper.hpp" -#include "renderingmanager.hpp" -#include "shadows.hpp" - -#include -#include -#include -#include - -#include - -using namespace Ogre; -using namespace MWRender; - -ShaderHelper::ShaderHelper(RenderingManager* rend) -{ - mRendering = rend; - applyShaders(); -} - -void ShaderHelper::applyShaders() -{ - if (!Settings::Manager::getBool("shaders", "Objects")) return; - - bool mrt = RenderingManager::useMRT(); - bool shadows = Settings::Manager::getBool("enabled", "Shadows"); - bool split = Settings::Manager::getBool("split", "Shadows"); - - // shader for normal rendering - createShader(mrt, shadows, split, "main"); - - // fallback shader without mrt and without shadows - // (useful for reflection and for minimap) - createShader(false, false, false, "main_fallback"); -} - -void ShaderHelper::createShader(const bool mrt, const bool shadows, const bool split, const std::string& name) -{ - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - - const int numsplits = 3; - - // the number of lights to support. - // when rendering an object, OGRE automatically picks the lights that are - // closest to the object being rendered. unfortunately this mechanism does - // not work perfectly for objects batched together (they will all use the same - // lights). to work around this, we are simply pushing the maximum number - // of lights here in order to minimize disappearing lights. - int num_lights = Settings::Manager::getInt("num lights", "Objects"); - - { - // vertex - HighLevelGpuProgramPtr vertex; - if (!mgr.getByName(name+"_vp").isNull()) - mgr.remove(name+"_vp"); - - vertex = mgr.createProgram(name+"_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_VERTEX_PROGRAM); - vertex->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1"); - vertex->setParameter("entry_point", "main_vp"); - StringUtil::StrStreamType outStream; - outStream << - "void main_vp( \n" - " float4 position : POSITION, \n" - " float4 normal : NORMAL, \n" - " float4 colour : COLOR, \n" - " in float2 uv : TEXCOORD0, \n" - " out float2 oUV : TEXCOORD0, \n" - " out float4 oPosition : POSITION, \n" - " out float4 oPositionObjSpace : TEXCOORD1, \n" - " out float4 oNormal : TEXCOORD2, \n" - " out float oDepth : TEXCOORD3, \n" - " out float4 oVertexColour : TEXCOORD4, \n"; - if (shadows && !split) outStream << - " out float4 oLightSpacePos0 : TEXCOORD5, \n" - " uniform float4x4 worldMatrix, \n" - " uniform float4x4 texViewProjMatrix0, \n"; - else - { - for (int i=0; isetSource(outStream.str()); - vertex->load(); - vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - if (shadows) - { - vertex->getDefaultParameters()->setNamedAutoConstant("worldMatrix", GpuProgramParameters::ACT_WORLD_MATRIX); - if (!split) - vertex->getDefaultParameters()->setNamedAutoConstant("texViewProjMatrix0", GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, 0); - else - { - for (int i=0; igetDefaultParameters()->setNamedAutoConstant("texViewProjMatrix"+StringConverter::toString(i), GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i); - } - } - } - } - - { - // fragment - HighLevelGpuProgramPtr fragment; - if (!mgr.getByName(name+"_fp").isNull()) - mgr.remove(name+"_fp"); - - fragment = mgr.createProgram(name+"_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_FRAGMENT_PROGRAM); - fragment->setParameter("profiles", "ps_4_0 ps_2_x fp40 arbfp1"); - fragment->setParameter("entry_point", "main_fp"); - StringUtil::StrStreamType outStream; - - if (shadows) outStream << - "float depthShadow(sampler2D shadowMap, float4 shadowMapPos, float2 offset) \n" - "{ \n" - " shadowMapPos /= shadowMapPos.w; \n" - " float3 o = float3(offset.xy, -offset.x) * 0.3f; \n" - " float c = (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy - o.xy).r) ? 1 : 0; // top left \n" - " c += (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy + o.xy).r) ? 1 : 0; // bottom right \n" - " c += (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy + o.zy).r) ? 1 : 0; // bottom left \n" - " c += (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy - o.zy).r) ? 1 : 0; // top right \n" - " return c / 4; \n" - "} \n"; - - outStream << - "void main_fp( \n" - " in float2 uv : TEXCOORD0, \n" - " out float4 oColor : COLOR, \n" - " uniform sampler2D texture : register(s0), \n" - " float4 positionObjSpace : TEXCOORD1, \n" - " float4 normal : TEXCOORD2, \n" - " float iDepth : TEXCOORD3, \n" - " float4 vertexColour : TEXCOORD4, \n" - " uniform float4 fogColour, \n" - " uniform float4 fogParams, \n"; - - if (shadows) outStream << - " uniform float4 shadowFar_fadeStart, \n"; - - if (shadows && !split) outStream << - " uniform sampler2D shadowMap : register(s1), \n" - " float4 lightSpacePos0 : TEXCOORD5, \n" - " uniform float4 invShadowmapSize0, \n"; - else - { - outStream << - " uniform float4 pssmSplitPoints, \n"; - for (int i=0; i shadowFar_fadeStart.x) ? 1 : ((iDepth > shadowFar_fadeStart.y) ? 1-((1-shadow)*fade) : shadow); \n" - " lightColour.xyz += shadow * lit(dot(normalize(lightDir), normalize(normal)), 0, 0).y * lightDiffuse"<setSource(outStream.str()); - fragment->load(); - - for (int i=0; igetDefaultParameters()->setNamedAutoConstant("lightPositionObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i); - fragment->getDefaultParameters()->setNamedAutoConstant("lightDiffuse"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i); - fragment->getDefaultParameters()->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i); - } - fragment->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); - fragment->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); - fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR); - fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR); - fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR); - fragment->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS); - - if (shadows) - { - fragment->getDefaultParameters()->setNamedConstant("shadowFar_fadeStart", Vector4(mRendering->getShadows()->getShadowFar(), mRendering->getShadows()->getFadeStart()*mRendering->getShadows()->getShadowFar(), 0, 0)); - for (int i=0; i < (split ? numsplits : 1); ++i) - { - fragment->getDefaultParameters()->setNamedAutoConstant("invShadowmapSize" + StringConverter::toString(i), GpuProgramParameters::ACT_INVERSE_TEXTURE_SIZE, i+1); - } - if (split) - { - Vector4 splitPoints; - const PSSMShadowCameraSetup::SplitPointList& splitPointList = mRendering->getShadows()->getPSSMSetup()->getSplitPoints(); - // Populate from split point 1, not 0, since split 0 isn't useful (usually 0) - for (int i = 1; i < numsplits; ++i) - { - splitPoints[i-1] = splitPointList[i]; - } - fragment->getDefaultParameters()->setNamedConstant("pssmSplitPoints", splitPoints); - } - } - - if (mrt) - fragment->getDefaultParameters()->setNamedAutoConstant("far", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE); - } -} diff --git a/apps/openmw/mwrender/shaderhelper.hpp b/apps/openmw/mwrender/shaderhelper.hpp deleted file mode 100644 index 356d345deb..0000000000 --- a/apps/openmw/mwrender/shaderhelper.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef GAME_SHADERHELPER_H -#define GAME_SHADERHELPER_H - -#include - -namespace MWRender -{ - class RenderingManager; - - /// - /// \brief manages the main shader - /// - class ShaderHelper - { - public: - ShaderHelper(RenderingManager* rend); - - void applyShaders(); - ///< apply new settings - - private: - RenderingManager* mRendering; - - void createShader(const bool mrt, const bool shadows, const bool split, const std::string& name); - }; - -} - -#endif diff --git a/apps/openmw/mwrender/shadows.cpp b/apps/openmw/mwrender/shadows.cpp index 9a4ae7243c..3d9f132435 100644 --- a/apps/openmw/mwrender/shadows.cpp +++ b/apps/openmw/mwrender/shadows.cpp @@ -12,6 +12,8 @@ #include #include +#include + #include "renderconst.hpp" using namespace Ogre; @@ -34,6 +36,9 @@ void Shadows::recreate() bool split = Settings::Manager::getBool("split", "Shadows"); //const bool split = false; + sh::Factory::getInstance ().setGlobalSetting ("shadows", enabled && !split ? "true" : "false"); + sh::Factory::getInstance ().setGlobalSetting ("shadows_pssm", enabled && split ? "true" : "false"); + if (!enabled) { mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE); @@ -53,7 +58,7 @@ void Shadows::recreate() mSceneMgr->setShadowTextureSelfShadow(true); mSceneMgr->setShadowCasterRenderBackFaces(true); - mSceneMgr->setShadowTextureCasterMaterial("depth_shadow_caster"); + mSceneMgr->setShadowTextureCasterMaterial("openmw_shadowcaster_default"); mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R); mSceneMgr->setShadowDirectionalLightExtrusionDistance(1000000); @@ -84,18 +89,27 @@ void Shadows::recreate() mSceneMgr->setShadowTextureConfig(i, texsize/4, texsize/4, Ogre::PF_FLOAT32_R);*/ } + // Populate from split point 1, not 0, since split 0 isn't useful (usually 0) + const PSSMShadowCameraSetup::SplitPointList& splitPointList = getPSSMSetup()->getSplitPoints(); + sh::Vector3* splitPoints = new sh::Vector3(splitPointList[1], splitPointList[2], splitPointList[3]); + + sh::Factory::getInstance ().setSharedParameter ("pssmSplitPoints", sh::makeProperty(splitPoints)); + shadowCameraSetup = ShadowCameraSetupPtr(mPSSMSetup); } else { LiSPSMShadowCameraSetup* lispsmSetup = new LiSPSMShadowCameraSetup(); - lispsmSetup->setOptimalAdjustFactor(2); + lispsmSetup->setOptimalAdjustFactor(64); //lispsmSetup->setCameraLightDirectionThreshold(Degree(0)); //lispsmSetup->setUseAggressiveFocusRegion(false); shadowCameraSetup = ShadowCameraSetupPtr(lispsmSetup); } mSceneMgr->setShadowCameraSetup(shadowCameraSetup); + sh::Vector4* shadowFar_fadeStart = new sh::Vector4(mShadowFar, mFadeStart * mShadowFar, 0, 0); + sh::Factory::getInstance ().setSharedParameter ("shadowFar_fadeStart", sh::makeProperty(shadowFar_fadeStart)); + // Set visibility mask for the shadow render textures int visibilityMask = RV_Actors * Settings::Manager::getBool("actor shadows", "Shadows") + (RV_Statics + RV_StaticsSmall) * Settings::Manager::getBool("statics shadows", "Shadows") @@ -111,53 +125,62 @@ void Shadows::recreate() // -------------------------------------------------------------------------------------------------------------------- // --------------------------- Debug overlays to display the content of shadow maps ----------------------------------- // -------------------------------------------------------------------------------------------------------------------- - /* - OverlayManager& mgr = OverlayManager::getSingleton(); - Overlay* overlay; - - // destroy if already exists - if (overlay = mgr.getByName("DebugOverlay")) - mgr.destroy(overlay); - - overlay = mgr.create("DebugOverlay"); - for (size_t i = 0; i < (split ? 3 : 1); ++i) { - TexturePtr tex = mRendering->getScene()->getShadowTexture(i); - - // Set up a debug panel to display the shadow - - if (MaterialManager::getSingleton().resourceExists("Ogre/DebugTexture" + StringConverter::toString(i))) - MaterialManager::getSingleton().remove("Ogre/DebugTexture" + StringConverter::toString(i)); - MaterialPtr debugMat = MaterialManager::getSingleton().create( - "Ogre/DebugTexture" + StringConverter::toString(i), - ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - - debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false); - TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName()); - t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); + if (Settings::Manager::getBool("debug", "Shadows")) + { + OverlayManager& mgr = OverlayManager::getSingleton(); + Overlay* overlay; - OverlayContainer* debugPanel; - - // destroy container if exists - try - { - if (debugPanel = - static_cast( - mgr.getOverlayElement("Ogre/DebugTexPanel" + StringConverter::toString(i) - ))) - mgr.destroyOverlayElement(debugPanel); - } - catch (Ogre::Exception&) {} - - debugPanel = (OverlayContainer*) - (OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugTexPanel" + StringConverter::toString(i))); - debugPanel->_setPosition(0.8, i*0.25); - debugPanel->_setDimensions(0.2, 0.24); - debugPanel->setMaterialName(debugMat->getName()); - debugPanel->show(); - overlay->add2D(debugPanel); - overlay->show(); - } - */ + // destroy if already exists + if ((overlay = mgr.getByName("DebugOverlay"))) + mgr.destroy(overlay); + + overlay = mgr.create("DebugOverlay"); + for (size_t i = 0; i < (split ? 3 : 1); ++i) { + TexturePtr tex = mRendering->getScene()->getShadowTexture(i); + + // Set up a debug panel to display the shadow + + if (MaterialManager::getSingleton().resourceExists("Ogre/DebugTexture" + StringConverter::toString(i))) + MaterialManager::getSingleton().remove("Ogre/DebugTexture" + StringConverter::toString(i)); + MaterialPtr debugMat = MaterialManager::getSingleton().create( + "Ogre/DebugTexture" + StringConverter::toString(i), + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + + debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false); + TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName()); + t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); + + OverlayContainer* debugPanel; + + // destroy container if exists + try + { + if ((debugPanel = + static_cast( + mgr.getOverlayElement("Ogre/DebugTexPanel" + StringConverter::toString(i) + )))) + mgr.destroyOverlayElement(debugPanel); + } + catch (Ogre::Exception&) {} + + debugPanel = (OverlayContainer*) + (OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugTexPanel" + StringConverter::toString(i))); + debugPanel->_setPosition(0.8, i*0.25); + debugPanel->_setDimensions(0.2, 0.24); + debugPanel->setMaterialName(debugMat->getName()); + debugPanel->show(); + overlay->add2D(debugPanel); + overlay->show(); + } + } + else + { + OverlayManager& mgr = OverlayManager::getSingleton(); + Overlay* overlay; + + if ((overlay = mgr.getByName("DebugOverlay"))) + mgr.destroy(overlay); + } } PSSMShadowCameraSetup* Shadows::getPSSMSetup() diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 45e48240b4..2a2df79437 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -15,8 +15,12 @@ #include #include +#include + #include +#include + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -29,15 +33,51 @@ using namespace Ogre; BillboardObject::BillboardObject( const String& textureName, const float initialSize, const Vector3& position, - SceneNode* rootNode) + SceneNode* rootNode, + const std::string& material) { - init(textureName, initialSize, position, rootNode); + SceneManager* sceneMgr = rootNode->getCreator(); + + Vector3 finalPosition = position.normalisedCopy() * 1000.f; + + static unsigned int bodyCount=0; + + /// \todo These billboards are not 100% correct, might want to revisit them later + mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1); + mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize); + mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON); + mBBSet->setCommonDirection( -position.normalisedCopy() ); + mBBSet->setVisibilityFlags(RV_Sky); + mNode = rootNode->createChildSceneNode(); + mNode->setPosition(finalPosition); + mNode->attachObject(mBBSet); + mBBSet->createBillboard(0,0,0); + mBBSet->setCastShadows(false); + + mMaterial = sh::Factory::getInstance().createMaterialInstance ("BillboardMaterial"+StringConverter::toString(bodyCount), material); + mMaterial->setProperty("texture", sh::makeProperty(new sh::StringValue(textureName))); + + sh::Factory::getInstance().getMaterialInstance ("BillboardMaterial"+StringConverter::toString(bodyCount))->setListener(this); + + mBBSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount)); + + bodyCount++; } BillboardObject::BillboardObject() { } +void BillboardObject::requestedConfiguration (sh::MaterialInstance* m, const std::string& configuration) +{ +} + +void BillboardObject::createdConfiguration (sh::MaterialInstance* m, const std::string& configuration) +{ + setVisibility(mVisibility); + setColour(mColour); +} + void BillboardObject::setVisible(const bool visible) { mBBSet->setVisible(visible); @@ -50,7 +90,14 @@ void BillboardObject::setSize(const float size) void BillboardObject::setVisibility(const float visibility) { - mMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, visibility); + mVisibility = visibility; + Ogre::MaterialPtr m = static_cast(mMaterial->getMaterial ())->getOgreMaterial (); + for (int i=0; igetNumTechniques(); ++i) + { + Ogre::Technique* t = m->getTechnique(i); + if (t->getNumPasses ()) + t->getPass(0)->setDiffuse (0,0,0, visibility); + } } void BillboardObject::setPosition(const Vector3& pPosition) @@ -76,7 +123,14 @@ void BillboardObject::setVisibilityFlags(int flags) void BillboardObject::setColour(const ColourValue& pColour) { - mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour); + mColour = pColour; + Ogre::MaterialPtr m = static_cast(mMaterial->getMaterial ())->getOgreMaterial (); + for (int i=0; igetNumTechniques(); ++i) + { + Ogre::Technique* t = m->getTechnique(i); + if (t->getNumPasses ()) + t->getPass(0)->setSelfIllumination (pColour); + } } void BillboardObject::setRenderQueue(unsigned int id) @@ -89,178 +143,13 @@ SceneNode* BillboardObject::getNode() return mNode; } -void BillboardObject::init(const String& textureName, - const float initialSize, - const Vector3& position, - SceneNode* rootNode) -{ - SceneManager* sceneMgr = rootNode->getCreator(); - - Vector3 finalPosition = position.normalisedCopy() * 1000.f; - - static unsigned int bodyCount=0; - - /// \todo These billboards are not 100% correct, might want to revisit them later - mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1); - mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize); - mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON); - mBBSet->setCommonDirection( -position.normalisedCopy() ); - mBBSet->setVisibilityFlags(RV_Sky); - mNode = rootNode->createChildSceneNode(); - mNode->setPosition(finalPosition); - mNode->attachObject(mBBSet); - mBBSet->createBillboard(0,0,0); - mBBSet->setCastShadows(false); - - mMaterial = MaterialManager::getSingleton().create("BillboardMaterial"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - mMaterial->removeAllTechniques(); - Pass* p = mMaterial->createTechnique()->createPass(); - p->setSceneBlending(SBT_TRANSPARENT_ALPHA); - p->setDepthCheckEnabled(false); - p->setDepthWriteEnabled(false); - p->setSelfIllumination(1.0,1.0,1.0); - p->setDiffuse(0.0,0.0,0.0,1.0); - p->setAmbient(0.0,0.0,0.0); - p->setPolygonModeOverrideable(false); - p->createTextureUnitState(textureName); - mBBSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount)); - - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - HighLevelGpuProgramPtr vshader; - if (mgr.resourceExists("BBO_VP")) - vshader = mgr.getByName("BBO_VP"); - else - vshader = mgr.createProgram("BBO_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); - vshader->setParameter("profiles", "vs_2_x arbvp1"); - vshader->setParameter("entry_point", "main_vp"); - StringUtil::StrStreamType outStream; - outStream << - "void main_vp( \n" - " float4 position : POSITION, \n" - " in float2 uv : TEXCOORD0, \n" - " out float2 oUV : TEXCOORD0, \n" - " out float4 oPosition : POSITION, \n" - " uniform float4x4 worldViewProj \n" - ") \n" - "{ \n" - " oUV = uv; \n" - " oPosition = mul( worldViewProj, position ); \n" - "}"; - vshader->setSource(outStream.str()); - vshader->load(); - vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - mMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName()); - - HighLevelGpuProgramPtr fshader; - if (mgr.resourceExists("BBO_FP")) - fshader = mgr.getByName("BBO_FP"); - else - fshader = mgr.createProgram("BBO_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); - - fshader->setParameter("profiles", "ps_2_x arbfp1"); - fshader->setParameter("entry_point", "main_fp"); - StringUtil::StrStreamType outStream2; - outStream2 << - "void main_fp( \n" - " in float2 uv : TEXCOORD0, \n" - " out float4 oColor : COLOR, \n"; - if (RenderingManager::useMRT()) outStream2 << - " out float4 oColor1 : COLOR1, \n"; - outStream2 << - " uniform sampler2D texture : TEXUNIT0, \n" - " uniform float4 diffuse, \n" - " uniform float4 emissive \n" - ") \n" - "{ \n" - " float4 tex = tex2D(texture, uv); \n" - " oColor = float4(emissive.xyz,1) * tex * float4(1,1,1,diffuse.a); \n"; - if (RenderingManager::useMRT()) outStream2 << - " oColor1 = float4(1, 0, 0, 1); \n"; - outStream2 << - "}"; - fshader->setSource(outStream2.str()); - fshader->load(); - fshader->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); - fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); - mMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName()); - - bodyCount++; -} - Moon::Moon( const String& textureName, const float initialSize, const Vector3& position, - SceneNode* rootNode) + SceneNode* rootNode, + const std::string& material) + : BillboardObject(textureName, initialSize, position, rootNode, material) { - init(textureName, initialSize, position, rootNode); - - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - HighLevelGpuProgramPtr vshader; - if (mgr.resourceExists("Moon_VP")) - vshader = mgr.getByName("Moon_VP"); - else - vshader = mgr.createProgram("Moon_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); - vshader->setParameter("profiles", "vs_2_x arbvp1"); - vshader->setParameter("entry_point", "main_vp"); - StringUtil::StrStreamType outStream; - outStream << - "void main_vp( \n" - " float4 position : POSITION, \n" - " in float2 uv : TEXCOORD0, \n" - " out float2 oUV : TEXCOORD0, \n" - " out float4 oPosition : POSITION, \n" - " uniform float4x4 worldViewProj \n" - ") \n" - "{ \n" - " oUV = uv; \n" - " oPosition = mul( worldViewProj, position ); \n" - "}"; - vshader->setSource(outStream.str()); - vshader->load(); - vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - mMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName()); - - HighLevelGpuProgramPtr fshader; - if (mgr.resourceExists("Moon_FP")) - fshader = mgr.getByName("Moon_FP"); - else - fshader = mgr.createProgram("Moon_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); - - fshader->setParameter("profiles", "ps_2_x arbfp1"); - fshader->setParameter("entry_point", "main_fp"); - StringUtil::StrStreamType outStream2; - outStream2 << - "void main_fp( \n" - " in float2 uv : TEXCOORD0, \n" - " out float4 oColor : COLOR, \n"; - if (RenderingManager::useMRT()) outStream2 << - " out float4 oColor1 : COLOR1, \n"; - outStream2 << - " uniform sampler2D texture : TEXUNIT0, \n" - " uniform float4 skyColour, \n" - " uniform float4 diffuse, \n" - " uniform float4 emissive \n" - ") \n" - "{ \n" - " float4 tex = tex2D(texture, uv); \n" - " oColor = float4(emissive.xyz,1) * tex; \n"; - if (RenderingManager::useMRT()) outStream2 << - " oColor1 = float4(1, 0, 0, 1); \n"; - outStream2 << - // use a circle for the alpha (compute UV distance to center) - // looks a bit bad because its not filtered on the edges, - // but it's cheaper than a seperate alpha texture. - " float sqrUVdist = pow(uv.x-0.5,2) + pow(uv.y-0.5, 2); \n" - " oColor.a = diffuse.a * (sqrUVdist >= 0.24 ? 0 : 1); \n" - " oColor.rgb += (1-tex.a) * oColor.a * skyColour.rgb; \n"//fill dark side of moon with skycolour - " oColor.rgb += (1-diffuse.a) * skyColour.rgb; \n"//fade bump - "}"; - fshader->setSource(outStream2.str()); - fshader->load(); - fshader->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); - fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); - mMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName()); - setVisibility(1.0); mPhase = Moon::Phase_Full; @@ -271,11 +160,6 @@ void Moon::setType(const Moon::Type& type) mType = type; } -void Moon::setSkyColour(const Ogre::ColourValue& colour) -{ - mMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("skyColour", colour); -} - void Moon::setPhase(const Moon::Phase& phase) { // Colour texture @@ -295,7 +179,10 @@ void Moon::setPhase(const Moon::Phase& phase) textureName += ".dds"; - mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(textureName); + if (mType == Moon::Type_Secunda) + sh::Factory::getInstance ().setTextureAlias ("secunda_texture", textureName); + else + sh::Factory::getInstance ().setTextureAlias ("masser_texture", textureName); mPhase = phase; } @@ -344,25 +231,12 @@ void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType) else if (i>= 33 && i <= 48) alpha = 64; // second bottom-most row else alpha = 255; } - + // NB we would have to swap R and B depending on rendersystem specific VertexElementType, but doesn't matter since they are both 1 uint8 tmpR = static_cast(255); uint8 tmpG = static_cast(255); uint8 tmpB = static_cast(255); uint8 tmpA = static_cast(alpha); - // This does not matter since R and B are always 1. - /*VertexElementType format = Root::getSingleton().getRenderSystem()->getColourVertexElementType(); - switch (format) - { - case VET_COLOUR_ARGB: - std::swap(tmpR, tmpB); - break; - case VET_COLOUR_ABGR: - break; - default: - break; - }*/ - // Modify *((uint32*)currentVertex) = tmpR | (tmpG << 8) | (tmpB << 16) | (tmpA << 24); @@ -387,8 +261,6 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) , mSceneMgr(NULL) , mAtmosphereDay(NULL) , mAtmosphereNight(NULL) - , mCloudMaterial() - , mAtmosphereMaterial() , mCloudFragmentShader() , mClouds() , mNextClouds() @@ -396,8 +268,6 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) , mCloudOpacity(0.0f) , mCloudSpeed(0.0f) , mStarsOpacity(0.0f) - , mThunderOverlay(NULL) - , mThunderTextureUnit(NULL) , mRemainingTransitionTime(0.0f) , mGlareFade(0.0f) , mGlare(0.0f) @@ -406,6 +276,8 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) , mMasserEnabled(true) , mSecundaEnabled(true) , mCreated(false) + , mCloudAnimationTimer(0.f) + , mMoonRed(false) { mSceneMgr = pMwRoot->getCreator(); mRootNode = mCamera->getParentSceneNode()->createChildSceneNode(); @@ -415,45 +287,42 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera) void SkyManager::create() { - /// \todo preload all the textures and meshes that are used for sky rendering + sh::Factory::getInstance().setSharedParameter ("cloudBlendFactor", + sh::makeProperty(new sh::FloatValue(0))); + sh::Factory::getInstance().setSharedParameter ("cloudOpacity", + sh::makeProperty(new sh::FloatValue(1))); + sh::Factory::getInstance().setSharedParameter ("cloudColour", + sh::makeProperty(new sh::Vector3(1,1,1))); + sh::Factory::getInstance().setSharedParameter ("cloudAnimationTimer", + sh::makeProperty(new sh::FloatValue(0))); + sh::Factory::getInstance().setSharedParameter ("nightFade", + sh::makeProperty(new sh::FloatValue(0))); + + sh::Factory::getInstance().setTextureAlias ("cloud_texture_1", ""); + sh::Factory::getInstance().setTextureAlias ("cloud_texture_2", ""); // Create overlay used for thunderstorm - MaterialPtr material = MaterialManager::getSingleton().create( "ThunderMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); - Pass* pass = material->getTechnique(0)->getPass(0); - pass->setSceneBlending(SBT_TRANSPARENT_ALPHA); - mThunderTextureUnit = pass->createTextureUnitState(); - mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f)); - mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f); - OverlayManager& ovm = OverlayManager::getSingleton(); - mThunderOverlay = ovm.create( "ThunderOverlay" ); - OverlayContainer* overlay_panel; - overlay_panel = (OverlayContainer*)ovm.createOverlayElement("Panel", "ThunderPanel"); - overlay_panel->_setPosition(0, 0); - overlay_panel->_setDimensions(1, 1); - overlay_panel->setMaterialName( "ThunderMaterial" ); - overlay_panel->show(); - mThunderOverlay->add2D(overlay_panel); - mThunderOverlay->hide(); + mLightning = mSceneMgr->createLight(); + mLightning->setType (Ogre::Light::LT_DIRECTIONAL); + mLightning->setDirection (Ogre::Vector3(0.3, -0.7, 0.3)); + mLightning->setVisible (false); + mLightning->setDiffuseColour (ColourValue(3,3,3)); - mSecunda = new Moon("textures\\tx_secunda_full.dds", 0.5, Vector3(-0.4, 0.4, 0.5), mRootNode); + mSecunda = new Moon("secunda_texture", 0.5, Vector3(-0.4, 0.4, 0.5), mRootNode, "openmw_moon"); mSecunda->setType(Moon::Type_Secunda); mSecunda->setRenderQueue(RQG_SkiesEarly+4); - mMasser = new Moon("textures\\tx_masser_full.dds", 0.75, Vector3(-0.4, 0.4, 0.5), mRootNode); + mMasser = new Moon("masser_texture", 0.75, Vector3(-0.4, 0.4, 0.5), mRootNode, "openmw_moon"); mMasser->setRenderQueue(RQG_SkiesEarly+3); mMasser->setType(Moon::Type_Masser); - mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 0.4), mRootNode); + mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 0.4), mRootNode, "openmw_sun"); mSun->setRenderQueue(RQG_SkiesEarly+4); - mSunGlare = new BillboardObject("textures\\tx_sun_flash_grey_05.dds", 3, Vector3(0.4, 0.4, 0.4), mRootNode); + mSunGlare = new BillboardObject("textures\\tx_sun_flash_grey_05.dds", 3, Vector3(0.4, 0.4, 0.4), mRootNode, "openmw_sun"); mSunGlare->setRenderQueue(RQG_SkiesLate); - mSunGlare->setVisibilityFlags(RV_Glare); - - - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); + mSunGlare->setVisibilityFlags(RV_NoReflection); // Stars - /// \todo sky_night_02.nif (available in Bloodmoon) MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif"); Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif"); night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1); @@ -463,73 +332,17 @@ void SkyManager::create() mAtmosphereNight = mRootNode->createChildSceneNode(); mAtmosphereNight->attachObject(night1_ent); - // Stars vertex shader - HighLevelGpuProgramPtr stars_vp = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_VERTEX_PROGRAM); - stars_vp->setParameter("profiles", "vs_2_x arbvp1"); - stars_vp->setParameter("entry_point", "main_vp"); - StringUtil::StrStreamType outStream4; - outStream4 << - "void main_vp( \n" - " float4 position : POSITION, \n" - " in float2 uv : TEXCOORD0, \n" - " out float2 oUV : TEXCOORD0, \n" - " out float oFade : TEXCOORD1, \n" - " out float4 oPosition : POSITION, \n" - " uniform float4x4 worldViewProj \n" - ") \n" - "{ \n" - " oUV = uv; \n" - " oFade = (position.z > 50) ? 1.f : 0.f; \n" - " oPosition = mul( worldViewProj, position ); \n" - "}"; - stars_vp->setSource(outStream4.str()); - stars_vp->load(); - stars_vp->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - - // Stars fragment shader - HighLevelGpuProgramPtr stars_fp = mgr.createProgram("Stars_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_FRAGMENT_PROGRAM); - stars_fp->setParameter("profiles", "ps_2_x arbfp1"); - stars_fp->setParameter("entry_point", "main_fp"); - StringUtil::StrStreamType outStream5; - outStream5 << - "void main_fp( \n" - " in float2 uv : TEXCOORD0, \n" - " out float4 oColor : COLOR, \n"; - if (RenderingManager::useMRT()) outStream5 << - " out float4 oColor1 : COLOR1, \n"; - outStream5 << - " in float fade : TEXCOORD1, \n" - " uniform sampler2D texture : TEXUNIT0, \n" - " uniform float opacity, \n" - " uniform float4 diffuse, \n" - " uniform float4 emissive \n" - ") \n" - "{ \n" - " oColor = tex2D(texture, uv) * float4(emissive.xyz, 1) * float4(1,1,1,fade*diffuse.a); \n"; - if (RenderingManager::useMRT()) outStream5 << - " oColor1 = float4(1, 0, 0, 1); \n"; - outStream5 << - "}"; - stars_fp->setSource(outStream5.str()); - stars_fp->load(); - stars_fp->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); - stars_fp->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); - for (unsigned int i=0; igetNumSubEntities(); ++i) { - MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial(); - mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); - mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0); - mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0); - mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); - mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); - mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); - mp->getTechnique(0)->getPass(0)->setVertexProgram(stars_vp->getName()); - mp->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName()); - mp->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); - mStarsMaterials[i] = mp; + std::string matName = "openmw_stars_" + boost::lexical_cast(i); + sh::MaterialInstance* m = sh::Factory::getInstance ().createMaterialInstance (matName, "openmw_stars"); + + std::string textureName = sh::retrieveValue( + sh::Factory::getInstance().getMaterialInstance(night1_ent->getSubEntity (i)->getMaterialName ())->getProperty("diffuseMap"), NULL).get(); + + m->setProperty ("texture", sh::makeProperty(new sh::StringValue(textureName))); + + night1_ent->getSubEntity(i)->setMaterialName (matName); } // Atmosphere (day) @@ -543,62 +356,7 @@ void SkyManager::create() atmosphere_ent->setVisibilityFlags(RV_Sky); mAtmosphereDay = mRootNode->createChildSceneNode(); mAtmosphereDay->attachObject(atmosphere_ent); - mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial(); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); - - // Atmosphere shader - HighLevelGpuProgramPtr vshader = mgr.createProgram("Atmosphere_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_VERTEX_PROGRAM); - - vshader->setParameter("profiles", "vs_2_x arbvp1"); - vshader->setParameter("entry_point", "main_vp"); - - StringUtil::StrStreamType outStream; - outStream << - "void main_vp( \n" - " float4 position : POSITION, \n" - " in float4 color : COLOR, \n" - " out float4 oPosition : POSITION, \n" - " out float4 oVertexColor : TEXCOORD0, \n" - " uniform float4x4 worldViewProj \n" - ") \n" - "{ \n" - " oPosition = mul( worldViewProj, position ); \n" - " oVertexColor = color; \n" - "}"; - vshader->setSource(outStream.str()); - vshader->load(); - - vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName()); - - HighLevelGpuProgramPtr fshader = mgr.createProgram("Atmosphere_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_FRAGMENT_PROGRAM); - - fshader->setParameter("profiles", "ps_2_x arbfp1"); - fshader->setParameter("entry_point", "main_fp"); - - StringUtil::StrStreamType _outStream; - _outStream << - "void main_fp( \n" - " in float4 iVertexColor : TEXCOORD0, \n" - " out float4 oColor : COLOR, \n"; - if (RenderingManager::useMRT()) _outStream << - " out float4 oColor1 : COLOR1, \n"; - _outStream << - " uniform float4 emissive \n" - ") \n" - "{ \n" - " oColor = iVertexColor * emissive; \n"; - if (RenderingManager::useMRT()) _outStream << - " oColor1 = float4(1, 0, 0, 1); \n"; - _outStream << - "}"; - fshader->setSource(_outStream.str()); - fshader->load(); - - fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName()); + atmosphere_ent->getSubEntity (0)->setMaterialName ("openmw_atmosphere"); // Clouds NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif"); @@ -607,94 +365,11 @@ void SkyManager::create() clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5); SceneNode* clouds_node = mRootNode->createChildSceneNode(); clouds_node->attachObject(clouds_ent); - mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial(); - mCloudMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); + clouds_ent->getSubEntity(0)->setMaterialName ("openmw_clouds"); clouds_ent->setCastShadows(false); - // Clouds vertex shader - HighLevelGpuProgramPtr vshader2 = mgr.createProgram("Clouds_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_VERTEX_PROGRAM); - vshader2->setParameter("profiles", "vs_2_x arbvp1"); - vshader2->setParameter("entry_point", "main_vp"); - StringUtil::StrStreamType outStream3; - outStream3 << - "void main_vp( \n" - " float4 position : POSITION, \n" - " in float4 color : COLOR, \n" - " out float4 oColor : TEXCOORD1, \n" - " in float2 uv : TEXCOORD0, \n" - " out float2 oUV : TEXCOORD0, \n" - " out float4 oPosition : POSITION, \n" - " uniform float4x4 worldViewProj \n" - ") \n" - "{ \n" - " oUV = uv; \n" - " oColor = color; \n" - " oPosition = mul( worldViewProj, position ); \n" - "}"; - vshader2->setSource(outStream3.str()); - vshader2->load(); - vshader2->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); - mCloudMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader2->getName()); - - // Clouds fragment shader - mCloudFragmentShader = mgr.createProgram("Clouds_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_FRAGMENT_PROGRAM); - mCloudFragmentShader->setParameter("profiles", "ps_2_x arbfp1"); - mCloudFragmentShader->setParameter("entry_point", "main_fp"); - StringUtil::StrStreamType outStream2; - outStream2 << - "void main_fp( \n" - " in float2 uv : TEXCOORD0, \n" - " in float4 color : TEXCOORD1, \n" - " out float4 oColor : COLOR, \n"; - if (RenderingManager::useMRT()) outStream2 << - " out float4 oColor1 : COLOR1, \n"; - outStream2 << - " uniform sampler2D texture : TEXUNIT0, \n" - " uniform sampler2D secondTexture : TEXUNIT1, \n" - " uniform float transitionFactor, \n" - " uniform float time, \n" - " uniform float speed, \n" - " uniform float opacity, \n" - " uniform float4 emissive \n" - ") \n" - "{ \n" - " uv += float2(0,1) * time * speed * 0.003; \n" // Scroll in y direction - " float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n" - " oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n"; - if (RenderingManager::useMRT()) outStream2 << - " oColor1 = float4(1, 0, 0, 1); \n"; - outStream2 << - "}"; - mCloudFragmentShader->setSource(outStream2.str()); - mCloudFragmentShader->load(); - mCloudFragmentShader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); - mCloudMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(mCloudFragmentShader->getName()); - setCloudsOpacity(0.75); - ModVertexAlpha(clouds_ent, 1); - // I'm not sure if the materials are being used by any other objects - // Make a unique "modifiable" copy of the materials to be sure - mCloudMaterial = mCloudMaterial->clone("Clouds"); - clouds_ent->getSubEntity(0)->setMaterial(mCloudMaterial); - mAtmosphereMaterial = mAtmosphereMaterial->clone("Atmosphere"); - atmosphere_ent->getSubEntity(0)->setMaterial(mAtmosphereMaterial); - - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 0.0); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0); - mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); - mCloudMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); - mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); - - mCloudMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates(); - mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("textures\\tx_sky_cloudy.dds"); - mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState(""); - mCreated = true; } @@ -723,24 +398,28 @@ void SkyManager::update(float duration) if (!mEnabled) return; // UV Scroll the clouds - mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", MWBase::Environment::get().getWorld()->getTimeScaleFactor()/30.f); + mCloudAnimationTimer += duration * mCloudSpeed * (MWBase::Environment::get().getWorld()->getTimeScaleFactor()/30.f); + sh::Factory::getInstance().setSharedParameter ("cloudAnimationTimer", + sh::makeProperty(new sh::FloatValue(mCloudAnimationTimer))); /// \todo improve this mMasser->setPhase( static_cast( (int) ((mDay % 32)/4.f)) ); mSecunda->setPhase ( static_cast( (int) ((mDay % 32)/4.f)) ); + mSecunda->setColour ( mMoonRed ? ColourValue(1.0, 0.0784, 0.0784) : ColourValue(1,1,1,1)); + mMasser->setColour (ColourValue(1,1,1,1)); if (mSunEnabled) { - // take 1/5 sec for fading the glare effect from invisible to full + // take 1/10 sec for fading the glare effect from invisible to full if (mGlareFade > mGlare) { - mGlareFade -= duration*5; + mGlareFade -= duration*10; if (mGlareFade < mGlare) mGlareFade = mGlare; } else if (mGlareFade < mGlare) { - mGlareFade += duration*5; + mGlareFade += duration*10; if (mGlareFade > mGlare) mGlareFade = mGlare; } @@ -782,42 +461,37 @@ void SkyManager::disable() void SkyManager::setMoonColour (bool red) { - if (!mCreated) return; - mSecunda->setColour( red ? ColourValue(1.0, 0.0784, 0.0784) - : ColourValue(1.0, 1.0, 1.0)); -} - -void SkyManager::setCloudsOpacity(float opacity) -{ - if (!mCreated) return; - mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(opacity)); + mMoonRed = red; } void SkyManager::setWeather(const MWWorld::WeatherResult& weather) { if (!mCreated) return; + if (mClouds != weather.mCloudTexture) { - mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("textures\\"+weather.mCloudTexture); + sh::Factory::getInstance().setTextureAlias ("cloud_texture_1", "textures\\"+weather.mCloudTexture); mClouds = weather.mCloudTexture; } if (mNextClouds != weather.mNextCloudTexture) { - mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName("textures\\"+weather.mNextCloudTexture); + sh::Factory::getInstance().setTextureAlias ("cloud_texture_2", "textures\\"+weather.mNextCloudTexture); mNextClouds = weather.mNextCloudTexture; } if (mCloudBlendFactor != weather.mCloudBlendFactor) { - mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("transitionFactor", Real(weather.mCloudBlendFactor)); mCloudBlendFactor = weather.mCloudBlendFactor; + sh::Factory::getInstance().setSharedParameter ("cloudBlendFactor", + sh::makeProperty(new sh::FloatValue(weather.mCloudBlendFactor))); } if (mCloudOpacity != weather.mCloudOpacity) { - mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(weather.mCloudOpacity)); mCloudOpacity = weather.mCloudOpacity; + sh::Factory::getInstance().setSharedParameter ("cloudOpacity", + sh::makeProperty(new sh::FloatValue(weather.mCloudOpacity))); } if (mCloudColour != weather.mSunColor) @@ -826,23 +500,20 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather) weather.mSunColor.g*0.7 + weather.mAmbientColor.g*0.7, weather.mSunColor.b*0.7 + weather.mAmbientColor.b*0.7); - mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(clr); + sh::Factory::getInstance().setSharedParameter ("cloudColour", + sh::makeProperty(new sh::Vector3(clr.r, clr.g, clr.b))); + mCloudColour = weather.mSunColor; } if (mSkyColour != weather.mSkyColor) { - mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(weather.mSkyColor); - mMasser->setSkyColour(weather.mSkyColor); - mSecunda->setSkyColour(weather.mSkyColor); mSkyColour = weather.mSkyColor; + sh::Factory::getInstance().setSharedParameter ("atmosphereColour", sh::makeProperty(new sh::Vector4( + weather.mSkyColor.r, weather.mSkyColor.g, weather.mSkyColor.b, weather.mSkyColor.a))); } - if (mCloudSpeed != weather.mCloudSpeed) - { - mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("speed", Real(weather.mCloudSpeed)); - mCloudSpeed = weather.mCloudSpeed; - } + mCloudSpeed = weather.mCloudSpeed; if (weather.mNight && mStarsOpacity != weather.mNightFade) { @@ -851,12 +522,15 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather) else { mAtmosphereNight->setVisible(true); - for (int i=0; i<7; ++i) - mStarsMaterials[i]->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, weather.mNightFade); + + sh::Factory::getInstance().setSharedParameter ("nightFade", + sh::makeProperty(new sh::FloatValue(weather.mNightFade))); + mStarsOpacity = weather.mNightFade; } } + float strength; float timeofday_angle = std::abs(mSunGlare->getPosition().z/mSunGlare->getPosition().length()); if (timeofday_angle <= 0.44) @@ -897,6 +571,10 @@ void SkyManager::setSunDirection(const Vector3& direction) if (!mCreated) return; mSun->setPosition(direction); mSunGlare->setPosition(direction); + + float height = direction.z; + float fade = ( height > 0.5) ? 1.0 : height * 2; + sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty(new sh::Vector2(fade, height))); } void SkyManager::setMasserDirection(const Vector3& direction) @@ -931,16 +609,22 @@ void SkyManager::secundaDisable() mSecundaEnabled = false; } -void SkyManager::setThunder(const float factor) +void SkyManager::setLightningStrength(const float factor) { if (!mCreated) return; if (factor > 0.f) { - mThunderOverlay->show(); - mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, factor*0.6); + mLightning->setDiffuseColour (ColourValue(2*factor, 2*factor, 2*factor)); + mLightning->setVisible(true); } else - mThunderOverlay->hide(); + mLightning->setVisible(false); +} + +void SkyManager::setLightningDirection(const Ogre::Vector3& dir) +{ + if (!mCreated) return; + mLightning->setDirection (dir); } void SkyManager::setMasserFade(const float fade) @@ -986,3 +670,10 @@ void SkyManager::scaleSky(float scale) { mRootNode->setScale(scale, scale, scale); } + +void SkyManager::setGlareEnabled (bool enabled) +{ + if (!mCreated) + return; + mSunGlare->setVisible (mSunEnabled && enabled); +} diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index e11745e828..9fdff3a01e 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -7,6 +7,8 @@ #include #include +#include + #include "sky.hpp" #include "../mwworld/weather.hpp" @@ -25,16 +27,20 @@ namespace Ogre namespace MWRender { - class BillboardObject + class BillboardObject : public sh::MaterialInstanceListener { public: BillboardObject( const Ogre::String& textureName, const float size, const Ogre::Vector3& position, - Ogre::SceneNode* rootNode + Ogre::SceneNode* rootNode, + const std::string& material ); BillboardObject(); + void requestedConfiguration (sh::MaterialInstance* m, const std::string& configuration); + void createdConfiguration (sh::MaterialInstance* m, const std::string& configuration); + virtual ~BillboardObject() {} void setColour(const Ogre::ColourValue& pColour); @@ -50,13 +56,10 @@ namespace MWRender Ogre::SceneNode* getNode(); protected: - virtual void init(const Ogre::String& textureName, - const float size, - const Ogre::Vector3& position, - Ogre::SceneNode* rootNode); - + float mVisibility; + Ogre::ColourValue mColour; Ogre::SceneNode* mNode; - Ogre::MaterialPtr mMaterial; + sh::MaterialInstance* mMaterial; Ogre::BillboardSet* mBBSet; }; @@ -70,7 +73,8 @@ namespace MWRender Moon( const Ogre::String& textureName, const float size, const Ogre::Vector3& position, - Ogre::SceneNode* rootNode + Ogre::SceneNode* rootNode, + const std::string& material ); virtual ~Moon() {} @@ -95,7 +99,6 @@ namespace MWRender void setPhase(const Phase& phase); void setType(const Type& type); - void setSkyColour(const Ogre::ColourValue& colour); Phase getPhase() const; unsigned int getPhaseInt() const; @@ -137,9 +140,6 @@ namespace MWRender void setMoonColour (bool red); ///< change Secunda colour to red - void setCloudsOpacity(float opacity); - ///< change opacity of the clouds - void setWeather(const MWWorld::WeatherResult& weather); Ogre::SceneNode* getSunNode(); @@ -164,9 +164,11 @@ namespace MWRender void secundaEnable(); void secundaDisable(); - void setThunder(const float factor); + void setLightningStrength(const float factor); + void setLightningDirection(const Ogre::Vector3& dir); void setGlare(const float glare); + void setGlareEnabled(bool enabled); Ogre::Vector3 getRealSunPos(); void setSkyPosition(const Ogre::Vector3& position); @@ -176,10 +178,14 @@ namespace MWRender private: bool mCreated; + bool mMoonRed; + float mHour; int mDay; int mMonth; + float mCloudAnimationTimer; + BillboardObject* mSun; BillboardObject* mSunGlare; Moon* mMasser; @@ -192,11 +198,6 @@ namespace MWRender Ogre::SceneNode* mAtmosphereDay; Ogre::SceneNode* mAtmosphereNight; - Ogre::MaterialPtr mCloudMaterial; - Ogre::MaterialPtr mAtmosphereMaterial; - - Ogre::MaterialPtr mStarsMaterials[7]; - Ogre::HighLevelGpuProgramPtr mCloudFragmentShader; // remember some settings so we don't have to apply them again if they didnt change @@ -209,8 +210,7 @@ namespace MWRender Ogre::ColourValue mCloudColour; Ogre::ColourValue mSkyColour; - Ogre::Overlay* mThunderOverlay; - Ogre::TextureUnitState* mThunderTextureUnit; + Ogre::Light* mLightning; float mRemainingTransitionTime; diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index f14db34e61..691e7c4af3 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -28,22 +28,22 @@ namespace MWRender mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend) { mTerrainGlobals = OGRE_NEW TerrainGlobalOptions(); + TerrainMaterialGeneratorPtr matGen; - TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB(); + TerrainMaterial* matGenP = new TerrainMaterial(); matGen.bind(matGenP); mTerrainGlobals->setDefaultMaterialGenerator(matGen); TerrainMaterialGenerator::Profile* const activeProfile = mTerrainGlobals->getDefaultMaterialGenerator() ->getActiveProfile(); - mActiveProfile = static_cast(activeProfile); + mActiveProfile = static_cast(activeProfile); //The pixel error should be as high as possible without it being noticed //as it governs how fast mesh quality decreases. mTerrainGlobals->setMaxPixelError(8); mTerrainGlobals->setLayerBlendMapSize(32); - mTerrainGlobals->setDefaultGlobalColourMapSize(65); //10 (default) didn't seem to be quite enough mTerrainGlobals->setSkirtSize(128); @@ -52,26 +52,6 @@ namespace MWRender //this seemed the distance where it wasn't too noticeable mTerrainGlobals->setCompositeMapDistance(mWorldSize*2); - mActiveProfile->setLightmapEnabled(false); - mActiveProfile->setLayerSpecularMappingEnabled(false); - mActiveProfile->setLayerNormalMappingEnabled(false); - mActiveProfile->setLayerParallaxMappingEnabled(false); - - bool shadows = Settings::Manager::getBool("enabled", "Shadows"); - mActiveProfile->setReceiveDynamicShadowsEnabled(shadows); - mActiveProfile->setReceiveDynamicShadowsDepth(shadows); - if (Settings::Manager::getBool("split", "Shadows")) - mActiveProfile->setReceiveDynamicShadowsPSSM(mRendering->getShadows()->getPSSMSetup()); - else - mActiveProfile->setReceiveDynamicShadowsPSSM(0); - - mActiveProfile->setShadowFar(mRendering->getShadows()->getShadowFar()); - mActiveProfile->setShadowFadeStart(mRendering->getShadows()->getFadeStart()); - - //composite maps lead to a drastic increase in loading time so are - //disabled - mActiveProfile->setCompositeMapEnabled(false); - mTerrainGroup.setOrigin(Vector3(mWorldSize/2, 0, -mWorldSize/2)); @@ -178,23 +158,20 @@ namespace MWRender terrain->setVisibilityFlags(RV_Terrain); terrain->setRenderQueueGroup(RQG_Main); + // disable or enable global colour map (depends on available vertex colours) if ( land->landData->usingColours ) { - // disable or enable global colour map (depends on available vertex colours) - mActiveProfile->setGlobalColourMapEnabled(true); TexturePtr vertex = getVertexColours(land, cellX, cellY, x*(mLandSize-1), y*(mLandSize-1), mLandSize); - //this is a hack to get around the fact that Ogre seems to - //corrupt the global colour map leading to rendering errors - MaterialPtr mat = terrain->getMaterial(); - mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() ); - //mat = terrain->_getCompositeMapMaterial(); - //mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() ); + mActiveProfile->setGlobalColourMapEnabled(true); + mActiveProfile->setGlobalColourMap (terrain, vertex->getName()); } + else + mActiveProfile->setGlobalColourMapEnabled (false); } } } diff --git a/apps/openmw/mwrender/terrain.hpp b/apps/openmw/mwrender/terrain.hpp index 7ac48047da..c83d96cf47 100644 --- a/apps/openmw/mwrender/terrain.hpp +++ b/apps/openmw/mwrender/terrain.hpp @@ -46,7 +46,7 @@ namespace MWRender{ RenderingManager* mRendering; - Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile; + TerrainMaterial::Profile* mActiveProfile; /** * The length in verticies of a single terrain block. diff --git a/apps/openmw/mwrender/terrainmaterial.cpp b/apps/openmw/mwrender/terrainmaterial.cpp index a3265b2a5c..1a2d96a144 100644 --- a/apps/openmw/mwrender/terrainmaterial.cpp +++ b/apps/openmw/mwrender/terrainmaterial.cpp @@ -1,1746 +1,178 @@ -/* ------------------------------------------------------------------------------ -This source file is part of OGRE -(Object-oriented Graphics Rendering Engine) -For the latest info, see http://www.ogre3d.org/ - -Copyright (c) 2000-2011 Torus Knot Software Ltd - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. ------------------------------------------------------------------------------ -*/ #include "terrainmaterial.hpp" -#include "OgreTerrain.h" -#include "OgreMaterialManager.h" -#include "OgreTechnique.h" -#include "OgrePass.h" -#include "OgreTextureUnitState.h" -#include "OgreGpuProgramManager.h" -#include "OgreHighLevelGpuProgramManager.h" -#include "OgreHardwarePixelBuffer.h" -#include "OgreShadowCameraSetupPSSM.h" -#include -#include "renderingmanager.hpp" +#include -#undef far +#include -namespace Ogre +namespace { - //--------------------------------------------------------------------- - TerrainMaterialGeneratorB::TerrainMaterialGeneratorB() - { - // define the layers - // We expect terrain textures to have no alpha, so we use the alpha channel - // in the albedo texture to store specular reflection - // similarly we double-up the normal and height (for parallax) - mLayerDecl.samplers.push_back(TerrainLayerSampler("albedo_specular", PF_BYTE_RGBA)); - //mLayerDecl.samplers.push_back(TerrainLayerSampler("normal_height", PF_BYTE_RGBA)); - - mLayerDecl.elements.push_back( - TerrainLayerSamplerElement(0, TLSS_ALBEDO, 0, 3)); - //mLayerDecl.elements.push_back( - // TerrainLayerSamplerElement(0, TLSS_SPECULAR, 3, 1)); - //mLayerDecl.elements.push_back( - // TerrainLayerSamplerElement(1, TLSS_NORMAL, 0, 3)); - //mLayerDecl.elements.push_back( - // TerrainLayerSamplerElement(1, TLSS_HEIGHT, 3, 1)); - - - mProfiles.push_back(OGRE_NEW SM2Profile(this, "SM2", "Profile for rendering on Shader Model 2 capable cards")); - // TODO - check hardware capabilities & use fallbacks if required (more profiles needed) - setActiveProfile("SM2"); - - } - //--------------------------------------------------------------------- - TerrainMaterialGeneratorB::~TerrainMaterialGeneratorB() - { - - } - //--------------------------------------------------------------------- - //--------------------------------------------------------------------- - TerrainMaterialGeneratorB::SM2Profile::SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc) - : Profile(parent, name, desc) - , mShaderGen(0) - , mLayerNormalMappingEnabled(true) - , mLayerParallaxMappingEnabled(true) - , mLayerSpecularMappingEnabled(true) - , mGlobalColourMapEnabled(true) - , mLightmapEnabled(true) - , mCompositeMapEnabled(true) - , mReceiveDynamicShadows(true) - , mPSSM(0) - , mDepthShadows(false) - , mLowLodShadows(false) - , mShadowFar(1300) - { - - } - //--------------------------------------------------------------------- - TerrainMaterialGeneratorB::SM2Profile::~SM2Profile() - { - OGRE_DELETE mShaderGen; - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::requestOptions(Terrain* terrain) - { - terrain->_setMorphRequired(true); - terrain->_setNormalMapRequired(true); - terrain->_setLightMapRequired(mLightmapEnabled, true); - terrain->_setCompositeMapRequired(mCompositeMapEnabled); - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::setShadowFar(float far) + Ogre::String getComponent (int num) { - if (mShadowFar != far) + if (num == 0) + return "x"; + else if (num == 1) + return "y"; + else if (num == 2) + return "z"; + else + return "w"; + } +} + + +namespace MWRender +{ + + TerrainMaterial::TerrainMaterial() + { + mLayerDecl.samplers.push_back(Ogre::TerrainLayerSampler("albedo_specular", Ogre::PF_BYTE_RGBA)); + //mLayerDecl.samplers.push_back(Ogre::TerrainLayerSampler("normal_height", Ogre::PF_BYTE_RGBA)); + + mLayerDecl.elements.push_back( + Ogre::TerrainLayerSamplerElement(0, Ogre::TLSS_ALBEDO, 0, 3)); + //mLayerDecl.elements.push_back( + // Ogre::TerrainLayerSamplerElement(0, Ogre::TLSS_SPECULAR, 3, 1)); + //mLayerDecl.elements.push_back( + // Ogre::TerrainLayerSamplerElement(1, Ogre::TLSS_NORMAL, 0, 3)); + //mLayerDecl.elements.push_back( + // Ogre::TerrainLayerSamplerElement(1, Ogre::TLSS_HEIGHT, 3, 1)); + + + mProfiles.push_back(OGRE_NEW Profile(this, "SM2", "Profile for rendering on Shader Model 2 capable cards")); + setActiveProfile("SM2"); + } + + // ----------------------------------------------------------------------------------------------------------------------- + + TerrainMaterial::Profile::Profile(Ogre::TerrainMaterialGenerator* parent, const Ogre::String& name, const Ogre::String& desc) + : Ogre::TerrainMaterialGenerator::Profile(parent, name, desc) + , mGlobalColourMap(false) + { + } + + TerrainMaterial::Profile::~Profile() + { + } + + + Ogre::MaterialPtr TerrainMaterial::Profile::generate(const Ogre::Terrain* terrain) + { + const Ogre::String& matName = terrain->getMaterialName(); + + sh::Factory::getInstance().destroyMaterialInstance (matName); + + Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName(matName); + if (!mat.isNull()) + Ogre::MaterialManager::getSingleton().remove(matName); + + mMaterial = sh::Factory::getInstance().createMaterialInstance (matName); + + mMaterial->setProperty ("allow_fixed_function", sh::makeProperty(new sh::BooleanValue(false))); + + sh::MaterialInstancePass* p = mMaterial->createPass (); + + p->setProperty ("vertex_program", sh::makeProperty(new sh::StringValue("terrain_vertex"))); + p->setProperty ("fragment_program", sh::makeProperty(new sh::StringValue("terrain_fragment"))); + + p->mShaderProperties.setProperty ("colour_map", sh::makeProperty(new sh::BooleanValue(mGlobalColourMap))); + + // global colour map + sh::MaterialInstanceTextureUnit* colourMap = p->createTextureUnit ("colourMap"); + colourMap->setProperty ("texture_alias", sh::makeProperty (new sh::StringValue(mMaterial->getName() + "_colourMap"))); + colourMap->setProperty ("tex_address_mode", sh::makeProperty (new sh::StringValue("clamp"))); + + // global normal map + sh::MaterialInstanceTextureUnit* normalMap = p->createTextureUnit ("normalMap"); + normalMap->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(terrain->getTerrainNormalMap ()->getName()))); + normalMap->setProperty ("tex_address_mode", sh::makeProperty (new sh::StringValue("clamp"))); + + uint maxLayers = getMaxLayers(terrain); + uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()); + uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); + + p->mShaderProperties.setProperty ("num_layers", sh::makeProperty(new sh::StringValue(Ogre::StringConverter::toString(numLayers)))); + p->mShaderProperties.setProperty ("num_blendmaps", sh::makeProperty(new sh::StringValue(Ogre::StringConverter::toString(numBlendTextures)))); + + // blend maps + for (uint i = 0; i < numBlendTextures; ++i) { - mShadowFar = far; - mParent->_markChanged(); + sh::MaterialInstanceTextureUnit* blendTex = p->createTextureUnit ("blendMap" + Ogre::StringConverter::toString(i)); + blendTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(terrain->getBlendTextureName(i)))); + blendTex->setProperty ("tex_address_mode", sh::makeProperty (new sh::StringValue("clamp"))); } - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::setShadowFadeStart(float fadestart) - { - if (mShadowFadeStart != fadestart) + + // layer maps + for (uint i = 0; i < numLayers; ++i) { - mShadowFadeStart = fadestart; - mParent->_markChanged(); + sh::MaterialInstanceTextureUnit* diffuseTex = p->createTextureUnit ("diffuseMap" + Ogre::StringConverter::toString(i)); + diffuseTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(terrain->getLayerTextureName(i, 0)))); + p->mShaderProperties.setProperty ("blendmap_component_" + Ogre::StringConverter::toString(i), + sh::makeProperty(new sh::StringValue(Ogre::StringConverter::toString(int((i-1) / 4)) + "." + getComponent(int((i-1) % 4))))); } + + // shadow + for (uint i = 0; i < 3; ++i) + { + sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i)); + shadowTex->setProperty ("content_type", sh::makeProperty (new sh::StringValue("shadow"))); + } + + // caustics + sh::MaterialInstanceTextureUnit* caustics = p->createTextureUnit ("causticMap"); + caustics->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue("water_nm.png"))); + + p->mShaderProperties.setProperty ("shadowtexture_offset", sh::makeProperty(new sh::StringValue( + Ogre::StringConverter::toString(numBlendTextures + numLayers + 2)))); + + return Ogre::MaterialManager::getSingleton().getByName(matName); } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::setLayerNormalMappingEnabled(bool enabled) - { - if (enabled != mLayerNormalMappingEnabled) - { - mLayerNormalMappingEnabled = enabled; - mParent->_markChanged(); - } - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::setLayerParallaxMappingEnabled(bool enabled) - { - if (enabled != mLayerParallaxMappingEnabled) - { - mLayerParallaxMappingEnabled = enabled; - mParent->_markChanged(); - } - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::setLayerSpecularMappingEnabled(bool enabled) - { - if (enabled != mLayerSpecularMappingEnabled) - { - mLayerSpecularMappingEnabled = enabled; - mParent->_markChanged(); - } - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::setGlobalColourMapEnabled(bool enabled) - { - if (enabled != mGlobalColourMapEnabled) - { - mGlobalColourMapEnabled = enabled; - //mParent->_markChanged(); - } - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::setLightmapEnabled(bool enabled) - { - if (enabled != mLightmapEnabled) - { - mLightmapEnabled = enabled; - mParent->_markChanged(); - } - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::setCompositeMapEnabled(bool enabled) - { - if (enabled != mCompositeMapEnabled) - { - mCompositeMapEnabled = enabled; - mParent->_markChanged(); - } - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::setReceiveDynamicShadowsEnabled(bool enabled) - { - if (enabled != mReceiveDynamicShadows) - { - mReceiveDynamicShadows = enabled; - mParent->_markChanged(); - } - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::setReceiveDynamicShadowsPSSM(PSSMShadowCameraSetup* pssmSettings) - { - if (pssmSettings != mPSSM) - { - mPSSM = pssmSettings; - mParent->_markChanged(); - } - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::setReceiveDynamicShadowsDepth(bool enabled) - { - if (enabled != mDepthShadows) - { - mDepthShadows = enabled; - mParent->_markChanged(); - } - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::setReceiveDynamicShadowsLowLod(bool enabled) - { - if (enabled != mLowLodShadows) - { - mLowLodShadows = enabled; - mParent->_markChanged(); - } - } - //--------------------------------------------------------------------- - uint8 TerrainMaterialGeneratorB::SM2Profile::getMaxLayers(const Terrain* terrain) const - { - // count the texture units free - uint8 freeTextureUnits = 16; - // lightmap - if (mLightmapEnabled) - --freeTextureUnits; - // normalmap - --freeTextureUnits; - // colourmap - //if (terrain->getGlobalColourMapEnabled()) - --freeTextureUnits; - if (isShadowingEnabled(HIGH_LOD, terrain)) - { - uint numShadowTextures = 1; - if (getReceiveDynamicShadowsPSSM()) - { - numShadowTextures = getReceiveDynamicShadowsPSSM()->getSplitCount(); - } - freeTextureUnits -= numShadowTextures; - } - - // each layer needs 2.25 units (1xdiffusespec, (1xnormalheight), 0.25xblend) - return static_cast(freeTextureUnits / (1.25f + (mLayerNormalMappingEnabled||mLayerParallaxMappingEnabled))); - - - } - int TerrainMaterialGeneratorB::SM2Profile::getNumberOfLightsSupported() const + void TerrainMaterial::Profile::setGlobalColourMapEnabled (bool enabled) { - return Settings::Manager::getInt("num lights", "Terrain"); + mGlobalColourMap = enabled; + mParent->_markChanged(); } - //--------------------------------------------------------------------- - MaterialPtr TerrainMaterialGeneratorB::SM2Profile::generate(const Terrain* terrain) - { - // re-use old material if exists - MaterialPtr mat = terrain->_getMaterial(); - if (mat.isNull()) - { - MaterialManager& matMgr = MaterialManager::getSingleton(); - - // it's important that the names are deterministic for a given terrain, so - // use the terrain pointer as an ID - const String& matName = terrain->getMaterialName(); - mat = matMgr.getByName(matName); - if (mat.isNull()) - { - mat = matMgr.create(matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - } - } - // clear everything - mat->removeAllTechniques(); - - // Automatically disable normal & parallax mapping if card cannot handle it - // We do this rather than having a specific technique for it since it's simpler - GpuProgramManager& gmgr = GpuProgramManager::getSingleton(); - if (!gmgr.isSyntaxSupported("ps_3_0") && !gmgr.isSyntaxSupported("ps_2_x") - && !gmgr.isSyntaxSupported("fp40") && !gmgr.isSyntaxSupported("arbfp1")) - { - setLayerNormalMappingEnabled(false); - setLayerParallaxMappingEnabled(false); - } - - addTechnique(mat, terrain, HIGH_LOD); - - // LOD - if(mCompositeMapEnabled) - { - addTechnique(mat, terrain, LOW_LOD); - Material::LodValueList lodValues; - lodValues.push_back(TerrainGlobalOptions::getSingleton().getCompositeMapDistance()); - mat->setLodLevels(lodValues); - Technique* lowLodTechnique = mat->getTechnique(1); - lowLodTechnique->setLodIndex(1); - } - - updateParams(mat, terrain); - - return mat; - - } - //--------------------------------------------------------------------- - MaterialPtr TerrainMaterialGeneratorB::SM2Profile::generateForCompositeMap(const Terrain* terrain) - { - // re-use old material if exists - MaterialPtr mat = terrain->_getCompositeMapMaterial(); - if (mat.isNull()) - { - MaterialManager& matMgr = MaterialManager::getSingleton(); - - // it's important that the names are deterministic for a given terrain, so - // use the terrain pointer as an ID - const String& matName = terrain->getMaterialName() + "/comp"; - mat = matMgr.getByName(matName); - if (mat.isNull()) - { - mat = matMgr.create(matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - } - } - // clear everything - mat->removeAllTechniques(); - - addTechnique(mat, terrain, RENDER_COMPOSITE_MAP); - - updateParamsForCompositeMap(mat, terrain); - - return mat; - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::addTechnique( - const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt) - { - - Technique* tech = mat->createTechnique(); - - // Only supporting one pass - Pass* pass = tech->createPass(); - - GpuProgramManager& gmgr = GpuProgramManager::getSingleton(); - HighLevelGpuProgramManager& hmgr = HighLevelGpuProgramManager::getSingleton(); - if (!mShaderGen) - { - bool check2x = mLayerNormalMappingEnabled || mLayerParallaxMappingEnabled; - if (hmgr.isLanguageSupported("cg")) - mShaderGen = OGRE_NEW ShaderHelperCg(); - else if (hmgr.isLanguageSupported("hlsl") && - ((check2x && gmgr.isSyntaxSupported("ps_2_x")) || - (!check2x && gmgr.isSyntaxSupported("ps_2_0")))) - mShaderGen = OGRE_NEW ShaderHelperHLSL(); - else if (hmgr.isLanguageSupported("glsl")) - mShaderGen = OGRE_NEW ShaderHelperGLSL(); - else - { - // todo - } - - // check SM3 features - mSM3Available = GpuProgramManager::getSingleton().isSyntaxSupported("ps_3_0"); - - } - HighLevelGpuProgramPtr vprog = mShaderGen->generateVertexProgram(this, terrain, tt); - HighLevelGpuProgramPtr fprog = mShaderGen->generateFragmentProgram(this, terrain, tt); - - pass->setVertexProgram(vprog->getName()); - pass->setFragmentProgram(fprog->getName()); - - if (tt == HIGH_LOD || tt == RENDER_COMPOSITE_MAP) - { - // global normal map - TextureUnitState* tu = pass->createTextureUnitState(); - tu->setTextureName(terrain->getTerrainNormalMap()->getName()); - tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); - - // global colour map - if (isGlobalColourMapEnabled()) - { - tu = pass->createTextureUnitState(""); - tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); - } - - // light map - if (isLightmapEnabled()) - { - tu = pass->createTextureUnitState(terrain->getLightmap()->getName()); - tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); - } - - // blend maps - uint maxLayers = getMaxLayers(terrain); - uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()); - uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); - for (uint i = 0; i < numBlendTextures; ++i) - { - tu = pass->createTextureUnitState(terrain->getBlendTextureName(i)); - tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); - } - - // layer textures - for (uint i = 0; i < numLayers; ++i) - { - // diffuse / specular - tu = pass->createTextureUnitState(terrain->getLayerTextureName(i, 0)); - - // normal / height - if (mLayerNormalMappingEnabled || mLayerParallaxMappingEnabled) - tu = pass->createTextureUnitState(terrain->getLayerTextureName(i, 1)); - } - - } - else - { - // LOW_LOD textures - // composite map - TextureUnitState* tu = pass->createTextureUnitState(); - tu->setTextureName(terrain->getCompositeMap()->getName()); - tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); - - // That's it! - - } - - // Add shadow textures (always at the end) - if (isShadowingEnabled(tt, terrain)) - { - uint numTextures = 1; - if (getReceiveDynamicShadowsPSSM()) - { - numTextures = getReceiveDynamicShadowsPSSM()->getSplitCount(); - } - for (uint i = 0; i < numTextures; ++i) - { - TextureUnitState* tu = pass->createTextureUnitState(); - tu->setContentType(TextureUnitState::CONTENT_SHADOW); - tu->setTextureAddressingMode(TextureUnitState::TAM_BORDER); - tu->setTextureBorderColour(ColourValue::White); - } - } - - } - //--------------------------------------------------------------------- - bool TerrainMaterialGeneratorB::SM2Profile::isShadowingEnabled(TechniqueType tt, const Terrain* terrain) const - { - return getReceiveDynamicShadowsEnabled() && tt != RENDER_COMPOSITE_MAP && - (tt != LOW_LOD || mLowLodShadows) && - terrain->getSceneManager()->isShadowTechniqueTextureBased(); - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::updateParams(const MaterialPtr& mat, const Terrain* terrain) - { - mShaderGen->updateParams(this, mat, terrain, false); - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::updateParamsForCompositeMap(const MaterialPtr& mat, const Terrain* terrain) - { - mShaderGen->updateParams(this, mat, terrain, true); - } - //--------------------------------------------------------------------- - //--------------------------------------------------------------------- - HighLevelGpuProgramPtr - TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::generateVertexProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) - { - HighLevelGpuProgramPtr ret = createVertexProgram(prof, terrain, tt); - - StringUtil::StrStreamType sourceStr; - generateVertexProgramSource(prof, terrain, tt, sourceStr); - ret->setSource(sourceStr.str()); - ret->load(); - defaultVpParams(prof, terrain, tt, ret); -#if OGRE_DEBUG_MODE - LogManager::getSingleton().stream(LML_TRIVIAL) << "*** Terrain Vertex Program: " - << ret->getName() << " ***\n" << ret->getSource() << "\n*** ***"; -#endif - - return ret; - - } - //--------------------------------------------------------------------- - HighLevelGpuProgramPtr - TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::generateFragmentProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) - { - HighLevelGpuProgramPtr ret = createFragmentProgram(prof, terrain, tt); - - StringUtil::StrStreamType sourceStr; - generateFragmentProgramSource(prof, terrain, tt, sourceStr); - - ret->setSource(sourceStr.str()); - ret->load(); - defaultFpParams(prof, terrain, tt, ret); - -#if OGRE_DEBUG_MODE - LogManager::getSingleton().stream(LML_TRIVIAL) << "*** Terrain Fragment Program: " - << ret->getName() << " ***\n" << ret->getSource() << "\n*** ***"; -#endif - - return ret; - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::generateVertexProgramSource( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) - { - generateVpHeader(prof, terrain, tt, outStream); - - if (tt != LOW_LOD) - { - uint maxLayers = prof->getMaxLayers(terrain); - uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); - - for (uint i = 0; i < numLayers; ++i) - generateVpLayer(prof, terrain, tt, i, outStream); - } - - generateVpFooter(prof, terrain, tt, outStream); - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::generateFragmentProgramSource( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) - { - generateFpHeader(prof, terrain, tt, outStream); - - if (tt != LOW_LOD) - { - uint maxLayers = prof->getMaxLayers(terrain); - uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); - - for (uint i = 0; i < numLayers; ++i) - generateFpLayer(prof, terrain, tt, i, outStream); - } - - generateFpFooter(prof, terrain, tt, outStream); - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::defaultVpParams( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog) - { - GpuProgramParametersSharedPtr params = prog->getDefaultParameters(); - params->setIgnoreMissingParams(true); - params->setNamedAutoConstant("worldMatrix", GpuProgramParameters::ACT_WORLD_MATRIX); - params->setNamedAutoConstant("viewProjMatrix", GpuProgramParameters::ACT_VIEWPROJ_MATRIX); - params->setNamedAutoConstant("lodMorph", GpuProgramParameters::ACT_CUSTOM, - Terrain::LOD_MORPH_CUSTOM_PARAM); - - if (prof->isShadowingEnabled(tt, terrain)) - { - uint numTextures = 1; - if (prof->getReceiveDynamicShadowsPSSM()) - { - numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); - } - for (uint i = 0; i < numTextures; ++i) - { - params->setNamedAutoConstant("texViewProjMatrix" + StringConverter::toString(i), - GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i); - if (prof->getReceiveDynamicShadowsDepth()) - { - //params->setNamedAutoConstant("depthRange" + StringConverter::toString(i), - //GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i); - } - } - } - - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::defaultFpParams( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog) - { - GpuProgramParametersSharedPtr params = prog->getDefaultParameters(); - params->setIgnoreMissingParams(true); - - params->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR); - - for (int i=0; igetNumberOfLightsSupported(); ++i) - { - params->setNamedAutoConstant("lightPosObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i); - params->setNamedAutoConstant("lightDiffuseColour"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i); - if (i > 0) - params->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i); - //params->setNamedAutoConstant("lightSpecularColour"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, i); - } - - if (MWRender::RenderingManager::useMRT()) - params->setNamedAutoConstant("far", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE); - - params->setNamedAutoConstant("eyePosObjSpace", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); - params->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR); - params->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS); - - if (prof->isShadowingEnabled(tt, terrain)) - { - params->setNamedConstant("shadowFar_fadeStart", Vector4(prof->mShadowFar, prof->mShadowFadeStart * prof->mShadowFar, 0, 0)); - uint numTextures = 1; - if (prof->getReceiveDynamicShadowsPSSM()) - { - PSSMShadowCameraSetup* pssm = prof->getReceiveDynamicShadowsPSSM(); - numTextures = pssm->getSplitCount(); - Vector4 splitPoints; - const PSSMShadowCameraSetup::SplitPointList& splitPointList = pssm->getSplitPoints(); - // Populate from split point 1, not 0, since split 0 isn't useful (usually 0) - for (uint i = 1; i < numTextures; ++i) - { - splitPoints[i-1] = splitPointList[i]; - } - params->setNamedConstant("pssmSplitPoints", splitPoints); - } - - if (prof->getReceiveDynamicShadowsDepth()) - { - size_t samplerOffset = (tt == HIGH_LOD) ? mShadowSamplerStartHi : mShadowSamplerStartLo; - for (uint i = 0; i < numTextures; ++i) - { - params->setNamedAutoConstant("inverseShadowmapSize" + StringConverter::toString(i), - GpuProgramParameters::ACT_INVERSE_TEXTURE_SIZE, i + samplerOffset); - } - } - } - - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::updateParams( - const SM2Profile* prof, const MaterialPtr& mat, const Terrain* terrain, bool compositeMap) - { - Pass* p = mat->getTechnique(0)->getPass(0); - if (compositeMap) - { - updateVpParams(prof, terrain, RENDER_COMPOSITE_MAP, p->getVertexProgramParameters()); - updateFpParams(prof, terrain, RENDER_COMPOSITE_MAP, p->getFragmentProgramParameters()); - } - else - { - // high lod - updateVpParams(prof, terrain, HIGH_LOD, p->getVertexProgramParameters()); - updateFpParams(prof, terrain, HIGH_LOD, p->getFragmentProgramParameters()); - - if(prof->isCompositeMapEnabled()) - { - // low lod - p = mat->getTechnique(1)->getPass(0); - updateVpParams(prof, terrain, LOW_LOD, p->getVertexProgramParameters()); - updateFpParams(prof, terrain, LOW_LOD, p->getFragmentProgramParameters()); - } - } - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::updateVpParams( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params) - { - params->setIgnoreMissingParams(true); - uint maxLayers = prof->getMaxLayers(terrain); - uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); - uint numUVMul = numLayers / 4; - if (numLayers % 4) - ++numUVMul; - for (uint i = 0; i < numUVMul; ++i) - { - Vector4 uvMul( - terrain->getLayerUVMultiplier(i * 4), - terrain->getLayerUVMultiplier(i * 4 + 1), - terrain->getLayerUVMultiplier(i * 4 + 2), - terrain->getLayerUVMultiplier(i * 4 + 3) - ); - params->setNamedConstant("uvMul" + StringConverter::toString(i), uvMul); - } - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::updateFpParams( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params) - { - params->setIgnoreMissingParams(true); - // TODO - parameterise this? - Vector4 scaleBiasSpecular(0.03, -0.04, 32, 1); - params->setNamedConstant("scaleBiasSpecular", scaleBiasSpecular); - - } - //--------------------------------------------------------------------- - String TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::getChannel(uint idx) - { - uint rem = idx % 4; - switch(rem) - { - case 0: - default: - return "r"; - case 1: - return "g"; - case 2: - return "b"; - case 3: - return "a"; - }; - } - //--------------------------------------------------------------------- - String TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::getVertexProgramName( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) - { - String progName = terrain->getMaterialName() + "/sm2/vp"; - - switch(tt) - { - case HIGH_LOD: - progName += "/hlod"; - break; - case LOW_LOD: - progName += "/llod"; - break; - case RENDER_COMPOSITE_MAP: - progName += "/comp"; - break; - } - - return progName; - - } - //--------------------------------------------------------------------- - String TerrainMaterialGeneratorB::SM2Profile::ShaderHelper::getFragmentProgramName( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) - { - - String progName = terrain->getMaterialName() + "/sm2/fp"; - - switch(tt) - { - case HIGH_LOD: - progName += "/hlod"; - break; - case LOW_LOD: - progName += "/llod"; - break; - case RENDER_COMPOSITE_MAP: - progName += "/comp"; - break; - } - - return progName; - } - //--------------------------------------------------------------------- - //--------------------------------------------------------------------- - HighLevelGpuProgramPtr - TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::createVertexProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) - { - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getVertexProgramName(prof, terrain, tt); - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_VERTEX_PROGRAM); - } - else - { - ret->unload(); - } - - ret->setParameter("profiles", "vs_3_0 vs_2_0 vp40 arbvp1"); - ret->setParameter("entry_point", "main_vp"); - - return ret; - - } - //--------------------------------------------------------------------- - HighLevelGpuProgramPtr - TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::createFragmentProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) - { - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getFragmentProgramName(prof, terrain, tt); - - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", GPT_FRAGMENT_PROGRAM); - } - else - { - ret->unload(); - } - - ret->setParameter("profiles", "ps_3_0 ps_2_x fp40 arbfp1"); - ret->setParameter("entry_point", "main_fp"); - - return ret; - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateVpHeader( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) - { - outStream << - "void main_vp(\n" - "float4 pos : POSITION,\n" - "float2 uv : TEXCOORD0,\n"; - if (tt != RENDER_COMPOSITE_MAP) - outStream << "float2 delta : TEXCOORD1,\n"; // lodDelta, lodThreshold - - outStream << - "uniform float4x4 worldMatrix,\n" - "uniform float4x4 viewProjMatrix,\n" - "uniform float2 lodMorph,\n"; // morph amount, morph LOD target - - // uv multipliers - uint maxLayers = prof->getMaxLayers(terrain); - uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); - uint numUVMultipliers = (numLayers / 4); - if (numLayers % 4) - ++numUVMultipliers; - for (uint i = 0; i < numUVMultipliers; ++i) - outStream << "uniform float4 uvMul" << i << ", \n"; - - outStream << - "out float4 oPos : POSITION,\n" - "out float4 oPosObj : TEXCOORD0 \n"; - - uint texCoordSet = 1; - outStream << - ", out float4 oUVMisc : COLOR0 // xy = uv, z = camDepth\n"; - - // layer UV's premultiplied, packed as xy/zw - uint numUVSets = numLayers / 2; - if (numLayers % 2) - ++numUVSets; - if (tt != LOW_LOD) - { - for (uint i = 0; i < numUVSets; ++i) - { - outStream << - ", out float4 oUV" << i << " : TEXCOORD" << texCoordSet++ << "\n"; - } - } - - if (prof->getParent()->getDebugLevel() && tt != RENDER_COMPOSITE_MAP) - { - outStream << ", out float2 lodInfo : TEXCOORD" << texCoordSet++ << "\n"; - } - - if (prof->isShadowingEnabled(tt, terrain)) - { - texCoordSet = generateVpDynamicShadowsParams(texCoordSet, prof, terrain, tt, outStream); - } - - // check we haven't exceeded texture coordinates - if (texCoordSet > 8) - { - OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, - "Requested options require too many texture coordinate sets! Try reducing the number of layers. requested: " + StringConverter::toString(texCoordSet), - __FUNCTION__); - } - - outStream << - ")\n" - "{\n" - " float4 worldPos = mul(worldMatrix, pos);\n" - " oPosObj = pos;\n"; - - if (tt != RENDER_COMPOSITE_MAP) - { - // determine whether to apply the LOD morph to this vertex - // we store the deltas against all vertices so we only want to apply - // the morph to the ones which would disappear. The target LOD which is - // being morphed to is stored in lodMorph.y, and the LOD at which - // the vertex should be morphed is stored in uv.w. If we subtract - // the former from the latter, and arrange to only morph if the - // result is negative (it will only be -1 in fact, since after that - // the vertex will never be indexed), we will achieve our aim. - // sign(vertexLOD - targetLOD) == -1 is to morph - outStream << - " float toMorph = -min(0, sign(delta.y - lodMorph.y));\n"; - // this will either be 1 (morph) or 0 (don't morph) - if (prof->getParent()->getDebugLevel()) - { - // x == LOD level (-1 since value is target level, we want to display actual) - outStream << "lodInfo.x = (lodMorph.y - 1) / " << terrain->getNumLodLevels() << ";\n"; - // y == LOD morph - outStream << "lodInfo.y = toMorph * lodMorph.x;\n"; - } - - // morph - switch (terrain->getAlignment()) - { - case Terrain::ALIGN_X_Y: - outStream << " worldPos.z += delta.x * toMorph * lodMorph.x;\n"; - break; - case Terrain::ALIGN_X_Z: - outStream << " worldPos.y += delta.x * toMorph * lodMorph.x;\n"; - break; - case Terrain::ALIGN_Y_Z: - outStream << " worldPos.x += delta.x * toMorph * lodMorph.x;\n"; - break; - }; - } - - - // generate UVs - if (tt != LOW_LOD) - { - for (uint i = 0; i < numUVSets; ++i) - { - uint layer = i * 2; - uint uvMulIdx = layer / 4; - - outStream << - " oUV" << i << ".xy = " << " uv.xy * uvMul" << uvMulIdx << "." << getChannel(layer) << ";\n"; - outStream << - " oUV" << i << ".zw = " << " uv.xy * uvMul" << uvMulIdx << "." << getChannel(layer+1) << ";\n"; - - } - - } - - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateFpHeader( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) - { - - // Main header - outStream << - // helpers - "float4 expand(float4 v)\n" - "{ \n" - " return v * 2 - 1;\n" - "}\n\n\n"; - - if (prof->isShadowingEnabled(tt, terrain)) - generateFpDynamicShadowsHelpers(prof, terrain, tt, outStream); - - - outStream << - "void main_fp(\n" - "float4 position : TEXCOORD0,\n"; - - uint texCoordSet = 1; - outStream << - "float4 uvMisc : COLOR0,\n"; - - // UV's premultiplied, packed as xy/zw - uint maxLayers = prof->getMaxLayers(terrain); - uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()); - uint numLayers = std::min(maxLayers, static_cast(terrain->getLayerCount())); - uint numUVSets = numLayers / 2; - if (numLayers % 2) - ++numUVSets; - if (tt != LOW_LOD) - { - for (uint i = 0; i < numUVSets; ++i) - { - outStream << - "float4 layerUV" << i << " : TEXCOORD" << texCoordSet++ << ", \n"; - } - - } - if (prof->getParent()->getDebugLevel() && tt != RENDER_COMPOSITE_MAP) - { - outStream << "float2 lodInfo : TEXCOORD" << texCoordSet++ << ", \n"; - } - - bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP; - if (fog) - { - outStream << - "uniform float4 fogParams, \n" - "uniform float3 fogColour, \n"; - } - - uint currentSamplerIdx = 0; - - outStream << - // Only 1 light supported in this version - // deferred shading profile / generator later, ok? :) - "uniform float3 ambient,\n"; - - - for (int i=0; igetNumberOfLightsSupported(); ++i) - { - outStream << - "uniform float4 lightPosObjSpace"< 0) - outStream << - "uniform float4 lightAttenuation"<isGlobalColourMapEnabled()) - { - outStream << ", uniform sampler2D globalColourMap : register(s" - << currentSamplerIdx++ << ")\n"; - } - if (prof->isLightmapEnabled()) - { - outStream << ", uniform sampler2D lightMap : register(s" - << currentSamplerIdx++ << ")\n"; - } - // Blend textures - sampler definitions - for (uint i = 0; i < numBlendTextures; ++i) - { - outStream << ", uniform sampler2D blendTex" << i - << " : register(s" << currentSamplerIdx++ << ")\n"; - } - - // Layer textures - sampler definitions & UV multipliers - for (uint i = 0; i < numLayers; ++i) - { - outStream << ", uniform sampler2D difftex" << i - << " : register(s" << currentSamplerIdx++ << ")\n"; - - if (prof->mLayerNormalMappingEnabled || prof->mLayerParallaxMappingEnabled) - outStream << ", uniform sampler2D normtex" << i - << " : register(s" << currentSamplerIdx++ << ")\n"; - } - } - - if (prof->isShadowingEnabled(tt, terrain)) - { - generateFpDynamicShadowsParams(&texCoordSet, ¤tSamplerIdx, prof, terrain, tt, outStream); - } - - // check we haven't exceeded samplers - if (currentSamplerIdx > 16) - { - OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, - "Requested options require too many texture samplers! Try reducing the number of layers.", - __FUNCTION__); - } - - if (MWRender::RenderingManager::useMRT()) outStream << - " , out float4 oColor : COLOR \n" - " , out float4 oColor1 : COLOR1 \n" - " , uniform float far \n"; - else outStream << - " , out float4 oColor : COLOR \n"; - - outStream << - ")\n" - "{\n" - " float4 outputCol;\n" - " float shadow = 1.0;\n" - " float2 uv = uvMisc.xy;\n" - // base colour - " outputCol = float4(0,0,0,1);\n"; - - if (tt != LOW_LOD) - { - outStream << - // global normal - " float3 normal = expand(tex2D(globalNormal, uv)).rgb;\n"; - - // not needed anymore apparently - //" normal = float3(normal.x, normal.z, -normal.y); \n"; // convert Ogre to MW coordinate system - - } - - for (int i=0; igetNumberOfLightsSupported(); ++i) - outStream << - " float3 lightDir"<isLayerNormalMappingEnabled()) - { - // derive the tangent space basis - // we do this in the pixel shader because we don't have per-vertex normals - // because of the LOD, we use a normal map - // tangent is always +x or -z in object space depending on alignment - switch(terrain->getAlignment()) - { - case Terrain::ALIGN_X_Y: - case Terrain::ALIGN_X_Z: - outStream << " float3 tangent = float3(1, 0, 0);\n"; - break; - case Terrain::ALIGN_Y_Z: - outStream << " float3 tangent = float3(0, 0, -1);\n"; - break; - }; - - outStream << " float3 binormal = normalize(cross(tangent, normal));\n"; - // note, now we need to re-cross to derive tangent again because it wasn't orthonormal - outStream << " tangent = normalize(cross(normal, binormal));\n"; - // derive final matrix - outStream << " float3x3 TBN = float3x3(tangent, binormal, normal);\n"; - - // set up lighting result placeholders for interpolation - outStream << " float4 litRes, litResLayer;\n"; - outStream << " float3 TSlightDir, TSeyeDir, TShalfAngle, TSnormal;\n"; - if (prof->isLayerParallaxMappingEnabled()) - outStream << " float displacement;\n"; - // move - outStream << " TSlightDir = normalize(mul(TBN, lightDir));\n"; - outStream << " TSeyeDir = normalize(mul(TBN, eyeDir));\n"; - - } - else - { - if (prof->getNumberOfLightsSupported() > 1) - outStream << "float d; \n" - "float attn; \n"; - - outStream << - " eyeDir = normalize(eyeDir); \n"; - - // simple per-pixel lighting with no normal mapping - for (int i=0; igetNumberOfLightsSupported(); ++i) - { - outStream << - " float4 litRes"< 0) - outStream << - // pre-multiply light color with attenuation factor - "d = length( lightDir"<_isSM3Available()) - outStream << " if (" << blendWeightStr << " > 0.0003)\n { \n"; - - - // generate UV - outStream << " float2 uv" << layer << " = layerUV" << uvIdx << uvChannels << ";\n"; - - // calculate lighting here if normal mapping - if (prof->isLayerNormalMappingEnabled()) - { - if (prof->isLayerParallaxMappingEnabled() && tt != RENDER_COMPOSITE_MAP) - { - // modify UV - note we have to sample an extra time - outStream << " displacement = tex2D(normtex" << layer << ", uv" << layer << ").a\n" - " * scaleBiasSpecular.x + scaleBiasSpecular.y;\n"; - outStream << " uv" << layer << " += TSeyeDir.xy * displacement;\n"; - } - - // access TS normal map - outStream << " TSnormal = expand(tex2D(normtex" << layer << ", uv" << layer << ")).rgb;\n"; - outStream << " TShalfAngle = normalize(TSlightDir + TSeyeDir);\n"; - outStream << " litResLayer = lit(dot(TSlightDir, TSnormal), dot(TShalfAngle, TSnormal), scaleBiasSpecular.z);\n"; - if (!layer) - outStream << " litRes = litResLayer;\n"; - else - outStream << " litRes = lerp(litRes, litResLayer, " << blendWeightStr << ");\n"; - - } - - // sample diffuse texture - outStream << " float4 diffuseSpecTex" << layer - << " = tex2D(difftex" << layer << ", uv" << layer << ");\n"; - - // apply to common - if (!layer) - { - outStream << " diffuse = diffuseSpecTex0.rgb;\n"; - if (prof->isLayerSpecularMappingEnabled()) - outStream << " specular = diffuseSpecTex0.a;\n"; - } - else - { - outStream << " diffuse = lerp(diffuse, diffuseSpecTex" << layer - << ".rgb, " << blendWeightStr << ");\n"; - if (prof->isLayerSpecularMappingEnabled()) - outStream << " specular = lerp(specular, diffuseSpecTex" << layer - << ".a, " << blendWeightStr << ");\n"; - - } - - // End early-out - // Disable - causing some issues even when trying to force the use of texldd - - // comment by scrawl: - // on a NVIDIA card in opengl mode, didn't produce any problems, - // while increasing FPS from 170 to 185 (!!!) in the same area - // so let's try this out - if something does cause problems for - // someone else (with a different card / renderer) we can just - // add a vendor-specific check here - if (layer && prof->_isSM3Available()) - outStream << " } // early-out blend value\n"; - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateVpFooter( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) - { - - outStream << - " oPos = mul(viewProjMatrix, worldPos);\n" - " oUVMisc.xy = uv.xy;\n"; - - outStream << - " // pass cam depth\n" - " oPosObj.w = oPos.z;\n"; - - if (prof->isShadowingEnabled(tt, terrain)) - generateVpDynamicShadows(prof, terrain, tt, outStream); - - outStream << - "}\n"; - - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateFpFooter( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) - { - - if (tt == LOW_LOD) - { - if (prof->isShadowingEnabled(tt, terrain)) - { - generateFpDynamicShadows(prof, terrain, tt, outStream); - outStream << - " outputCol.rgb = diffuse * rtshadow;\n"; - } - else - { - outStream << - " outputCol.rgb = diffuse;\n"; - } - } - else - { - if (prof->isGlobalColourMapEnabled()) - { - // sample colour map and apply to diffuse - outStream << " diffuse *= tex2D(globalColourMap, uv).rgb;\n"; - } - if (prof->isLightmapEnabled()) - { - // sample lightmap - outStream << " shadow = tex2D(lightMap, uv).r;\n"; - } - - if (prof->isShadowingEnabled(tt, terrain)) - { - generateFpDynamicShadows(prof, terrain, tt, outStream); - } - - outStream << " outputCol.rgb += ambient * diffuse; \n"; - - // diffuse lighting - for (int i=0; igetNumberOfLightsSupported(); ++i) - { - // shadows only for first light (directional) - if (i==0) - outStream << " outputCol.rgb += litRes"<isLayerSpecularMappingEnabled()) - outStream << " specular = 0.0;\n"; - - if (tt == RENDER_COMPOSITE_MAP) - { - // Lighting embedded in alpha - outStream << - " outputCol.a = shadow;\n"; - - } - else - { - // Apply specular - //outStream << " outputCol.rgb += litRes.z * lightSpecularColour * specular * shadow;\n"; - - if (prof->getParent()->getDebugLevel()) - { - outStream << " outputCol.rg += lodInfo.xy;\n"; - } - } - } - - bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP; - if (fog) - { - if (terrain->getSceneManager()->getFogMode() == FOG_LINEAR) - { - outStream << - " float fogVal = saturate((position.w - fogParams.y) * fogParams.w);\n"; - } - else - { - outStream << - " float fogVal = saturate(1 / (exp(position.w * fogParams.x)));\n"; - } - outStream << " outputCol.rgb = lerp(outputCol.rgb, fogColour, fogVal);\n"; - } - - // Final return - outStream << " oColor = outputCol;\n"; - - if (MWRender::RenderingManager::useMRT()) outStream << - " oColor1 = float4(position.w / far, 0, 0, 1); \n"; - - outStream - << "}\n"; - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateFpDynamicShadowsHelpers( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) - { - // TODO make filtering configurable - outStream << - "// Simple PCF \n" - "// Number of samples in one dimension (square for total samples) \n" - "#define NUM_SHADOW_SAMPLES_1D 1.0 \n" - "#define SHADOW_FILTER_SCALE 1 \n" - - "#define SHADOW_SAMPLES NUM_SHADOW_SAMPLES_1D*NUM_SHADOW_SAMPLES_1D \n" - - "float4 offsetSample(float4 uv, float2 offset, float invMapSize) \n" - "{ \n" - " return float4(uv.xy + offset * invMapSize * uv.w, uv.z, uv.w); \n" - "} \n"; - - if (prof->getReceiveDynamicShadowsDepth()) - { - outStream << - "float calcDepthShadow(sampler2D shadowMap, float4 shadowMapPos, float2 offset) \n" - " { \n" - " shadowMapPos = shadowMapPos / shadowMapPos.w; \n" - " float2 uv = shadowMapPos.xy; \n" - " float3 o = float3(offset, -offset.x) * 0.3f; \n" - " // Note: We using 2x2 PCF. Good enough and is alot faster. \n" - " float c = (shadowMapPos.z <= tex2D(shadowMap, uv.xy - o.xy).r) ? 1 : 0; // top left \n" - " c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy + o.xy).r) ? 1 : 0; // bottom right \n" - " c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy + o.zy).r) ? 1 : 0; // bottom left \n" - " c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy - o.zy).r) ? 1 : 0; // top right \n" - " return c / 4; \n" - " } \n"; - } - else - { - outStream << - "float calcSimpleShadow(sampler2D shadowMap, float4 shadowMapPos) \n" - "{ \n" - " return tex2Dproj(shadowMap, shadowMapPos).x; \n" - "} \n"; - - } - - if (prof->getReceiveDynamicShadowsPSSM()) - { - uint numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); - - - if (prof->getReceiveDynamicShadowsDepth()) - { - outStream << - "float calcPSSMDepthShadow("; - } - else - { - outStream << - "float calcPSSMSimpleShadow("; - } - - outStream << "\n "; - for (uint i = 0; i < numTextures; ++i) - outStream << "sampler2D shadowMap" << i << ", "; - outStream << "\n "; - for (uint i = 0; i < numTextures; ++i) - outStream << "float4 lsPos" << i << ", "; - if (prof->getReceiveDynamicShadowsDepth()) - { - outStream << "\n "; - for (uint i = 0; i < numTextures; ++i) - outStream << "float2 invShadowmapSize" << i << ", "; - } - outStream << "\n" - " float4 pssmSplitPoints, float camDepth) \n" - "{ \n" - " float shadow; \n" - " // calculate shadow \n"; - - for (uint i = 0; i < numTextures; ++i) - { - if (!i) - outStream << " if (camDepth <= pssmSplitPoints." << ShaderHelper::getChannel(i) << ") \n"; - else if (i < numTextures - 1) - outStream << " else if (camDepth <= pssmSplitPoints." << ShaderHelper::getChannel(i) << ") \n"; - else - outStream << " else \n"; - - outStream << - " { \n"; - if (prof->getReceiveDynamicShadowsDepth()) - { - outStream << - " shadow = calcDepthShadow(shadowMap" << i << ", lsPos" << i << ", invShadowmapSize" << i << ".xy); \n"; - } - else - { - outStream << - " shadow = calcSimpleShadow(shadowMap" << i << ", lsPos" << i << "); \n"; - } - outStream << - " } \n"; - - } - - outStream << - " return shadow; \n" - "} \n\n\n"; - } - - - } - //--------------------------------------------------------------------- - uint TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateVpDynamicShadowsParams( - uint texCoord, const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) - { - // out semantics & params - uint numTextures = 1; - if (prof->getReceiveDynamicShadowsPSSM()) - { - numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); - } - for (uint i = 0; i < numTextures; ++i) - { - outStream << - ", out float4 oLightSpacePos" << i << " : TEXCOORD" << texCoord++ << " \n" << - ", uniform float4x4 texViewProjMatrix" << i << " \n"; - if (prof->getReceiveDynamicShadowsDepth()) - { - outStream << - ", uniform float4 depthRange" << i << " // x = min, y = max, z = range, w = 1/range \n"; - } - } - - return texCoord; - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateVpDynamicShadows( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) - { - uint numTextures = 1; - if (prof->getReceiveDynamicShadowsPSSM()) - { - numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); - } - - // Calculate the position of vertex in light space - for (uint i = 0; i < numTextures; ++i) - { - outStream << - " oLightSpacePos" << i << " = mul(texViewProjMatrix" << i << ", worldPos); \n"; - if (prof->getReceiveDynamicShadowsDepth()) - { - // make linear - //outStream << - // "oLightSpacePos" << i << ".z = (oLightSpacePos" << i << ".z - depthRange" << i << ".x) * depthRange" << i << ".w;\n"; - - } - } - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateFpDynamicShadowsParams( - uint* texCoord, uint* sampler, const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) - { - if (tt == HIGH_LOD) - mShadowSamplerStartHi = *sampler; - else if (tt == LOW_LOD) - mShadowSamplerStartLo = *sampler; - - // in semantics & params - uint numTextures = 1; - outStream << - ", uniform float4 shadowFar_fadeStart \n"; - if (prof->getReceiveDynamicShadowsPSSM()) - { - numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); - outStream << - ", uniform float4 pssmSplitPoints \n"; - } - for (uint i = 0; i < numTextures; ++i) - { - outStream << - ", float4 lightSpacePos" << i << " : TEXCOORD" << *texCoord << " \n" << - ", uniform sampler2D shadowMap" << i << " : register(s" << *sampler << ") \n"; - *sampler = *sampler + 1; - *texCoord = *texCoord + 1; - if (prof->getReceiveDynamicShadowsDepth()) - { - outStream << - ", uniform float4 inverseShadowmapSize" << i << " \n"; - } - } - - } - //--------------------------------------------------------------------- - void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateFpDynamicShadows( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) - { - if (prof->getReceiveDynamicShadowsPSSM()) - { - uint numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); - outStream << - " float camDepth = position.w;\n"; - - if (prof->getReceiveDynamicShadowsDepth()) - { - outStream << - " float rtshadow = calcPSSMDepthShadow("; - } - else - { - outStream << - " float rtshadow = calcPSSMSimpleShadow("; - } - for (uint i = 0; i < numTextures; ++i) - outStream << "shadowMap" << i << ", "; - outStream << "\n "; - - for (uint i = 0; i < numTextures; ++i) - outStream << "lightSpacePos" << i << ", "; - if (prof->getReceiveDynamicShadowsDepth()) - { - outStream << "\n "; - for (uint i = 0; i < numTextures; ++i) - outStream << "inverseShadowmapSize" << i << ".xy, "; - } - outStream << "\n" << - " pssmSplitPoints, camDepth);\n"; - - } - else - { - if (prof->getReceiveDynamicShadowsDepth()) - { - outStream << - " float rtshadow = calcDepthShadow(shadowMap0, lightSpacePos0, inverseShadowmapSize0.xy);"; - } - else - { - outStream << - " float rtshadow = calcSimpleShadow(shadowMap0, lightSpacePos0);"; - } - } - - outStream << - " float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; \n" - " float fade = 1-((position.w - shadowFar_fadeStart.y) / fadeRange); \n" - " rtshadow = (position.w > shadowFar_fadeStart.x) ? 1 : ((position.w > shadowFar_fadeStart.y) ? 1-((1-rtshadow)*fade) : rtshadow); \n" - " rtshadow = (1-(1-rtshadow)*0.6); \n" // make the shadow a little less intensive - " shadow = min(shadow, rtshadow);\n"; - - } - //--------------------------------------------------------------------- - //--------------------------------------------------------------------- - HighLevelGpuProgramPtr - TerrainMaterialGeneratorB::SM2Profile::ShaderHelperHLSL::createVertexProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) - { - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getVertexProgramName(prof, terrain, tt); - - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "hlsl", GPT_VERTEX_PROGRAM); - } - else - { - ret->unload(); - } - - if (prof->_isSM3Available()) - ret->setParameter("target", "vs_3_0"); - else - ret->setParameter("target", "vs_2_0"); - ret->setParameter("entry_point", "main_vp"); - - return ret; - - } - //--------------------------------------------------------------------- - HighLevelGpuProgramPtr - TerrainMaterialGeneratorB::SM2Profile::ShaderHelperHLSL::createFragmentProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) - { - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getFragmentProgramName(prof, terrain, tt); - - - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "hlsl", GPT_FRAGMENT_PROGRAM); - } - else - { - ret->unload(); - } - - if (prof->_isSM3Available()) - ret->setParameter("target", "ps_3_0"); - else - ret->setParameter("target", "ps_2_x"); - ret->setParameter("entry_point", "main_fp"); - - return ret; - - } - //--------------------------------------------------------------------- - //--------------------------------------------------------------------- - HighLevelGpuProgramPtr - TerrainMaterialGeneratorB::SM2Profile::ShaderHelperGLSL::createVertexProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) - { - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getVertexProgramName(prof, terrain, tt); - - switch(tt) - { - case HIGH_LOD: - progName += "/hlod"; - break; - case LOW_LOD: - progName += "/llod"; - break; - case RENDER_COMPOSITE_MAP: - progName += "/comp"; - break; - } - - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "glsl", GPT_VERTEX_PROGRAM); - } - else - { - ret->unload(); - } - - return ret; - - } - //--------------------------------------------------------------------- - HighLevelGpuProgramPtr - TerrainMaterialGeneratorB::SM2Profile::ShaderHelperGLSL::createFragmentProgram( - const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) - { - HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); - String progName = getFragmentProgramName(prof, terrain, tt); - - HighLevelGpuProgramPtr ret = mgr.getByName(progName); - if (ret.isNull()) - { - ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "glsl", GPT_FRAGMENT_PROGRAM); - } - else - { - ret->unload(); - } - - return ret; - - } + void TerrainMaterial::Profile::setGlobalColourMap (Ogre::Terrain* terrain, const std::string& name) + { + sh::Factory::getInstance ().setTextureAlias (terrain->getMaterialName () + "_colourMap", name); + } + + Ogre::MaterialPtr TerrainMaterial::Profile::generateForCompositeMap(const Ogre::Terrain* terrain) + { + throw std::runtime_error ("composite map not supported"); + } + + Ogre::uint8 TerrainMaterial::Profile::getMaxLayers(const Ogre::Terrain* terrain) const + { + // count the texture units free + Ogre::uint8 freeTextureUnits = 16; + // normalmap + --freeTextureUnits; + // colourmap + --freeTextureUnits; + freeTextureUnits -= 3; // shadow PSSM + + --freeTextureUnits; // caustics + + // each layer needs 1.25 units (1xdiffusespec, 0.25xblend) + return static_cast(freeTextureUnits / (1.25f)); + } + + void TerrainMaterial::Profile::updateParams(const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain) + { + } + + void TerrainMaterial::Profile::updateParamsForCompositeMap(const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain) + { + } + + void TerrainMaterial::Profile::requestOptions(Ogre::Terrain* terrain) + { + terrain->_setMorphRequired(true); + terrain->_setNormalMapRequired(true); // global normal map + terrain->_setLightMapRequired(false); + terrain->_setCompositeMapRequired(false); + } } diff --git a/apps/openmw/mwrender/terrainmaterial.hpp b/apps/openmw/mwrender/terrainmaterial.hpp index e94e20b7e9..3e31b2a584 100644 --- a/apps/openmw/mwrender/terrainmaterial.hpp +++ b/apps/openmw/mwrender/terrainmaterial.hpp @@ -26,246 +26,59 @@ THE SOFTWARE. ----------------------------------------------------------------------------- */ -#ifndef __Ogre_TerrainMaterialGeneratorB_H__ -#define __Ogre_TerrainMaterialGeneratorB_H__ +#ifndef MWRENDER_TERRAINMATERIAL_H +#define MWRENDER_TERRAINMATERIAL_H #include "OgreTerrainPrerequisites.h" #include "OgreTerrainMaterialGenerator.h" #include "OgreGpuProgramParams.h" -namespace Ogre +namespace sh { - class PSSMShadowCameraSetup; + class MaterialInstance; +} - /** \addtogroup Optional Components - * @{ - */ - /** \addtogroup Terrain - * Some details on the terrain component - * @{ - */ +namespace MWRender +{ + class TerrainMaterial : public Ogre::TerrainMaterialGenerator + { + public: - /** A TerrainMaterialGenerator which can cope with normal mapped, specular mapped - terrain. - @note Requires the Cg plugin to render correctly - */ - class TerrainMaterialGeneratorB : public TerrainMaterialGenerator - { - public: - TerrainMaterialGeneratorB(); - ~TerrainMaterialGeneratorB(); + class Profile : public Ogre::TerrainMaterialGenerator::Profile + { + public: + Profile(Ogre::TerrainMaterialGenerator* parent, const Ogre::String& name, const Ogre::String& desc); + virtual ~Profile(); - /** Shader model 2 profile target. - */ - class SM2Profile : public TerrainMaterialGenerator::Profile - { - public: - SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc); - ~SM2Profile(); + virtual bool isVertexCompressionSupported() const { return false; } - bool isVertexCompressionSupported() const {return false;} - - MaterialPtr generate(const Terrain* terrain); - MaterialPtr generateForCompositeMap(const Terrain* terrain); - uint8 getMaxLayers(const Terrain* terrain) const; - void updateParams(const MaterialPtr& mat, const Terrain* terrain); - void updateParamsForCompositeMap(const MaterialPtr& mat, const Terrain* terrain); - void requestOptions(Terrain* terrain); + virtual Ogre::MaterialPtr generate(const Ogre::Terrain* terrain); - void setShadowFar(float far); - void setShadowFadeStart(float fadestart); + virtual Ogre::MaterialPtr generateForCompositeMap(const Ogre::Terrain* terrain); - /** Whether to support normal mapping per layer in the shader (default true). - */ - bool isLayerNormalMappingEnabled() const { return mLayerNormalMappingEnabled; } - /** Whether to support normal mapping per layer in the shader (default true). - */ - void setLayerNormalMappingEnabled(bool enabled); - /** Whether to support parallax mapping per layer in the shader (default true). - */ - bool isLayerParallaxMappingEnabled() const { return mLayerParallaxMappingEnabled; } - /** Whether to support parallax mapping per layer in the shader (default true). - */ - void setLayerParallaxMappingEnabled(bool enabled); - /** Whether to support specular mapping per layer in the shader (default true). - */ - bool isLayerSpecularMappingEnabled() const { return mLayerSpecularMappingEnabled; } - /** Whether to support specular mapping per layer in the shader (default true). - */ - void setLayerSpecularMappingEnabled(bool enabled); - /** Whether to support a global colour map over the terrain in the shader, - if it's present (default true). - */ - bool isGlobalColourMapEnabled() const { return mGlobalColourMapEnabled; } - /** Whether to support a global colour map over the terrain in the shader, - if it's present (default true). - */ - void setGlobalColourMapEnabled(bool enabled); - /** Whether to support a light map over the terrain in the shader, - if it's present (default true). - */ - bool isLightmapEnabled() const { return mLightmapEnabled; } - /** Whether to support a light map over the terrain in the shader, - if it's present (default true). - */ - void setLightmapEnabled(bool enabled); - /** Whether to use the composite map to provide a lower LOD technique - in the distance (default true). - */ - bool isCompositeMapEnabled() const { return mCompositeMapEnabled; } - /** Whether to use the composite map to provide a lower LOD technique - in the distance (default true). - */ - void setCompositeMapEnabled(bool enabled); - /** Whether to support dynamic texture shadows received from other - objects, on the terrain (default true). - */ - bool getReceiveDynamicShadowsEnabled() const { return mReceiveDynamicShadows; } - /** Whether to support dynamic texture shadows received from other - objects, on the terrain (default true). - */ - void setReceiveDynamicShadowsEnabled(bool enabled); + virtual Ogre::uint8 getMaxLayers(const Ogre::Terrain* terrain) const; - /** Whether to use PSSM support dynamic texture shadows, and if so the - settings to use (default 0). - */ - void setReceiveDynamicShadowsPSSM(PSSMShadowCameraSetup* pssmSettings); - /** Whether to use PSSM support dynamic texture shadows, and if so the - settings to use (default 0). - */ - PSSMShadowCameraSetup* getReceiveDynamicShadowsPSSM() const { return mPSSM; } - /** Whether to use depth shadows (default false). - */ - void setReceiveDynamicShadowsDepth(bool enabled); - /** Whether to use depth shadows (default false). - */ - bool getReceiveDynamicShadowsDepth() const { return mDepthShadows; } - /** Whether to use shadows on low LOD material rendering (when using composite map) (default false). - */ - void setReceiveDynamicShadowsLowLod(bool enabled); - /** Whether to use shadows on low LOD material rendering (when using composite map) (default false). - */ - bool getReceiveDynamicShadowsLowLod() const { return mLowLodShadows; } + virtual void updateParams(const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain); - int getNumberOfLightsSupported() const; + virtual void updateParamsForCompositeMap(const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain); - /// Internal - bool _isSM3Available() const { return mSM3Available; } - - protected: + virtual void requestOptions(Ogre::Terrain* terrain); - enum TechniqueType - { - HIGH_LOD, - LOW_LOD, - RENDER_COMPOSITE_MAP - }; - void addTechnique(const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt); + void setGlobalColourMapEnabled(bool enabled); + void setGlobalColourMap (Ogre::Terrain* terrain, const std::string& name); - /// Interface definition for helper class to generate shaders - class ShaderHelper : public TerrainAlloc - { - public: - ShaderHelper() : mShadowSamplerStartHi(0), mShadowSamplerStartLo(0) {} - virtual ~ShaderHelper() {} - virtual HighLevelGpuProgramPtr generateVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - virtual HighLevelGpuProgramPtr generateFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - virtual void updateParams(const SM2Profile* prof, const MaterialPtr& mat, const Terrain* terrain, bool compositeMap); - protected: - virtual String getVertexProgramName(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - virtual String getFragmentProgramName(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - virtual HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) = 0; - virtual HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) = 0; - virtual void generateVertexProgramSource(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - virtual void generateFragmentProgramSource(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - virtual void generateVpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0; - virtual void generateFpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0; - virtual void generateVpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) = 0; - virtual void generateFpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) = 0; - virtual void generateVpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0; - virtual void generateFpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0; - virtual void defaultVpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog); - virtual void defaultFpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog); - virtual void updateVpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params); - virtual void updateFpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params); - static String getChannel(uint idx); + private: + sh::MaterialInstance* mMaterial; - size_t mShadowSamplerStartHi; - size_t mShadowSamplerStartLo; + bool mGlobalColourMap; - }; - - /// Utility class to help with generating shaders for Cg / HLSL. - class ShaderHelperCg : public ShaderHelper - { - protected: - HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - void generateVpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateFpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateVpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream); - void generateFpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream); - void generateVpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateFpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - uint generateVpDynamicShadowsParams(uint texCoordStart, const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateVpDynamicShadows(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateFpDynamicShadowsHelpers(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateFpDynamicShadowsParams(uint* texCoord, uint* sampler, const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - void generateFpDynamicShadows(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream); - }; - - class ShaderHelperHLSL : public ShaderHelperCg - { - protected: - HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - }; - - /// Utility class to help with generating shaders for GLSL. - class ShaderHelperGLSL : public ShaderHelper - { - protected: - HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); - void generateVpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {} - void generateFpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {} - void generateVpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) {} - void generateFpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) {} - void generateVpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {} - void generateFpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {} - }; - - ShaderHelper* mShaderGen; - bool mLayerNormalMappingEnabled; - bool mLayerParallaxMappingEnabled; - bool mLayerSpecularMappingEnabled; - bool mGlobalColourMapEnabled; - bool mLightmapEnabled; - bool mCompositeMapEnabled; - bool mReceiveDynamicShadows; - PSSMShadowCameraSetup* mPSSM; - bool mDepthShadows; - bool mLowLodShadows; - bool mSM3Available; - float mShadowFar; - float mShadowFadeStart; - - bool isShadowingEnabled(TechniqueType tt, const Terrain* terrain) const; - - }; - - - - - }; - - - - /** @} */ - /** @} */ + }; + TerrainMaterial(); + }; } + #endif diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 94fb3d6d98..1c0afab67e 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -8,11 +8,20 @@ #include #include #include +#include +#include +#include #include "sky.hpp" #include "renderingmanager.hpp" #include "compositors.hpp" +#include +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + using namespace Ogre; namespace MWRender @@ -22,10 +31,18 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mCamera (camera), mSceneManager (camera->getSceneManager()), mIsUnderwater(false), mVisibilityFlags(0), mReflectionTarget(0), mActive(1), mToggled(1), - mReflectionRenderActive(false), mRendering(rend) + mReflectionRenderActive(false), mRendering(rend), + mOldFarClip(0), mOldFarClip2(0), + mWaterTimer(0.f) { mSky = rend->getSkyManager(); + sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty(new sh::Vector3(0.5, -0.8, 0.2))); + sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty(new sh::FloatValue(0))); + sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty(new sh::Vector2(1, 0.6))); + + mMaterial = MaterialManager::getSingleton().getByName("Water"); + mTop = cell->water; mIsUnderwater = false; @@ -40,7 +57,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel mWater->setCastShadows(false); mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode(); - mWaterNode->setPosition(0, mTop, 0); mReflectionCamera = mSceneManager->createCamera("ReflectionCamera"); @@ -53,27 +69,36 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel applyRTT(); applyVisibilityMask(); - - createMaterial(); mWater->setMaterial(mMaterial); - mUnderwaterEffect = Settings::Manager::getBool("underwater effect", "Water"); + Ogre::Entity* underwaterDome = mSceneManager->createEntity ("underwater_dome.mesh"); + underwaterDome->setRenderQueueGroup (RQG_UnderWater); + mUnderwaterDome = mSceneManager->getRootSceneNode ()->createChildSceneNode (); + mUnderwaterDome->attachObject (underwaterDome); + mUnderwaterDome->setScale(10000,10000,10000); + mUnderwaterDome->setVisible(false); + underwaterDome->setMaterialName("Underwater_Dome"); mSceneManager->addRenderQueueListener(this); assignTextures(); + setHeight(mTop); + + sh::MaterialInstance* m = sh::Factory::getInstance ().getMaterialInstance ("Water"); + m->setListener (this); + // ---------------------------------------------------------------------------------------------- // ---------------------------------- reflection debug overlay ---------------------------------- // ---------------------------------------------------------------------------------------------- - /* +/* if (Settings::Manager::getBool("shader", "Water")) { OverlayManager& mgr = OverlayManager::getSingleton(); Overlay* overlay; // destroy if already exists - if (overlay = mgr.getByName("ReflectionDebugOverlay")) + if ((overlay = mgr.getByName("ReflectionDebugOverlay"))) mgr.destroy(overlay); overlay = mgr.create("ReflectionDebugOverlay"); @@ -85,18 +110,17 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false); - TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName()); - t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); + debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(mReflectionTexture->getName()); OverlayContainer* debugPanel; // destroy container if exists try { - if (debugPanel = + if ((debugPanel = static_cast( mgr.getOverlayElement("Ogre/ReflectionDebugTexPanel" - ))) + )))) mgr.destroyOverlayElement(debugPanel); } catch (Ogre::Exception&) {} @@ -110,13 +134,15 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel overlay->add2D(debugPanel); overlay->show(); } - */ +*/ } void Water::setActive(bool active) { mActive = active; updateVisible(); + + sh::Factory::getInstance ().setSharedParameter ("waterEnabled", sh::makeProperty (new sh::FloatValue(active ? 1.0 : 0.0))); } Water::~Water() @@ -144,8 +170,14 @@ void Water::changeCell(const ESM::Cell* cell) void Water::setHeight(const float height) { mTop = height; + mWaterPlane = Plane(Vector3::UNIT_Y, height); + + // small error due to reflection texture size & reflection distortion + mErrorPlane = Plane(Vector3::UNIT_Y, height - 5); + mWaterNode->setPosition(0, height, 0); + sh::Factory::getInstance ().setSharedParameter ("waterLevel", sh::makeProperty(new sh::FloatValue(height))); } void Water::toggle() @@ -158,36 +190,16 @@ void Water::checkUnderwater(float y) { if (!mActive) { - mRendering->getCompositors()->setCompositorEnabled(mCompositorName, false); return; } if ((mIsUnderwater && y > mTop) || !mWater->isVisible() || mCamera->getPolygonMode() != Ogre::PM_SOLID) { - mRendering->getCompositors()->setCompositorEnabled(mCompositorName, false); - - // tell the shader we are not underwater - Ogre::Pass* pass = mMaterial->getTechnique(0)->getPass(0); - if (pass->hasFragmentProgram() && pass->getFragmentProgramParameters()->_findNamedConstantDefinition("isUnderwater", false)) - pass->getFragmentProgramParameters()->setNamedConstant("isUnderwater", Real(0)); - - mWater->setRenderQueueGroup(RQG_Water); - mIsUnderwater = false; } if (!mIsUnderwater && y < mTop && mWater->isVisible() && mCamera->getPolygonMode() == Ogre::PM_SOLID) { - if (mUnderwaterEffect) - mRendering->getCompositors()->setCompositorEnabled(mCompositorName, true); - - // tell the shader we are underwater - Ogre::Pass* pass = mMaterial->getTechnique(0)->getPass(0); - if (pass->hasFragmentProgram() && pass->getFragmentProgramParameters()->_findNamedConstantDefinition("isUnderwater", false)) - pass->getFragmentProgramParameters()->setNamedConstant("isUnderwater", Real(1)); - - mWater->setRenderQueueGroup(RQG_UnderWater); - mIsUnderwater = true; } @@ -211,12 +223,11 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt) mReflectionCamera->setFOVy(mCamera->getFOVy()); mReflectionRenderActive = true; - /// \todo For some reason this camera is delayed for 1 frame, which causes ugly sky reflection behaviour.. - /// to circumvent this we just scale the sky up, so it's not that noticable + /// \todo the reflection render (and probably all renderingmanager-updates) lag behind 1 camera frame for some reason Vector3 pos = mCamera->getRealPosition(); pos.y = mTop*2 - pos.y; mSky->setSkyPosition(pos); - mSky->scaleSky(mCamera->getFarClipDistance() / 5000.f); + mSky->scaleSky(mCamera->getFarClipDistance() / 50.f); mReflectionCamera->enableReflection(mWaterPlane); } } @@ -233,48 +244,18 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt) } } -void Water::createMaterial() -{ - if (mReflectionTarget == 0) - { - mMaterial = MaterialManager::getSingleton().getByName("Water_Fallback"); - } - else - { - mMaterial = MaterialManager::getSingleton().getByName("Water"); - mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(mReflectionTexture); - } - - // these have to be set in code - std::string textureNames[32]; - for (int i=0; i<32; ++i) - { - textureNames[i] = "textures\\water\\water" + StringConverter::toString(i, 2, '0') + ".dds"; - } - Ogre::Technique* tech; - if (mReflectionTarget == 0) - tech = mMaterial->getTechnique(0); - else - tech = mMaterial->getTechnique(1); - - tech->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2); -} - void Water::assignTextures() { if (Settings::Manager::getBool("shader", "Water")) { + CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mRendering->getViewport())->getCompositor("gbuffer"); TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0); - TextureUnitState* tus = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState("refractionMap"); - if (tus != 0) - tus->setTexture(colorTexture); + sh::Factory::getInstance ().setTextureAlias ("WaterRefraction", colorTexture->getName()); TexturePtr depthTexture = compositor->getTextureInstance("mrt_output", 1); - tus = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState("depthMap"); - if (tus != 0) - tus->setTexture(depthTexture); + sh::Factory::getInstance ().setTextureAlias ("SceneDepth", depthTexture->getName()); } } @@ -288,7 +269,7 @@ void Water::updateVisible() { mWater->setVisible(mToggled && mActive); if (mReflectionTarget) - mReflectionTarget->setActive(mToggled && mActive && !mIsUnderwater); + mReflectionTarget->setActive(mToggled && mActive); } void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) @@ -296,22 +277,46 @@ void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &in // We don't want the sky to get clipped by custom near clip plane (the water plane) if (queueGroupId < 20 && mReflectionRenderActive) { + mOldFarClip = mReflectionCamera->getFarClipDistance (); mReflectionCamera->disableCustomNearClipPlane(); + mReflectionCamera->setFarClipDistance (1000000000); Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); } + else if (queueGroupId == RQG_UnderWater) + {/* + mOldFarClip2 = mCamera->getFarClipDistance (); + mCamera->setFarClipDistance (1000000000); + Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); + */} } void Water::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation) { if (queueGroupId < 20 && mReflectionRenderActive) { - mReflectionCamera->enableCustomNearClipPlane(mWaterPlane); + mReflectionCamera->setFarClipDistance (mOldFarClip); + if (!mIsUnderwater) + mReflectionCamera->enableCustomNearClipPlane(mErrorPlane); Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); } + if (queueGroupId == RQG_UnderWater) + { + /* + mCamera->setFarClipDistance (mOldFarClip2); + Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); + */} } -void Water::update() +void Water::update(float dt) { + Ogre::Vector3 pos = mCamera->getDerivedPosition (); + pos.y = -mWaterPlane.d; + mUnderwaterDome->setPosition (pos); + + mWaterTimer += dt / 30.0 * MWBase::Environment::get().getWorld()->getTimeScaleFactor(); + sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty(new sh::FloatValue(mWaterTimer))); + + mRendering->getSkyManager ()->setGlareEnabled (!mIsUnderwater); } void Water::applyRTT() @@ -336,14 +341,14 @@ void Water::applyRTT() vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f)); vp->setShadowsEnabled(false); // use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain) - //vp->setMaterialScheme("Fallback"); + vp->setMaterialScheme("water_reflection"); rtt->addListener(this); rtt->setActive(true); mReflectionTarget = rtt; - } - mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT"; + sh::Factory::getInstance ().setTextureAlias ("WaterReflection", mReflectionTexture->getName()); + } } void Water::applyVisibilityMask() @@ -386,7 +391,6 @@ void Water::processChangedSettings(const Settings::CategorySettingVector& settin { applyRTT(); applyVisibilityMask(); - createMaterial(); mWater->setMaterial(mMaterial); assignTextures(); } @@ -394,4 +398,29 @@ void Water::processChangedSettings(const Settings::CategorySettingVector& settin applyVisibilityMask(); } +void Water::requestedConfiguration (sh::MaterialInstance* m, const std::string& configuration) +{ +} + +void Water::createdConfiguration (sh::MaterialInstance* m, const std::string& configuration) +{ + if (configuration == "local_map" || !Settings::Manager::getBool("shader", "Water")) + { + // for simple water, set animated texture names + // these have to be set in code + std::string textureNames[32]; + for (int i=0; i<32; ++i) + { + textureNames[i] = "textures\\water\\water" + StringConverter::toString(i, 2, '0') + ".dds"; + } + + Ogre::Technique* t = static_cast(m->getMaterial())->getOgreTechniqueForConfiguration(configuration); + if (t->getPass(0)->getNumTextureUnitStates () == 0) + return; + t->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2); + t->getPass(0)->setDepthWriteEnabled (false); + t->getPass(0)->setSceneBlending (Ogre::SBT_TRANSPARENT_ALPHA); + } +} + } // namespace diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 71f261f2b0..60e39c4966 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -13,6 +13,8 @@ #include "renderconst.hpp" +#include + namespace Ogre { class Camera; @@ -29,21 +31,30 @@ namespace MWRender { class RenderingManager; /// Water rendering - class Water : public Ogre::RenderTargetListener, public Ogre::RenderQueueListener + class Water : public Ogre::RenderTargetListener, public Ogre::RenderQueueListener, public sh::MaterialInstanceListener { static const int CELL_SIZE = 8192; Ogre::Camera *mCamera; Ogre::SceneManager *mSceneManager; Ogre::Plane mWaterPlane; + Ogre::Plane mErrorPlane; + Ogre::SceneNode *mWaterNode; Ogre::Entity *mWater; + Ogre::SceneNode* mUnderwaterDome; + bool mIsUnderwater; bool mActive; bool mToggled; int mTop; + int mOldFarClip; + int mOldFarClip2; + + float mWaterTimer; + bool mReflectionRenderActive; Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY); @@ -65,7 +76,6 @@ namespace MWRender { std::string mCompositorName; - void createMaterial(); Ogre::MaterialPtr mMaterial; Ogre::Camera* mReflectionCamera; @@ -83,7 +93,7 @@ namespace MWRender { void setActive(bool active); void toggle(); - void update(); + void update(float dt); void assignTextures(); @@ -95,6 +105,9 @@ namespace MWRender { void changeCell(const ESM::Cell* cell); void setHeight(const float height); + virtual void requestedConfiguration (sh::MaterialInstance* m, const std::string& configuration); + virtual void createdConfiguration (sh::MaterialInstance* m, const std::string& configuration); + }; } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 105995aca7..bf5c001db1 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -181,16 +181,15 @@ namespace MWWorld playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90; - Ogre::Quaternion quat = yawNode->getOrientation(); - Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); + Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); - pm_ref.rightmove = -iter->second.x; - pm_ref.forwardmove = -iter->second.y; - pm_ref.upmove = iter->second.z; + pm_ref.rightmove = -iter->second.x; + pm_ref.forwardmove = -iter->second.y; + pm_ref.upmove = iter->second.z; - } + } diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 6c275ff80a..b5f2e3a575 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -476,8 +476,7 @@ WeatherResult WeatherManager::transition(float factor) result.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor); result.mFogDepth = lerp(current.mFogDepth, other.mFogDepth); result.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed); - //result.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed); - result.mCloudSpeed = current.mCloudSpeed; + result.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed); result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity); result.mGlareView = lerp(current.mGlareView, other.mGlareView); result.mNightFade = lerp(current.mNightFade, other.mNightFade); @@ -689,13 +688,13 @@ void WeatherManager::update(float duration) mThunderFlash -= duration; if (mThunderFlash > 0) - mRendering->getSkyManager()->setThunder( mThunderFlash / WeatherGlobals::mThunderThreshold ); + mRendering->getSkyManager()->setLightningStrength( mThunderFlash / WeatherGlobals::mThunderThreshold ); else { srand(time(NULL)); mThunderChanceNeeded = rand() % 100; mThunderChance = 0; - mRendering->getSkyManager()->setThunder( 0.f ); + mRendering->getSkyManager()->setLightningStrength( 0.f ); } } else @@ -706,14 +705,14 @@ void WeatherManager::update(float duration) { mThunderFlash = WeatherGlobals::mThunderThreshold; - mRendering->getSkyManager()->setThunder( mThunderFlash / WeatherGlobals::mThunderThreshold ); + mRendering->getSkyManager()->setLightningStrength( mThunderFlash / WeatherGlobals::mThunderThreshold ); mThunderSoundDelay = WeatherGlobals::mThunderSoundDelay; } } } else - mRendering->getSkyManager()->setThunder(0.f); + mRendering->getSkyManager()->setLightningStrength(0.f); mRendering->setAmbientColour(result.mAmbientColor); mRendering->sunEnable(); @@ -725,7 +724,7 @@ void WeatherManager::update(float duration) { mRendering->sunDisable(); mRendering->skyDisable(); - mRendering->getSkyManager()->setThunder(0.f); + mRendering->getSkyManager()->setLightningStrength(0.f); } // play sounds diff --git a/cmake/OpenMWMacros.cmake b/cmake/OpenMWMacros.cmake index 024338d3ad..e6f45fdb1f 100644 --- a/cmake/OpenMWMacros.cmake +++ b/cmake/OpenMWMacros.cmake @@ -22,3 +22,10 @@ endforeach (f) endforeach (u) source_group ("components\\${dir}" FILES ${files}) endmacro (add_component_dir) + +macro (copy_all_files source_dir destination_dir files) +foreach (f ${files}) +get_filename_component(filename ${f} NAME) +configure_file(${source_dir}/${f} ${destination_dir}/${filename} COPYONLY) +endforeach (f) +endmacro (copy_all_files) diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index dee51b0c15..ef810fb061 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -15,7 +15,6 @@ namespace Files { static const char* const openmwCfgFile = "openmw.cfg"; -static const char* const pluginsCfgFile = "plugins.cfg"; const char* const mwToken = "?mw?"; const char* const localToken = "?local?"; @@ -29,17 +28,6 @@ ConfigurationManager::ConfigurationManager() boost::filesystem::create_directories(mFixedPath.getUserPath()); - mPluginsCfgPath = mFixedPath.getLocalPath() / pluginsCfgFile; - if (!boost::filesystem::is_regular_file(mPluginsCfgPath)) - { - mPluginsCfgPath = mFixedPath.getGlobalPath() / pluginsCfgFile; - if (!boost::filesystem::is_regular_file(mPluginsCfgPath)) - { - std::cerr << "Failed to find " << pluginsCfgFile << " file!" << std::endl; - mPluginsCfgPath.clear(); - } - } - mLogPath = mFixedPath.getUserPath(); } @@ -164,11 +152,6 @@ const boost::filesystem::path& ConfigurationManager::getInstallPath() const return mFixedPath.getInstallPath(); } -const boost::filesystem::path& ConfigurationManager::getPluginsConfigPath() const -{ - return mPluginsCfgPath; -} - const boost::filesystem::path& ConfigurationManager::getLogPath() const { return mLogPath; diff --git a/components/files/configurationmanager.hpp b/components/files/configurationmanager.hpp index 0c22c6f7d5..ecbfac6646 100644 --- a/components/files/configurationmanager.hpp +++ b/components/files/configurationmanager.hpp @@ -40,7 +40,6 @@ struct ConfigurationManager const boost::filesystem::path& getLocalDataPath() const; const boost::filesystem::path& getInstallPath() const; - const boost::filesystem::path& getPluginsConfigPath() const; const boost::filesystem::path& getLogPath() const; private: @@ -57,7 +56,6 @@ struct ConfigurationManager FixedPathType mFixedPath; - boost::filesystem::path mPluginsCfgPath; boost::filesystem::path mLogPath; TokensMappingContainer mTokensMapping; diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index aca1966b92..bde9489701 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -33,6 +33,11 @@ #include #include +#include +#include + +#include + #include #include @@ -207,139 +212,82 @@ void NIFLoader::createMaterial(const Ogre::String &name, const Ogre::Vector3 &emissive, float glossiness, float alpha, int alphaFlags, float alphaTest, - const Ogre::String &texName) + const Ogre::String &texName, bool vertexColor) { - Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(name, resourceGroup); + if (texName.empty()) + return; + sh::MaterialInstance* instance = sh::Factory::getInstance ().createMaterialInstance (name, "openmw_objects_base"); + instance->setProperty ("ambient", sh::makeProperty ( + new sh::Vector3(ambient.x, ambient.y, ambient.z))); - //Hardware Skinning code, textures may be the wrong color if enabled + instance->setProperty ("diffuse", sh::makeProperty ( + new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); - /* if(!mSkel.isNull()){ - material->removeAllTechniques(); + instance->setProperty ("specular", sh::makeProperty ( + new sh::Vector4(specular.x, specular.y, specular.z, glossiness))); - Ogre::Technique* tech = material->createTechnique(); - //tech->setSchemeName("blahblah"); - Pass* pass = tech->createPass(); - pass->setVertexProgram("Ogre/BasicVertexPrograms/AmbientOneTexture");*/ + instance->setProperty ("emissive", sh::makeProperty ( + new sh::Vector3(emissive.x, emissive.y, emissive.z))); + instance->setProperty ("diffuseMap", sh::makeProperty(texName)); - // This assigns the texture to this material. If the texture name is - // a file name, and this file exists (in a resource directory), it - // will automatically be loaded when needed. If not (such as for - // internal NIF textures that we might support later), we should - // already have inserted a manual loader for the texture. + if (vertexColor) + instance->setProperty ("has_vertex_colour", sh::makeProperty(new sh::BooleanValue(true))); - - if (!texName.empty()) + // Add transparency if NiAlphaProperty was present + if (alphaFlags != -1) { - Ogre::Pass *pass = material->getTechnique(0)->getPass(0); - /*TextureUnitState *txt =*/ - pass->createTextureUnitState(texName); - - pass->setVertexColourTracking(Ogre::TVC_DIFFUSE); - - // As of yet UNTESTED code from Chris: - /*pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC); - pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL); - pass->setDepthCheckEnabled(true); - - // Add transparency if NiAlphaProperty was present - if (alphaFlags != -1) + // The 237 alpha flags are by far the most common. Check + // NiAlphaProperty in nif/property.h if you need to decode + // other values. 237 basically means normal transparencly. + if (alphaFlags == 237) { - std::cout << "Alpha flags set!" << endl; - if ((alphaFlags&1)) + NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName); + if (result.first) { - pass->setDepthWriteEnabled(false); - pass->setSceneBlending(getBlendFactor((alphaFlags>>1)&0xf), - getBlendFactor((alphaFlags>>5)&0xf)); + instance->setProperty("alpha_rejection", + sh::makeProperty(new sh::StringValue("greater_equal " + boost::lexical_cast(result.second)))); } else - pass->setDepthWriteEnabled(true); - - if ((alphaFlags>>9)&1) - pass->setAlphaRejectSettings(getTestMode((alphaFlags>>10)&0x7), - alphaTest); - - pass->setTransparentSortingEnabled(!((alphaFlags>>13)&1)); - } - else - pass->setDepthWriteEnabled(true); */ - - - // Add transparency if NiAlphaProperty was present - if (alphaFlags != -1) - { - // The 237 alpha flags are by far the most common. Check - // NiAlphaProperty in nif/property.h if you need to decode - // other values. 237 basically means normal transparencly. - if (alphaFlags == 237) { - NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName); - if (result.first) - { - pass->setAlphaRejectFunction(Ogre::CMPF_GREATER_EQUAL); - pass->setAlphaRejectValue(result.second); - } - else - { - // Enable transparency - pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); - - //pass->setDepthCheckEnabled(false); - pass->setDepthWriteEnabled(false); - //std::cout << "alpha 237; material: " << name << " texName: " << texName << std::endl; - } + // Enable transparency + instance->setProperty("scene_blend", sh::makeProperty(new sh::StringValue("alpha_blend"))); + instance->setProperty("depth_write", sh::makeProperty(new sh::StringValue("off"))); } - else - warn("Unhandled alpha setting for texture " + texName); } else + warn("Unhandled alpha setting for texture " + texName); + } + else + instance->getMaterial ()->setShadowCasterMaterial ("openmw_shadowcaster_noalpha"); + + // As of yet UNTESTED code from Chris: + /*pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC); + pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL); + pass->setDepthCheckEnabled(true); + + // Add transparency if NiAlphaProperty was present + if (alphaFlags != -1) + { + std::cout << "Alpha flags set!" << endl; + if ((alphaFlags&1)) { - material->getTechnique(0)->setShadowCasterMaterial("depth_shadow_caster_noalpha"); + pass->setDepthWriteEnabled(false); + pass->setSceneBlending(getBlendFactor((alphaFlags>>1)&0xf), + getBlendFactor((alphaFlags>>5)&0xf)); } + else + pass->setDepthWriteEnabled(true); + + if ((alphaFlags>>9)&1) + pass->setAlphaRejectSettings(getTestMode((alphaFlags>>10)&0x7), + alphaTest); + + pass->setTransparentSortingEnabled(!((alphaFlags>>13)&1)); } - - if (Settings::Manager::getBool("enabled", "Shadows")) - { - bool split = Settings::Manager::getBool("split", "Shadows"); - const int numsplits = 3; - for (int i = 0; i < (split ? numsplits : 1); ++i) - { - Ogre::TextureUnitState* tu = material->getTechnique(0)->getPass(0)->createTextureUnitState(); - tu->setName("shadowMap" + Ogre::StringConverter::toString(i)); - tu->setContentType(Ogre::TextureUnitState::CONTENT_SHADOW); - tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_BORDER); - tu->setTextureBorderColour(Ogre::ColourValue::White); - } - } - - if (Settings::Manager::getBool("shaders", "Objects")) - { - material->getTechnique(0)->getPass(0)->setVertexProgram("main_vp"); - material->getTechnique(0)->getPass(0)->setFragmentProgram("main_fp"); - - material->getTechnique(0)->getPass(0)->setFog(true); // force-disable fixed function fog, it is calculated in shader - } - - // Create a fallback technique without shadows and without mrt - Ogre::Technique* tech2 = material->createTechnique(); - tech2->setSchemeName("Fallback"); - Ogre::Pass* pass2 = tech2->createPass(); - pass2->createTextureUnitState(texName); - pass2->setVertexColourTracking(Ogre::TVC_DIFFUSE); - if (Settings::Manager::getBool("shaders", "Objects")) - { - pass2->setVertexProgram("main_fallback_vp"); - pass2->setFragmentProgram("main_fallback_fp"); - pass2->setFog(true); // force-disable fixed function fog, it is calculated in shader - } - - // Add material bells and whistles - material->setAmbient(ambient[0], ambient[1], ambient[2]); - material->setDiffuse(diffuse[0], diffuse[1], diffuse[2], alpha); - material->setSpecular(specular[0], specular[1], specular[2], alpha); - material->setSelfIllumination(emissive[0], emissive[1], emissive[2]); - material->setShininess(glossiness); + else + pass->setDepthWriteEnabled(true); */ } // Takes a name and adds a unique part to it. This is just used to @@ -642,6 +590,8 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou NiTexturingProperty *t = NULL; NiMaterialProperty *m = NULL; NiAlphaProperty *a = NULL; + // can't make any sense of these values, so ignoring them for now + //NiVertexColorProperty *v = NULL; // Scan the property list for material information PropertyList &list = shape->props; @@ -659,6 +609,8 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou m = static_cast(pr); else if (pr->recType == RC_NiAlphaProperty) a = static_cast(pr); + //else if (pr->recType == RC_NiVertexColorProperty) + //v = static_cast(pr); } // Texture @@ -727,7 +679,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou { //std::cout << "new"; createMaterial(material, d->ambient, d->diffuse, d->specular, d->emissive, - d->glossiness, d->alpha, alphaFlags, alphaTest, texName); + d->glossiness, d->alpha, alphaFlags, alphaTest, texName, shape->data->colors.size() != 0); MaterialMap.insert(std::make_pair(texName,material)); } } @@ -737,7 +689,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou // material for it. const Ogre::Vector3 zero(0.0f), one(1.0f); createMaterial(material, one, one, zero, zero, 0.0f, 1.0f, - alphaFlags, alphaTest, texName); + alphaFlags, alphaTest, texName, shape->data->colors.size() != 0); } } } // End of material block, if(!hidden) ... diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 7b32d24d1f..8e317ff4d5 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -117,7 +117,8 @@ class NIFLoader : Ogre::ManualResourceLoader const Ogre::Vector3 &emissive, float glossiness, float alpha, int alphaFlags, float alphaTest, - const Ogre::String &texName); + const Ogre::String &texName, + bool vertexColor); void findRealTexture(Ogre::String &texName); diff --git a/extern/shiny b/extern/shiny new file mode 160000 index 0000000000..41245d1361 --- /dev/null +++ b/extern/shiny @@ -0,0 +1 @@ +Subproject commit 41245d1361bc0242e5d2c2313caffb711207e5fc diff --git a/files/CMakeLists.txt b/files/CMakeLists.txt index 8ab3d5b51e..3e99f57455 100644 --- a/files/CMakeLists.txt +++ b/files/CMakeLists.txt @@ -1,16 +1,50 @@ project(resources) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/caustic_0.png "${OpenMW_BINARY_DIR}/resources/water/caustic_0.png" COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/underwater.cg "${OpenMW_BINARY_DIR}/resources/water/underwater.cg" COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/perlinvolume.dds "${OpenMW_BINARY_DIR}/resources/water/perlinvolume.dds" COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.compositor "${OpenMW_BINARY_DIR}/resources/water/water.compositor" COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.material "${OpenMW_BINARY_DIR}/resources/water/water.material" COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/WaterNormal2.tga "${OpenMW_BINARY_DIR}/resources/water/WaterNormal2.tga" COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.cg "${OpenMW_BINARY_DIR}/resources/water/water.cg" COPYONLY) +set(WATER_FILES + underwater_dome.mesh + water_nm.png +) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.cg "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.cg" COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.material "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.material" COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.compositor "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.compositor" COPYONLY) +set(GBUFFER_FILES + gbuffer.compositor +) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/shadows/depthshadowcaster.material "${OpenMW_BINARY_DIR}/resources/shadows/depthshadowcaster.material" COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/shadows/depthshadowcaster.cg "${OpenMW_BINARY_DIR}/resources/shadows/depthshadowcaster.cg" COPYONLY) +set(MATERIAL_FILES + atmosphere.shader + atmosphere.shaderset + clouds.shader + clouds.shaderset + core.h + moon.shader + moon.shaderset + objects.mat + objects.shader + objects.shaderset + openmw.configuration + quad2.shader + quad.mat + quad.shader + quad.shaderset + shadowcaster.mat + shadowcaster.shader + shadowcaster.shaderset + shadows.h + sky.mat + stars.shader + stars.shaderset + sun.shader + sun.shaderset + terrain.shader + terrain.shaderset + underwater.h + water.mat + water.shader + water.shaderset + +) + +copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/water "${OpenMW_BINARY_DIR}/resources/water/" "${WATER_FILES}") + +copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer "${OpenMW_BINARY_DIR}/resources/gbuffer/" "${GBUFFER_FILES}") + +copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/materials "${OpenMW_BINARY_DIR}/resources/materials/" "${MATERIAL_FILES}") diff --git a/files/gbuffer/gbuffer.cg b/files/gbuffer/gbuffer.cg deleted file mode 100644 index c7f2fe6788..0000000000 --- a/files/gbuffer/gbuffer.cg +++ /dev/null @@ -1,18 +0,0 @@ -void RenderScene_vs(in float4 position : POSITION - ,in float2 uv :TEXCOORD0 - ,uniform float4x4 wvp - ,out float4 oPosition : POSITION - ,out float2 oUV :TEXCOORD0) -{ - oPosition = mul(wvp, position); - oUV = uv; -} - -void RenderScene_ps(in float4 position : POSITION - ,in float2 uv :TEXCOORD0 - ,uniform sampler2D tex1 : TEXUNIT0 - ,out float4 oColor : COLOR) -{ - float4 scene =tex2D(tex1, uv); - oColor= scene; -} diff --git a/files/gbuffer/gbuffer.compositor b/files/gbuffer/gbuffer.compositor index 6ca35df87b..04600ce9b7 100644 --- a/files/gbuffer/gbuffer.compositor +++ b/files/gbuffer/gbuffer.compositor @@ -9,16 +9,21 @@ compositor gbuffer target mrt_output { input none + pass clear { - // make sure to set this to the viewport background color from outside colour_value 0 0 0 1 } + pass render_quad + { + // this makes sure the depth for background is set to 1 + material openmw_viewport_init + } pass render_scene { // Renders everything except water first_render_queue 0 - last_render_queue 70 + last_render_queue 50 } } @@ -29,7 +34,7 @@ compositor gbuffer pass render_quad { - material RenderScene + material quad input 0 mrt_output 0 } } @@ -61,12 +66,12 @@ compositor gbufferFinalizer } pass render_quad { - material RenderSceneNoDepth + material quad_noDepthWrite input 0 previousscene } pass render_scene { - first_render_queue 71 + first_render_queue 51 last_render_queue 100 } } @@ -78,7 +83,7 @@ compositor gbufferFinalizer } pass render_quad { - material RenderSceneNoDepth + material quad_noDepthWrite input 0 no_mrt_output } } diff --git a/files/gbuffer/gbuffer.material b/files/gbuffer/gbuffer.material deleted file mode 100644 index faa8dd4980..0000000000 --- a/files/gbuffer/gbuffer.material +++ /dev/null @@ -1,63 +0,0 @@ -vertex_program RenderGBuffer_vs cg -{ - source gbuffer.cg - profiles vs_4_0 vs_1_1 arbvp1 - entry_point RenderScene_vs - default_params - { - param_named_auto wvp worldviewproj_matrix - } -} -fragment_program RenderGBuffer_ps cg -{ - source gbuffer.cg - entry_point RenderScene_ps - profiles ps_4_0 ps_2_x arbfp1 - default_params - { - } -} -material RenderScene -{ - technique - { - pass - { - vertex_program_ref RenderGBuffer_vs - { - } - - fragment_program_ref RenderGBuffer_ps - { - } - - texture_unit tex1 - { - //scenebuffer - } - } - } -} - -material RenderSceneNoDepth -{ - technique - { - pass - { - depth_write off - vertex_program_ref RenderGBuffer_vs - { - } - - fragment_program_ref RenderGBuffer_ps - { - } - - texture_unit tex1 - { - //scenebuffer - } - } - } -} diff --git a/files/materials/atmosphere.shader b/files/materials/atmosphere.shader new file mode 100644 index 0000000000..295fa93768 --- /dev/null +++ b/files/materials/atmosphere.shader @@ -0,0 +1,37 @@ +#include "core.h" + +#define MRT @shGlobalSettingBool(mrt_output) + +#ifdef SH_VERTEX_SHADER + + SH_BEGIN_PROGRAM + shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + + shColourInput(float4) + shOutput(float4, colourPassthrough) + + SH_START_PROGRAM + { + shOutputPosition = shMatrixMult(wvp, shInputPosition); + colourPassthrough = colour; + } + +#else + + SH_BEGIN_PROGRAM + shInput(float4, colourPassthrough) +#if MRT + shDeclareMrtOutput(1) +#endif + shUniform(float4, atmosphereColour) @shSharedParameter(atmosphereColour) + + SH_START_PROGRAM + { + shOutputColour(0) = colourPassthrough * atmosphereColour; + +#if MRT + shOutputColour(1) = float4(1,1,1,1); +#endif + } + +#endif diff --git a/files/materials/atmosphere.shaderset b/files/materials/atmosphere.shaderset new file mode 100644 index 0000000000..54108dbba6 --- /dev/null +++ b/files/materials/atmosphere.shaderset @@ -0,0 +1,15 @@ +shader_set atmosphere_vertex +{ + source atmosphere.shader + type vertex + profiles_cg vs_2_0 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set atmosphere_fragment +{ + source atmosphere.shader + type fragment + profiles_cg ps_2_x ps_2_0 ps arbfp1 + profiles_hlsl ps_2_0 +} diff --git a/files/materials/clouds.shader b/files/materials/clouds.shader new file mode 100644 index 0000000000..f4258bf5d4 --- /dev/null +++ b/files/materials/clouds.shader @@ -0,0 +1,52 @@ +#include "core.h" + +#define MRT @shGlobalSettingBool(mrt_output) + +#ifdef SH_VERTEX_SHADER + + SH_BEGIN_PROGRAM + shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + shVertexInput(float2, uv0) + shOutput(float2, UV) + shColourInput(float4) + shOutput(float4, colourPassthrough) + + SH_START_PROGRAM + { + colourPassthrough = colour; + shOutputPosition = shMatrixMult(wvp, shInputPosition); + UV = uv0; + } + +#else + + SH_BEGIN_PROGRAM + shInput(float2, UV) + shInput(float4, colourPassthrough) +#if MRT + shDeclareMrtOutput(1) +#endif + + shSampler2D(diffuseMap1) + shSampler2D(diffuseMap2) + + shUniform(float, cloudBlendFactor) @shSharedParameter(cloudBlendFactor) + shUniform(float, cloudAnimationTimer) @shSharedParameter(cloudAnimationTimer) + shUniform(float, cloudOpacity) @shSharedParameter(cloudOpacity) + shUniform(float3, cloudColour) @shSharedParameter(cloudColour) + + SH_START_PROGRAM + { + // Scroll in y direction + float2 scrolledUV = UV + float2(0,1) * cloudAnimationTimer * 0.003; + + float4 albedo = shSample(diffuseMap1, scrolledUV) * (1-cloudBlendFactor) + shSample(diffuseMap2, scrolledUV) * cloudBlendFactor; + + shOutputColour(0) = colourPassthrough * float4(cloudColour, 1) * albedo * float4(1,1,1, cloudOpacity); + +#if MRT + shOutputColour(1) = float4(1,1,1,1); +#endif + } + +#endif diff --git a/files/materials/clouds.shaderset b/files/materials/clouds.shaderset new file mode 100644 index 0000000000..5fffb5658d --- /dev/null +++ b/files/materials/clouds.shaderset @@ -0,0 +1,15 @@ +shader_set clouds_vertex +{ + source clouds.shader + type vertex + profiles_cg vs_2_0 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set clouds_fragment +{ + source clouds.shader + type fragment + profiles_cg ps_2_x ps_2_0 ps arbfp1 + profiles_hlsl ps_2_0 +} diff --git a/files/materials/core.h b/files/materials/core.h new file mode 100644 index 0000000000..306073a77d --- /dev/null +++ b/files/materials/core.h @@ -0,0 +1,159 @@ +#if SH_HLSL == 1 || SH_CG == 1 + + #define shTexture2D sampler2D + #define shSample(tex, coord) tex2D(tex, coord) + #define shLerp(a, b, t) lerp(a, b, t) + #define shSaturate(a) saturate(a) + + #define shSampler2D(name) , uniform sampler2D name : register(s@shCounter(0)) @shUseSampler(name) + + #define shMatrixMult(m, v) mul(m, v) + + #define shUniform(type, name) , uniform type name + + #define shVertexInput(type, name) , in type name : TEXCOORD@shCounter(1) + #define shInput(type, name) , in type name : TEXCOORD@shCounter(1) + #define shOutput(type, name) , out type name : TEXCOORD@shCounter(2) + + #define shNormalInput(type) , in type normal : NORMAL + + #define shColourInput(type) , in type colour : COLOR + + #ifdef SH_VERTEX_SHADER + + #define shOutputPosition oPosition + #define shInputPosition iPosition + + + #define SH_BEGIN_PROGRAM \ + void main( \ + float4 iPosition : POSITION \ + , out float4 oPosition : POSITION + + #define SH_START_PROGRAM \ + ) \ + + #endif + + #ifdef SH_FRAGMENT_SHADER + + #define shOutputColour(num) oColor##num + + #define shDeclareMrtOutput(num) , out float4 oColor##num : COLOR##num + + #define SH_BEGIN_PROGRAM \ + void main( \ + out float4 oColor0 : COLOR + + #define SH_START_PROGRAM \ + ) \ + + #endif + +#endif + +#if SH_GLSL == 1 + + @version 120 + + #define float2 vec2 + #define float3 vec3 + #define float4 vec4 + #define int2 ivec2 + #define int3 ivec3 + #define int4 ivec4/ + #define shTexture2D sampler2D + #define shSample(tex, coord) texture2D(tex, coord) + #define shLerp(a, b, t) mix(a, b, t) + #define shSaturate(a) clamp(a, 0.0, 1.0) + + #define shUniform(type, name) uniform type name; + + #define shSampler2D(name) uniform sampler2D name; @shUseSampler(name) + + #define shMatrixMult(m, v) (m * v) + + #define shOutputPosition gl_Position + + #define float4x4 mat4 + + // GLSL 1.3 + #if 0 + + // automatically recognized by ogre when the input name equals this + #define shInputPosition vertex + + #define shOutputColour(num) oColor##num + + + + #define shInput(type, name) in type name; + #define shOutput(type, name) out type name; + + // automatically recognized by ogre when the input name equals this + #define shNormalInput(type) in type normal; + #define shColourInput(type) in type colour; + + #ifdef SH_VERTEX_SHADER + + #define SH_BEGIN_PROGRAM \ + in float4 shInputPosition; + #define SH_START_PROGRAM \ + void main(void) + + #endif + + #ifdef SH_FRAGMENT_SHADER + + #define shDeclareMrtOutput(num) out vec4 oColor##num; + + #define SH_BEGIN_PROGRAM \ + out float4 oColor0; + #define SH_START_PROGRAM \ + void main(void) + + + #endif + + #endif + + // GLSL 1.2 + + #if 1 + + // automatically recognized by ogre when the input name equals this + #define shInputPosition gl_Vertex + + #define shOutputColour(num) gl_FragData[num] + + #define shVertexInput(type, name) attribute type name; + #define shInput(type, name) varying type name; + #define shOutput(type, name) varying type name; + + // automatically recognized by ogre when the input name equals this + #define shNormalInput(type) attribute type normal; + #define shColourInput(type) attribute type colour; + + #ifdef SH_VERTEX_SHADER + + #define SH_BEGIN_PROGRAM + + #define SH_START_PROGRAM \ + void main(void) + + #endif + + #ifdef SH_FRAGMENT_SHADER + + #define shDeclareMrtOutput(num) + + #define SH_BEGIN_PROGRAM + + #define SH_START_PROGRAM \ + void main(void) + + + #endif + + #endif +#endif diff --git a/files/materials/moon.shader b/files/materials/moon.shader new file mode 100644 index 0000000000..7640563cef --- /dev/null +++ b/files/materials/moon.shader @@ -0,0 +1,52 @@ +#include "core.h" + +#define MRT @shGlobalSettingBool(mrt_output) + + +#ifdef SH_VERTEX_SHADER + + SH_BEGIN_PROGRAM + shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + shVertexInput(float2, uv0) + shOutput(float2, UV) + + SH_START_PROGRAM + { + shOutputPosition = shMatrixMult(wvp, shInputPosition); + UV = uv0; + } + +#else + + SH_BEGIN_PROGRAM + shSampler2D(diffuseMap) + shInput(float2, UV) +#if MRT + shDeclareMrtOutput(1) +#endif + shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour) + shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour) + + shUniform(float4, atmosphereColour) @shSharedParameter(atmosphereColour) + + SH_START_PROGRAM + { + + float4 tex = shSample(diffuseMap, UV); + + shOutputColour(0) = float4(materialEmissive.xyz, 1) * tex; + + // use a circle for the alpha (compute UV distance to center) + // looks a bit bad because it's not filtered on the edges, + // but cheaper than a seperate alpha texture. + float sqrUVdist = pow(UV.x-0.5,2) + pow(UV.y-0.5, 2); + shOutputColour(0).a = materialDiffuse.a * (sqrUVdist >= 0.24 ? 0 : 1); + shOutputColour(0).rgb += (1-tex.a) * shOutputColour(0).a * atmosphereColour.rgb; //fill dark side of moon with atmosphereColour + shOutputColour(0).rgb += (1-materialDiffuse.a) * atmosphereColour.rgb; //fade bump + +#if MRT + shOutputColour(1) = float4(1,1,1,1); +#endif + } + +#endif diff --git a/files/materials/moon.shaderset b/files/materials/moon.shaderset new file mode 100644 index 0000000000..659481a961 --- /dev/null +++ b/files/materials/moon.shaderset @@ -0,0 +1,15 @@ +shader_set moon_vertex +{ + source moon.shader + type vertex + profiles_cg vs_2_0 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set moon_fragment +{ + source moon.shader + type fragment + profiles_cg ps_2_x ps_2_0 ps arbfp1 + profiles_hlsl ps_2_0 +} diff --git a/files/materials/objects.mat b/files/materials/objects.mat new file mode 100644 index 0000000000..f1198b4a23 --- /dev/null +++ b/files/materials/objects.mat @@ -0,0 +1,67 @@ +material openmw_objects_base +{ + diffuse 1.0 1.0 1.0 1.0 + specular 0.4 0.4 0.4 32 + ambient 1.0 1.0 1.0 + emissive 0.0 0.0 0.0 + has_vertex_colour false + diffuseMap black.png + + is_transparent false // real transparency, alpha rejection doesn't count here + scene_blend default + depth_write default + alpha_rejection default + + pass + { + vertex_program openmw_objects_vertex + fragment_program openmw_objects_fragment + + shader_properties + { + has_vertex_colour $has_vertex_colour + is_transparent $is_transparent + } + + diffuse $diffuse + specular $specular + ambient $ambient + emissive $emissive + scene_blend $scene_blend + alpha_rejection $alpha_rejection + depth_write $depth_write + + ffp_vertex_colour_ambient $has_vertex_colour + + + texture_unit diffuseMap + { + direct_texture $diffuseMap + create_in_ffp true + } + + texture_unit shadowMap0 + { + content_type shadow + tex_address_mode clamp + filtering none + } + texture_unit shadowMap1 + { + content_type shadow + tex_address_mode clamp + filtering none + } + texture_unit shadowMap2 + { + content_type shadow + tex_address_mode clamp + filtering none + } + + texture_unit causticMap + { + direct_texture water_nm.png + } + } +} diff --git a/files/materials/objects.shader b/files/materials/objects.shader new file mode 100644 index 0000000000..238ccdcf60 --- /dev/null +++ b/files/materials/objects.shader @@ -0,0 +1,299 @@ +#include "core.h" + + +#define FOG @shGlobalSettingBool(fog) +#define MRT @shPropertyNotBool(is_transparent) && @shGlobalSettingBool(mrt_output) +#define LIGHTING @shGlobalSettingBool(lighting) + +#define SHADOWS_PSSM LIGHTING && @shGlobalSettingBool(shadows_pssm) +#define SHADOWS LIGHTING && @shGlobalSettingBool(shadows) + +#if SHADOWS || SHADOWS_PSSM + #include "shadows.h" +#endif + +#if FOG || MRT || SHADOWS_PSSM +#define NEED_DEPTH +#endif + + +#define UNDERWATER @shGlobalSettingBool(underwater_effects) && LIGHTING + + +#define HAS_VERTEXCOLOR @shPropertyBool(has_vertex_colour) + +#ifdef SH_VERTEX_SHADER + + // ------------------------------------- VERTEX --------------------------------------- + + SH_BEGIN_PROGRAM + shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + shVertexInput(float2, uv0) + shOutput(float2, UV) + shNormalInput(float4) +#ifdef NEED_DEPTH + shOutput(float, depthPassthrough) +#endif + +#if LIGHTING + shOutput(float3, normalPassthrough) + shOutput(float3, objSpacePositionPassthrough) +#endif + +#if HAS_VERTEXCOLOR + shColourInput(float4) + shOutput(float4, colourPassthrough) +#endif + +#if SHADOWS + shOutput(float4, lightSpacePos0) + shUniform(float4x4, texViewProjMatrix0) @shAutoConstant(texViewProjMatrix0, texture_viewproj_matrix) + shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) +#endif + +#if SHADOWS_PSSM + @shForeach(3) + shOutput(float4, lightSpacePos@shIterator) + shUniform(float4x4, texViewProjMatrix@shIterator) @shAutoConstant(texViewProjMatrix@shIterator, texture_viewproj_matrix, @shIterator) + @shEndForeach + shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) +#endif + SH_START_PROGRAM + { + shOutputPosition = shMatrixMult(wvp, shInputPosition); + UV = uv0; +#if LIGHTING + normalPassthrough = normal.xyz; +#endif + +#ifdef NEED_DEPTH + depthPassthrough = shOutputPosition.z; +#endif + +#if LIGHTING + objSpacePositionPassthrough = shInputPosition.xyz; +#endif + +#if HAS_VERTEXCOLOR + colourPassthrough = colour; +#endif + +#if SHADOWS + lightSpacePos0 = shMatrixMult(texViewProjMatrix0, shMatrixMult(worldMatrix, shInputPosition)); +#endif +#if SHADOWS_PSSM + float4 wPos = shMatrixMult(worldMatrix, shInputPosition); + @shForeach(3) + lightSpacePos@shIterator = shMatrixMult(texViewProjMatrix@shIterator, wPos); + @shEndForeach +#endif + } + +#else + + // ----------------------------------- FRAGMENT ------------------------------------------ + +#if UNDERWATER + #include "underwater.h" +#endif + + SH_BEGIN_PROGRAM + shSampler2D(diffuseMap) + shInput(float2, UV) +#if MRT + shDeclareMrtOutput(1) +#endif + +#ifdef NEED_DEPTH + shInput(float, depthPassthrough) +#endif + +#if MRT + shUniform(float, far) @shAutoConstant(far, far_clip_distance) +#endif + +#if LIGHTING + shInput(float3, normalPassthrough) + shInput(float3, objSpacePositionPassthrough) + shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) + //shUniform(float, passIteration) @shAutoConstant(passIteration, pass_iteration_number) + shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour) + shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour) + shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour) + @shForeach(@shGlobalSettingString(num_lights)) + shUniform(float4, lightPosObjSpace@shIterator) @shAutoConstant(lightPosObjSpace@shIterator, light_position_object_space, @shIterator) + shUniform(float4, lightAttenuation@shIterator) @shAutoConstant(lightAttenuation@shIterator, light_attenuation, @shIterator) + shUniform(float4, lightDiffuse@shIterator) @shAutoConstant(lightDiffuse@shIterator, light_diffuse_colour, @shIterator) + @shEndForeach +#endif + +#if FOG + shUniform(float3, fogColour) @shAutoConstant(fogColour, fog_colour) + shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params) +#endif + +#if HAS_VERTEXCOLOR + shInput(float4, colourPassthrough) +#endif + +#if SHADOWS + shInput(float4, lightSpacePos0) + shSampler2D(shadowMap0) + shUniform(float2, invShadowmapSize0) @shAutoConstant(invShadowmapSize0, inverse_texture_size, 1) +#endif +#if SHADOWS_PSSM + @shForeach(3) + shInput(float4, lightSpacePos@shIterator) + shSampler2D(shadowMap@shIterator) + shUniform(float2, invShadowmapSize@shIterator) @shAutoConstant(invShadowmapSize@shIterator, inverse_texture_size, @shIterator(1)) + @shEndForeach + shUniform(float3, pssmSplitPoints) @shSharedParameter(pssmSplitPoints) +#endif + +#if SHADOWS || SHADOWS_PSSM + shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart) +#endif + +#if UNDERWATER + shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) + shUniform(float, waterLevel) @shSharedParameter(waterLevel) + shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position) + shUniform(float4, lightDirectionWS0) @shAutoConstant(lightDirectionWS0, light_position, 0) + + shSampler2D(causticMap) + + shUniform(float, waterTimer) @shSharedParameter(waterTimer) + shUniform(float2, waterSunFade_sunHeight) @shSharedParameter(waterSunFade_sunHeight) + shUniform(float, waterEnabled) @shSharedParameter(waterEnabled) + + shUniform(float3, windDir_windSpeed) @shSharedParameter(windDir_windSpeed) +#endif + + SH_START_PROGRAM + { + shOutputColour(0) = shSample(diffuseMap, UV); + +#if LIGHTING + float3 normal = normalize(normalPassthrough); + float3 lightDir; + float3 diffuse = float3(0,0,0); + float d; + float3 ambient = materialAmbient.xyz * lightAmbient.xyz; + + + // shadows only for the first (directional) light +#if SHADOWS + float shadow = depthShadowPCF (shadowMap0, lightSpacePos0, invShadowmapSize0); +#endif +#if SHADOWS_PSSM + float shadow = pssmDepthShadow (lightSpacePos0, invShadowmapSize0, shadowMap0, lightSpacePos1, invShadowmapSize1, shadowMap1, lightSpacePos2, invShadowmapSize2, shadowMap2, depthPassthrough, pssmSplitPoints); +#endif + +#if SHADOWS || SHADOWS_PSSM + float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; + float fade = 1-((depthPassthrough - shadowFar_fadeStart.y) / fadeRange); + shadow = (depthPassthrough > shadowFar_fadeStart.x) ? 1 : ((depthPassthrough > shadowFar_fadeStart.y) ? 1-((1-shadow)*fade) : shadow); +#endif + +#if !SHADOWS && !SHADOWS_PSSM + float shadow = 1.0; +#endif + + + + float3 caustics = float3(1,1,1); +#if UNDERWATER + float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePositionPassthrough,1)).xyz; + float3 waterEyePos = float3(1,1,1); + if (worldPos.y < waterLevel && waterEnabled == 1) + { + // NOTE: this calculation would be wrong for non-uniform scaling + float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); + waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,1,0), waterLevel); + caustics = getCaustics(causticMap, worldPos, waterEyePos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); + } +#endif + + + @shForeach(@shGlobalSettingString(num_lights)) + + /// \todo use the array auto params for lights, and use a real for-loop with auto param "light_count" iterations + lightDir = lightPosObjSpace@shIterator.xyz - (objSpacePositionPassthrough.xyz * lightPosObjSpace@shIterator.w); + d = length(lightDir); + + lightDir = normalize(lightDir); + +#if @shIterator == 0 + + #if (SHADOWS || SHADOWS_PSSM) + diffuse += materialDiffuse.xyz * lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0) * shadow * caustics; + + #else + diffuse += materialDiffuse.xyz * lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0) * caustics; + + #endif + +#else + diffuse += materialDiffuse.xyz * lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0); +#endif + + @shEndForeach + +#if HAS_VERTEXCOLOR + ambient *= colourPassthrough.xyz; +#endif + + shOutputColour(0).xyz *= (ambient + diffuse + materialEmissive.xyz); +#endif + + +#if HAS_VERTEXCOLOR && !LIGHTING + shOutputColour(0).xyz *= colourPassthrough.xyz; +#endif + +#if FOG + float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w); + + #if UNDERWATER + // regular fog only if fragment is above water + if (worldPos.y > waterLevel) + #endif + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); +#endif + + // prevent negative colour output (for example with negative lights) + shOutputColour(0).xyz = max(shOutputColour(0).xyz, float3(0,0,0)); + +#if UNDERWATER + float fogAmount = (cameraPos.y > waterLevel) + ? shSaturate(length(waterEyePos-worldPos) / VISIBILITY) + : shSaturate(length(cameraPos.xyz-worldPos)/ VISIBILITY); + + float3 eyeVec = normalize(cameraPos.xyz-worldPos); + + 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; + + 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 + 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; + + + float darkness = VISIBILITY*2.0; + darkness = clamp((waterEyePos.y - waterLevel + darkness)/darkness,0.2,1.0); + watercolour *= darkness; + + float isUnderwater = (worldPos.y < waterLevel) ? 1.0 : 0.0; + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater * waterEnabled); +#endif + +#if MRT + shOutputColour(1) = float4(depthPassthrough / far,1,1,1); +#endif + } + +#endif diff --git a/files/materials/objects.shaderset b/files/materials/objects.shaderset new file mode 100644 index 0000000000..e84368a5b9 --- /dev/null +++ b/files/materials/objects.shaderset @@ -0,0 +1,15 @@ +shader_set openmw_objects_vertex +{ + source objects.shader + type vertex + profiles_cg vs_2_0 vp40 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set openmw_objects_fragment +{ + source objects.shader + type fragment + profiles_cg ps_2_x ps_2_0 ps fp40 arbfp1 + profiles_hlsl ps_2_0 +} diff --git a/files/materials/openmw.configuration b/files/materials/openmw.configuration new file mode 100644 index 0000000000..ee97451d39 --- /dev/null +++ b/files/materials/openmw.configuration @@ -0,0 +1,17 @@ +configuration water_reflection +{ + fog false + shadows false + shadows_pssm false + mrt_output false +} + +configuration local_map +{ + fog false + mrt_output false + lighting false + shadows false + shadows_pssm false + simple_water true +} diff --git a/files/materials/quad.mat b/files/materials/quad.mat new file mode 100644 index 0000000000..afb7f51117 --- /dev/null +++ b/files/materials/quad.mat @@ -0,0 +1,35 @@ +material quad +{ + depth_write on + + pass + { + vertex_program quad_vertex + fragment_program quad_fragment + + depth_write $depth_write + + texture_unit SceneBuffer + { + } + } +} + +material quad_noDepthWrite +{ + parent quad + depth_write off +} + +material openmw_viewport_init +{ + pass + { + vertex_program viewport_init_vertex + fragment_program viewport_init_fragment + + depth_write off + depth_check off + scene_blend add + } +} diff --git a/files/materials/quad.shader b/files/materials/quad.shader new file mode 100644 index 0000000000..4620588c3c --- /dev/null +++ b/files/materials/quad.shader @@ -0,0 +1,25 @@ +#include "core.h" + +#ifdef SH_VERTEX_SHADER + + SH_BEGIN_PROGRAM + shVertexInput(float2, uv0) + shOutput(float2, UV) + shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + SH_START_PROGRAM + { + shOutputPosition = shMatrixMult(wvp, shInputPosition); + UV = uv0; + } + +#else + + SH_BEGIN_PROGRAM + shInput(float2, UV) + shSampler2D(SceneBuffer) + SH_START_PROGRAM + { + shOutputColour(0) = shSample(SceneBuffer, UV); + } + +#endif diff --git a/files/materials/quad.shaderset b/files/materials/quad.shaderset new file mode 100644 index 0000000000..c614975034 --- /dev/null +++ b/files/materials/quad.shaderset @@ -0,0 +1,31 @@ +shader_set quad_vertex +{ + source quad.shader + type vertex + profiles_cg vs_2_0 vp40 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set quad_fragment +{ + source quad.shader + type fragment + profiles_cg ps_2_x ps_2_0 ps fp40 arbfp1 + profiles_hlsl ps_2_0 +} + +shader_set viewport_init_vertex +{ + source quad2.shader + type vertex + profiles_cg vs_2_0 vp40 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set viewport_init_fragment +{ + source quad2.shader + type fragment + profiles_cg ps_2_x ps_2_0 ps fp40 arbfp1 + profiles_hlsl ps_2_0 +} diff --git a/files/materials/quad2.shader b/files/materials/quad2.shader new file mode 100644 index 0000000000..e54d83ef4e --- /dev/null +++ b/files/materials/quad2.shader @@ -0,0 +1,23 @@ +#include "core.h" + +#ifdef SH_VERTEX_SHADER + + SH_BEGIN_PROGRAM + shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + SH_START_PROGRAM + { + shOutputPosition = shMatrixMult(wvp, shInputPosition); + } + +#else + + SH_BEGIN_PROGRAM + shUniform(float3, viewportBackground) @shSharedParameter(viewportBackground) + shDeclareMrtOutput(1) + SH_START_PROGRAM + { + shOutputColour(0) = float4(viewportBackground, 1); + shOutputColour(1) = float4(1,1,1,1); + } + +#endif diff --git a/files/materials/shadowcaster.mat b/files/materials/shadowcaster.mat new file mode 100644 index 0000000000..5c5c8e088d --- /dev/null +++ b/files/materials/shadowcaster.mat @@ -0,0 +1,35 @@ +material openmw_shadowcaster_default +{ + create_configuration Default + allow_fixed_function false + pass + { + fog_override true + + vertex_program openmw_shadowcaster_vertex + fragment_program openmw_shadowcaster_fragment + + shader_properties + { + shadow_transparency true + } + } +} + +material openmw_shadowcaster_noalpha +{ + create_configuration Default + allow_fixed_function false + pass + { + fog_override true + + vertex_program openmw_shadowcaster_vertex + fragment_program openmw_shadowcaster_fragment + + shader_properties + { + shadow_transparency false + } + } +} diff --git a/files/materials/shadowcaster.shader b/files/materials/shadowcaster.shader new file mode 100644 index 0000000000..b312d414c5 --- /dev/null +++ b/files/materials/shadowcaster.shader @@ -0,0 +1,56 @@ +#include "core.h" + +#define ALPHA @shPropertyBool(shadow_transparency) + +#ifdef SH_VERTEX_SHADER + + SH_BEGIN_PROGRAM +#if ALPHA + shVertexInput(float2, uv0) + shOutput(float2, UV) +#endif + shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + shOutput(float2, depth) + SH_START_PROGRAM + { + // this is the view space position + shOutputPosition = shMatrixMult(wvp, shInputPosition); + + // depth info for the fragment. + depth.x = shOutputPosition.z; + depth.y = shOutputPosition.w; + + // clamp z to zero. seem to do the trick. :-/ + shOutputPosition.z = max(shOutputPosition.z, 0); + +#if ALPHA + UV = uv0; +#endif + } + +#else + + SH_BEGIN_PROGRAM +#if ALPHA + shInput(float2, UV) + shSampler2D(texture1) +#endif + shInput(float2, depth) + SH_START_PROGRAM + { + float finalDepth = depth.x / depth.y; + + +#if ALPHA + // use alpha channel of the first texture + float alpha = shSample(texture1, UV).a; + + // discard if alpha is less than 0.5 + if (alpha < 1.0) + discard; +#endif + + shOutputColour(0) = float4(finalDepth, finalDepth, finalDepth, 1); + } + +#endif diff --git a/files/materials/shadowcaster.shaderset b/files/materials/shadowcaster.shaderset new file mode 100644 index 0000000000..5f4990ed11 --- /dev/null +++ b/files/materials/shadowcaster.shaderset @@ -0,0 +1,15 @@ +shader_set openmw_shadowcaster_vertex +{ + source shadowcaster.shader + type vertex + profiles_cg vs_2_0 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set openmw_shadowcaster_fragment +{ + source shadowcaster.shader + type fragment + profiles_cg ps_2_x ps_2_0 ps arbfp1 + profiles_hlsl ps_2_0 +} diff --git a/files/materials/shadows.h b/files/materials/shadows.h new file mode 100644 index 0000000000..9127d28f79 --- /dev/null +++ b/files/materials/shadows.h @@ -0,0 +1,45 @@ + +float depthShadowPCF (shTexture2D shadowMap, float4 shadowMapPos, float2 offset) +{ + shadowMapPos /= shadowMapPos.w; + float3 o = float3(offset.xy, -offset.x) * 0.3; + //float3 o = float3(0,0,0); + float c = (shadowMapPos.z <= shSample(shadowMap, shadowMapPos.xy - o.xy).r) ? 1 : 0; // top left + c += (shadowMapPos.z <= shSample(shadowMap, shadowMapPos.xy + o.xy).r) ? 1 : 0; // bottom right + c += (shadowMapPos.z <= shSample(shadowMap, shadowMapPos.xy + o.zy).r) ? 1 : 0; // bottom left + c += (shadowMapPos.z <= shSample(shadowMap, shadowMapPos.xy - o.zy).r) ? 1 : 0; // top right + return c / 4; +} + + + +float pssmDepthShadow ( + + + float4 lightSpacePos0, + float2 invShadowmapSize0, + shTexture2D shadowMap0, + + float4 lightSpacePos1, + float2 invShadowmapSize1, + shTexture2D shadowMap1, + + float4 lightSpacePos2, + float2 invShadowmapSize2, + shTexture2D shadowMap2, + + float depth, + float3 pssmSplitPoints) + +{ + float shadow; + + if (depth < pssmSplitPoints.x) + shadow = depthShadowPCF(shadowMap0, lightSpacePos0, invShadowmapSize0); + else if (depth < pssmSplitPoints.y) + shadow = depthShadowPCF(shadowMap1, lightSpacePos1, invShadowmapSize1); + else + shadow = depthShadowPCF(shadowMap2, lightSpacePos2, invShadowmapSize2); + + return shadow; +} diff --git a/files/materials/sky.mat b/files/materials/sky.mat new file mode 100644 index 0000000000..17da7fc130 --- /dev/null +++ b/files/materials/sky.mat @@ -0,0 +1,103 @@ +material openmw_moon +{ + allow_fixed_function false + pass + { + vertex_program moon_vertex + fragment_program moon_fragment + + polygon_mode_overrideable off + depth_write off + depth_check off + scene_blend alpha_blend + + texture_unit diffuseMap + { + texture_alias $texture + } + } +} + +material openmw_clouds +{ + allow_fixed_function false + pass + { + vertex_program clouds_vertex + fragment_program clouds_fragment + + polygon_mode_overrideable off + + scene_blend alpha_blend + depth_write off + + // second diffuse map is used for weather transitions + texture_unit diffuseMap1 + { + texture_alias cloud_texture_1 + } + + texture_unit diffuseMap2 + { + texture_alias cloud_texture_2 + } + } +} + +material openmw_atmosphere +{ + allow_fixed_function false + pass + { + vertex_program atmosphere_vertex + fragment_program atmosphere_fragment + + polygon_mode_overrideable off + + scene_blend alpha_blend + depth_write off + } +} + +material openmw_stars +{ + allow_fixed_function false + pass + { + vertex_program stars_vertex + fragment_program stars_fragment + + polygon_mode_overrideable off + + depth_check off + depth_write off + scene_blend alpha_blend + + texture_unit diffuseMap + { + direct_texture $texture + } + } +} + +// used for both sun and sun glare +material openmw_sun +{ + allow_fixed_function false + pass + { + vertex_program sun_vertex + fragment_program sun_fragment + + polygon_mode_overrideable off + + depth_check off + depth_write off + scene_blend alpha_blend + + texture_unit diffuseMap + { + direct_texture $texture + } + } +} diff --git a/files/materials/stars.shader b/files/materials/stars.shader new file mode 100644 index 0000000000..5a55d171e4 --- /dev/null +++ b/files/materials/stars.shader @@ -0,0 +1,46 @@ +#include "core.h" + +#define MRT @shGlobalSettingBool(mrt_output) + +#ifdef SH_VERTEX_SHADER + + SH_BEGIN_PROGRAM + shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + + shVertexInput(float2, uv0) + shOutput(float2, UV) + shOutput(float, fade) + + SH_START_PROGRAM + { + shOutputPosition = shMatrixMult(wvp, shInputPosition); + UV = uv0; + + fade = (shInputPosition.z > 50) ? 1 : 0; + } + +#else + + SH_BEGIN_PROGRAM +#if MRT + shDeclareMrtOutput(1) +#endif + + shInput(float2, UV) + shInput(float, fade) + + shSampler2D(diffuseMap) + shUniform(float, nightFade) @shSharedParameter(nightFade) + + + SH_START_PROGRAM + { + shOutputColour(0) = shSample(diffuseMap, UV) * float4(1,1,1, nightFade * fade); + + +#if MRT + shOutputColour(1) = float4(1,1,1,1); +#endif + } + +#endif diff --git a/files/materials/stars.shaderset b/files/materials/stars.shaderset new file mode 100644 index 0000000000..0f8803450b --- /dev/null +++ b/files/materials/stars.shaderset @@ -0,0 +1,15 @@ +shader_set stars_vertex +{ + source stars.shader + type vertex + profiles_cg vs_2_0 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set stars_fragment +{ + source stars.shader + type fragment + profiles_cg ps_2_x ps_2_0 ps arbfp1 + profiles_hlsl ps_2_0 +} diff --git a/files/materials/sun.shader b/files/materials/sun.shader new file mode 100644 index 0000000000..45cd2f24b8 --- /dev/null +++ b/files/materials/sun.shader @@ -0,0 +1,39 @@ +#include "core.h" + +#define MRT @shGlobalSettingBool(mrt_output) + + +#ifdef SH_VERTEX_SHADER + + SH_BEGIN_PROGRAM + shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + shVertexInput(float2, uv0) + shOutput(float2, UV) + + SH_START_PROGRAM + { + shOutputPosition = shMatrixMult(wvp, shInputPosition); + UV = uv0; + } + +#else + + SH_BEGIN_PROGRAM + shSampler2D(diffuseMap) + shInput(float2, UV) +#if MRT + shDeclareMrtOutput(1) +#endif + shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour) + //shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour) + + SH_START_PROGRAM + { + shOutputColour(0) = float4(1,1,1,materialDiffuse.a) * shSample(diffuseMap, UV); + +#if MRT + shOutputColour(1) = float4(1,1,1,1); +#endif + } + +#endif diff --git a/files/materials/sun.shaderset b/files/materials/sun.shaderset new file mode 100644 index 0000000000..1b9e92a439 --- /dev/null +++ b/files/materials/sun.shaderset @@ -0,0 +1,15 @@ +shader_set sun_vertex +{ + source sun.shader + type vertex + profiles_cg vs_2_0 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set sun_fragment +{ + source sun.shader + type fragment + profiles_cg ps_2_x ps_2_0 ps arbfp1 + profiles_hlsl ps_2_0 +} diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader new file mode 100644 index 0000000000..a562d1ec3b --- /dev/null +++ b/files/materials/terrain.shader @@ -0,0 +1,377 @@ +#include "core.h" + +#define IS_FIRST_PASS 1 + +#define FOG @shGlobalSettingBool(fog) +#define MRT @shGlobalSettingBool(mrt_output) + +#define LIGHTING @shGlobalSettingBool(lighting) + +#define SHADOWS_PSSM LIGHTING && @shGlobalSettingBool(shadows_pssm) +#define SHADOWS LIGHTING && @shGlobalSettingBool(shadows) + +#if SHADOWS || SHADOWS_PSSM +#include "shadows.h" +#endif + +#define COLOUR_MAP @shPropertyBool(colour_map) + +#define NUM_LAYERS @shPropertyString(num_layers) + +#if MRT || FOG || SHADOWS_PSSM +#define NEED_DEPTH 1 +#endif + +#define UNDERWATER @shGlobalSettingBool(underwater_effects) && LIGHTING + + +#if NEED_DEPTH +@shAllocatePassthrough(1, depth) +#endif + +@shAllocatePassthrough(2, UV) + +#if LIGHTING +@shAllocatePassthrough(3, objSpacePosition) +#endif + +#if SHADOWS +@shAllocatePassthrough(4, lightSpacePos0) +#endif +#if SHADOWS_PSSM +@shForeach(3) + @shAllocatePassthrough(4, lightSpacePos@shIterator) +@shEndForeach +#endif + +#ifdef SH_VERTEX_SHADER + + // ------------------------------------- VERTEX --------------------------------------- + + SH_BEGIN_PROGRAM + shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) + shUniform(float4x4, viewProjMatrix) @shAutoConstant(viewProjMatrix, viewproj_matrix) + + shUniform(float2, lodMorph) @shAutoConstant(lodMorph, custom, 1001) + + shVertexInput(float2, uv0) + shVertexInput(float2, delta) // lodDelta, lodThreshold + +#if SHADOWS + shUniform(float4x4, texViewProjMatrix0) @shAutoConstant(texViewProjMatrix0, texture_viewproj_matrix) +#endif + +#if SHADOWS_PSSM + @shForeach(3) + shUniform(float4x4, texViewProjMatrix@shIterator) @shAutoConstant(texViewProjMatrix@shIterator, texture_viewproj_matrix, @shIterator) + @shEndForeach +#endif + + + @shPassthroughVertexOutputs + + SH_START_PROGRAM + { + + + float4 worldPos = shMatrixMult(worldMatrix, shInputPosition); + + // determine whether to apply the LOD morph to this vertex + // we store the deltas against all vertices so we only want to apply + // the morph to the ones which would disappear. The target LOD which is + // being morphed to is stored in lodMorph.y, and the LOD at which + // the vertex should be morphed is stored in uv.w. If we subtract + // the former from the latter, and arrange to only morph if the + // result is negative (it will only be -1 in fact, since after that + // the vertex will never be indexed), we will achieve our aim. + // sign(vertexLOD - targetLOD) == -1 is to morph + float toMorph = -min(0, sign(delta.y - lodMorph.y)); + + // morph + // this assumes XZ terrain alignment + worldPos.y += delta.x * toMorph * lodMorph.x; + + + shOutputPosition = shMatrixMult(viewProjMatrix, worldPos); + +#if NEED_DEPTH + @shPassthroughAssign(depth, shOutputPosition.z); +#endif + + @shPassthroughAssign(UV, uv0); + +#if LIGHTING + @shPassthroughAssign(objSpacePosition, shInputPosition.xyz); +#endif + +#if SHADOWS + float4 lightSpacePos = shMatrixMult(texViewProjMatrix0, shMatrixMult(worldMatrix, shInputPosition)); + @shPassthroughAssign(lightSpacePos0, lightSpacePos); +#endif +#if SHADOWS_PSSM + float4 wPos = shMatrixMult(worldMatrix, shInputPosition); + + float4 lightSpacePos; + @shForeach(3) + lightSpacePos = shMatrixMult(texViewProjMatrix@shIterator, wPos); + @shPassthroughAssign(lightSpacePos@shIterator, lightSpacePos); + @shEndForeach +#endif + + } + +#else + + // ----------------------------------- FRAGMENT ------------------------------------------ + +#if UNDERWATER + #include "underwater.h" +#endif + + SH_BEGIN_PROGRAM + + +#if COLOUR_MAP + shSampler2D(colourMap) +#endif + + shSampler2D(normalMap) // global normal map + + +@shForeach(@shPropertyString(num_blendmaps)) + shSampler2D(blendMap@shIterator) +@shEndForeach + +@shForeach(@shPropertyString(num_layers)) + shSampler2D(diffuseMap@shIterator) +@shEndForeach + +#if FOG + shUniform(float3, fogColour) @shAutoConstant(fogColour, fog_colour) + shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params) +#endif + + @shPassthroughFragmentInputs + +#if MRT + shDeclareMrtOutput(1) + shUniform(float, far) @shAutoConstant(far, far_clip_distance) +#endif + + +#if LIGHTING + shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour) + @shForeach(@shGlobalSettingString(num_lights)) + shUniform(float4, lightPosObjSpace@shIterator) @shAutoConstant(lightPosObjSpace@shIterator, light_position_object_space, @shIterator) + shUniform(float4, lightAttenuation@shIterator) @shAutoConstant(lightAttenuation@shIterator, light_attenuation, @shIterator) + shUniform(float4, lightDiffuse@shIterator) @shAutoConstant(lightDiffuse@shIterator, light_diffuse_colour, @shIterator) + @shEndForeach +#endif + + +#if SHADOWS + shSampler2D(shadowMap0) + shUniform(float2, invShadowmapSize0) @shAutoConstant(invShadowmapSize0, inverse_texture_size, @shPropertyString(shadowtexture_offset)) +#endif +#if SHADOWS_PSSM + @shForeach(3) + shSampler2D(shadowMap@shIterator) + shUniform(float2, invShadowmapSize@shIterator) @shAutoConstant(invShadowmapSize@shIterator, inverse_texture_size, @shIterator(@shPropertyString(shadowtexture_offset))) + @shEndForeach + shUniform(float3, pssmSplitPoints) @shSharedParameter(pssmSplitPoints) +#endif + +#if SHADOWS || SHADOWS_PSSM + shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart) +#endif + + +#if UNDERWATER + shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) + shUniform(float, waterLevel) @shSharedParameter(waterLevel) + shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position) + shUniform(float4, lightDirectionWS0) @shAutoConstant(lightDirectionWS0, light_position, 0) + + shSampler2D(causticMap) + + shUniform(float, waterTimer) @shSharedParameter(waterTimer) + shUniform(float2, waterSunFade_sunHeight) @shSharedParameter(waterSunFade_sunHeight) + + shUniform(float3, windDir_windSpeed) @shSharedParameter(windDir_windSpeed) +#endif + + + SH_START_PROGRAM + { + +#if NEED_DEPTH + float depth = @shPassthroughReceive(depth); +#endif + + float2 UV = @shPassthroughReceive(UV); + +#if LIGHTING + float3 objSpacePosition = @shPassthroughReceive(objSpacePosition); + + float3 normal = shSample(normalMap, UV).rgb * 2 - 1; + normal = normalize(normal); +#endif + + + + float3 caustics = float3(1,1,1); +#if UNDERWATER + + float3 worldPos = shMatrixMult(worldMatrix, float4(objSpacePosition,1)).xyz; + float3 waterEyePos = float3(1,1,1); + if (worldPos.y < waterLevel) + { + // NOTE: this calculation would be wrong for non-uniform scaling + float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); + waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,1,0), waterLevel); + caustics = getCaustics(causticMap, worldPos, waterEyePos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); + } + +#endif + + + // Layer calculations +@shForeach(@shPropertyString(num_blendmaps)) + float4 blendValues@shIterator = shSample(blendMap@shIterator, UV); +@shEndForeach + + float3 albedo = float3(0,0,0); +@shForeach(@shPropertyString(num_layers)) + + +#if IS_FIRST_PASS == 1 && @shIterator == 0 + // first layer of first pass doesn't need a blend map + albedo = shSample(diffuseMap0, UV * 10).rgb; +#else + albedo = shLerp(albedo, shSample(diffuseMap@shIterator, UV * 10).rgb, blendValues@shPropertyString(blendmap_component_@shIterator)); + +#endif +@shEndForeach + + shOutputColour(0) = float4(1,1,1,1); + +#if COLOUR_MAP + shOutputColour(0).rgb *= shSample(colourMap, UV).rgb; +#endif + + shOutputColour(0).rgb *= albedo; + + + + + + + // Lighting + +#if LIGHTING + // shadows only for the first (directional) light +#if SHADOWS + float4 lightSpacePos0 = @shPassthroughReceive(lightSpacePos0); + float shadow = depthShadowPCF (shadowMap0, lightSpacePos0, invShadowmapSize0); +#endif +#if SHADOWS_PSSM + @shForeach(3) + float4 lightSpacePos@shIterator = @shPassthroughReceive(lightSpacePos@shIterator); + @shEndForeach + + float shadow = pssmDepthShadow (lightSpacePos0, invShadowmapSize0, shadowMap0, lightSpacePos1, invShadowmapSize1, shadowMap1, lightSpacePos2, invShadowmapSize2, shadowMap2, depth, pssmSplitPoints); +#endif + +#if SHADOWS || SHADOWS_PSSM + float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; + float fade = 1-((depth - shadowFar_fadeStart.y) / fadeRange); + shadow = (depth > shadowFar_fadeStart.x) ? 1 : ((depth > shadowFar_fadeStart.y) ? 1-((1-shadow)*fade) : shadow); +#endif + +#if !SHADOWS && !SHADOWS_PSSM + float shadow = 1.0; +#endif + + + + float3 lightDir; + float3 diffuse = float3(0,0,0); + float d; + + @shForeach(@shGlobalSettingString(num_lights)) + + lightDir = lightPosObjSpace@shIterator.xyz - (objSpacePosition.xyz * lightPosObjSpace@shIterator.w); + d = length(lightDir); + + + lightDir = normalize(lightDir); + +#if @shIterator == 0 + + #if (SHADOWS || SHADOWS_PSSM) + diffuse += lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0) * shadow * caustics; + + #else + diffuse += lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0) * caustics; + + #endif + +#else + diffuse += lightDiffuse@shIterator.xyz * (1.0 / ((lightAttenuation@shIterator.y) + (lightAttenuation@shIterator.z * d) + (lightAttenuation@shIterator.w * d * d))) * max(dot(normal, lightDir), 0); +#endif + + @shEndForeach + + shOutputColour(0).xyz *= (lightAmbient.xyz + diffuse); +#endif + + + + +#if FOG + float fogValue = shSaturate((depth - fogParams.y) * fogParams.w); + + #if UNDERWATER + // regular fog only if fragment is above water + if (worldPos.y > waterLevel) + #endif + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); +#endif + + // prevent negative colour output (for example with negative lights) + shOutputColour(0).xyz = max(shOutputColour(0).xyz, float3(0,0,0)); + +#if UNDERWATER + float fogAmount = (cameraPos.y > waterLevel) + ? shSaturate(length(waterEyePos-worldPos) / VISIBILITY) + : shSaturate(length(cameraPos.xyz-worldPos)/ VISIBILITY); + + float3 eyeVec = normalize(cameraPos.xyz-worldPos); + + 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; + + 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 + 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; + + + float darkness = VISIBILITY*2.0; + darkness = clamp((waterEyePos.y - waterLevel + darkness)/darkness,0.2,1.0); + watercolour *= darkness; + + float isUnderwater = (worldPos.y < waterLevel) ? 1.0 : 0.0; + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater); +#endif + + +#if MRT + shOutputColour(1) = float4(depth / far,1,1,1); +#endif + } + +#endif diff --git a/files/materials/terrain.shaderset b/files/materials/terrain.shaderset new file mode 100644 index 0000000000..4132b8e9c5 --- /dev/null +++ b/files/materials/terrain.shaderset @@ -0,0 +1,15 @@ +shader_set terrain_vertex +{ + source terrain.shader + type vertex + profiles_cg vs_2_0 vp40 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set terrain_fragment +{ + source terrain.shader + type fragment + profiles_cg ps_2_x ps_2_0 ps fp40 arbfp1 + profiles_hlsl ps_2_0 +} diff --git a/files/materials/underwater.h b/files/materials/underwater.h new file mode 100644 index 0000000000..fe19ff93b9 --- /dev/null +++ b/files/materials/underwater.h @@ -0,0 +1,118 @@ +#define VISIBILITY 1500.0 // how far you can look through water + +#define BIG_WAVES_X 0.3 // strength of big waves +#define BIG_WAVES_Y 0.3 + +#define MID_WAVES_X 0.3 // strength of middle sized waves +#define MID_WAVES_Y 0.15 + +#define SMALL_WAVES_X 0.15 // strength of small waves +#define SMALL_WAVES_Y 0.1 + +#define WAVE_CHOPPYNESS 0.15 // wave choppyness +#define WAVE_SCALE 0.01 // overall wave scale + +#define ABBERATION 0.001 // chromatic abberation amount + +#define SUN_EXT float3(0.45, 0.55, 0.68) //sunlight extinction + +float3 intercept(float3 lineP, + float3 lineN, + float3 planeN, + float planeD) +{ + + float distance = (planeD - dot(planeN, lineP)) / dot(lineN, planeN); + return lineP + lineN * distance; +} + +float3 perturb1(shTexture2D tex, float2 coords, float bend, float2 windDir, float windSpeed, float timer) +{ + float2 nCoord = float2(0.0); + bend *= WAVE_CHOPPYNESS; + nCoord = coords * (WAVE_SCALE * 0.05) + windDir * timer * (windSpeed*0.04); + float3 normal0 = 2.0 * shSample(tex, nCoord + float2(-timer*0.015,-timer*0.05)).rgb - 1.0; + nCoord = coords * (WAVE_SCALE * 0.1) + windDir * timer * (windSpeed*0.08)-normal0.xy*bend; + float3 normal1 = 2.0 * shSample(tex, nCoord + float2(+timer*0.020,+timer*0.015)).rgb - 1.0; + + nCoord = coords * (WAVE_SCALE * 0.25) + windDir * timer * (windSpeed*0.07)-normal1.xy*bend; + float3 normal2 = 2.0 * shSample(tex, nCoord + float2(-timer*0.04,-timer*0.03)).rgb - 1.0; + nCoord = coords * (WAVE_SCALE * 0.5) + windDir * timer * (windSpeed*0.09)-normal2.xy*bend; + float3 normal3 = 2.0 * shSample(tex, nCoord + float2(+timer*0.03,+timer*0.04)).rgb - 1.0; + + nCoord = coords * (WAVE_SCALE* 1.0) + windDir * timer * (windSpeed*0.4)-normal3.xy*bend; + float3 normal4 = 2.0 * shSample(tex, nCoord + float2(-timer*0.2,+timer*0.1)).rgb - 1.0; + nCoord = coords * (WAVE_SCALE * 2.0) + windDir * timer * (windSpeed*0.7)-normal4.xy*bend; + float3 normal5 = 2.0 * shSample(tex, nCoord + float2(+timer*0.1,-timer*0.06)).rgb - 1.0; + + + float3 normal = normalize(normal0 * BIG_WAVES_X + normal1 * BIG_WAVES_Y + + normal2 * MID_WAVES_X + normal3 * MID_WAVES_Y + + normal4 * SMALL_WAVES_X + normal5 * SMALL_WAVES_Y); + return normal; +} + +float3 perturb(shTexture2D tex, float2 coords, float bend, float2 windDir, float windSpeed, float timer) +{ + bend *= WAVE_CHOPPYNESS; + float3 col = float3(0.0); + float2 nCoord = float2(0.0); //normal coords + + nCoord = coords * (WAVE_SCALE * 0.025) + windDir * timer * (windSpeed*0.03); + col += shSample(tex,nCoord + float2(-timer*0.005,-timer*0.01)).rgb*0.20; + nCoord = coords * (WAVE_SCALE * 0.1) + windDir * timer * (windSpeed*0.05)-(col.xy/col.zz)*bend; + col += shSample(tex,nCoord + float2(+timer*0.01,+timer*0.005)).rgb*0.20; + + nCoord = coords * (WAVE_SCALE * 0.2) + windDir * timer * (windSpeed*0.1)-(col.xy/col.zz)*bend; + col += shSample(tex,nCoord + float2(-timer*0.02,-timer*0.03)).rgb*0.20; + nCoord = coords * (WAVE_SCALE * 0.5) + windDir * timer * (windSpeed*0.2)-(col.xy/col.zz)*bend; + col += shSample(tex,nCoord + float2(+timer*0.03,+timer*0.02)).rgb*0.15; + + nCoord = coords * (WAVE_SCALE* 0.8) + windDir * timer * (windSpeed*1.0)-(col.xy/col.zz)*bend; + col += shSample(tex, nCoord + float2(-timer*0.06,+timer*0.08)).rgb*0.15; + nCoord = coords * (WAVE_SCALE * 1.0) + windDir * timer * (windSpeed*1.3)-(col.xy/col.zz)*bend; + col += shSample(tex,nCoord + float2(+timer*0.08,-timer*0.06)).rgb*0.10; + + return col; +} + + +float3 getCaustics (shTexture2D causticMap, float3 worldPos, float3 waterEyePos, float3 worldNormal, float3 lightDirectionWS0, float waterLevel, float waterTimer, float3 windDir_windSpeed) +{ + float waterDepth = shSaturate((waterEyePos.y - worldPos.y) / 50.0); + + float3 causticPos = intercept(worldPos.xyz, lightDirectionWS0.xyz, float3(0,1,0), waterLevel); + + ///\ todo clean this up + float causticdepth = length(causticPos-worldPos.xyz); + causticdepth = 1.0-shSaturate(causticdepth / VISIBILITY); + causticdepth = shSaturate(causticdepth); + + // NOTE: the original shader calculated a tangent space basis here, + // but using only the world normal is cheaper and i couldn't see a visual difference + // also, if this effect gets moved to screen-space some day, it's unlikely to have tangent information + float3 causticNorm = worldNormal.xyz * perturb(causticMap, causticPos.xz, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).xzy * 2 - 1; + + //float fresnel = pow(clamp(dot(LV,causticnorm),0.0,1.0),2.0); + + float NdotL = max(dot(worldNormal.xyz, lightDirectionWS0.xyz),0.0); + + float causticR = 1.0-perturb(causticMap, causticPos.xz, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).z; + + /// \todo sunFade + + // float3 caustics = clamp(pow(float3(causticR)*5.5,float3(5.5*causticdepth)),0.0,1.0)*NdotL*sunFade*causticdepth; + float3 caustics = clamp(pow(float3(causticR)*5.5,float3(5.5*causticdepth)),0.0,1.0)*NdotL*causticdepth; + float causticG = 1.0-perturb(causticMap,causticPos.xz+(1.0-causticdepth)*ABBERATION, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).z; + float causticB = 1.0-perturb(causticMap,causticPos.xz+(1.0-causticdepth)*ABBERATION*2.0, causticdepth, windDir_windSpeed.xy, windDir_windSpeed.z, waterTimer).z; + //caustics = shSaturate(pow(float3(causticR,causticG,causticB)*5.5,float3(5.5*causticdepth)))*NdotL*sunFade*causticdepth; + caustics = shSaturate(pow(float3(causticR,causticG,causticB)*5.5,float3(5.5*causticdepth)))*NdotL*causticdepth; + + caustics *= 3; + + // shore transition + caustics = shLerp (float3(1,1,1), caustics, waterDepth); + + return caustics; +} + diff --git a/files/materials/water.mat b/files/materials/water.mat new file mode 100644 index 0000000000..dcea5a0d07 --- /dev/null +++ b/files/materials/water.mat @@ -0,0 +1,55 @@ +material Water +{ + pass + { + emissive 0.6 0.7 1.0 + ambient 0 0 0 + diffuse 0 0 0 1 + specular 0 0 0 32 + + vertex_program water_vertex + fragment_program water_fragment + + cull_hardware none + + texture_unit reflectionMap + { + texture_alias WaterReflection + tex_address_mode clamp + } + + texture_unit refractionMap + { + texture_alias WaterRefraction + tex_address_mode clamp + } + + texture_unit depthMap + { + texture_alias SceneDepth + tex_address_mode clamp + } + + texture_unit normalMap + { + direct_texture water_nm.png + } + + + // for simple_water + texture_unit animatedTexture + { + create_in_ffp true + scale 0.1 0.1 + alpha_op_ex source1 src_manual src_current 0.7 + } + } +} + + +material Underwater_Dome +{ + parent openmw_objects_base + + depth_write off +} diff --git a/files/materials/water.shader b/files/materials/water.shader new file mode 100644 index 0000000000..2145919b0e --- /dev/null +++ b/files/materials/water.shader @@ -0,0 +1,307 @@ +#include "core.h" + + +#define SIMPLE_WATER @shGlobalSettingBool(simple_water) + + +#if SIMPLE_WATER + // --------------------------------------- SIMPLE WATER --------------------------------------------------- + + + #define MRT @shGlobalSettingBool(mrt_output) + + +#ifdef SH_VERTEX_SHADER + + SH_BEGIN_PROGRAM + shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + shVertexInput(float2, uv0) + shOutput(float2, UV) + shOutput(float, depth) + + SH_START_PROGRAM + { + shOutputPosition = shMatrixMult(wvp, shInputPosition); + UV = uv0; + depth = shOutputPosition.z; + } + +#else + + SH_BEGIN_PROGRAM + shSampler2D(animatedTexture) + shInput(float2, UV) + shInput(float, depth) +#if MRT + shDeclareMrtOutput(1) +#endif + + shUniform(float3, fogColor) @shAutoConstant(fogColor, fog_colour) + shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params) + + + SH_START_PROGRAM + { + shOutputColour(0).xyz = shSample(animatedTexture, UV * 15).xyz * float3(0.6, 0.7, 1.0); + shOutputColour(0).w = 0.7; + + float fogValue = shSaturate((depth - fogParams.y) * fogParams.w); + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue); + +#if MRT + shOutputColour(1) = float4(1,1,1,1); +#endif + } + +#endif + +#else + + + +// Inspired by Blender GLSL Water by martinsh ( http://devlog-martinsh.blogspot.de/2012/07/waterundewater-shader-wip.html ) + + + +#ifdef SH_VERTEX_SHADER + + SH_BEGIN_PROGRAM + shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + shVertexInput(float2, uv0) + shOutput(float2, UV) + + shOutput(float3, screenCoordsPassthrough) + shOutput(float4, position) + shOutput(float, depthPassthrough) + + SH_START_PROGRAM + { + shOutputPosition = shMatrixMult(wvp, shInputPosition); + UV = uv0; + + + #if !SH_GLSL + float4x4 scalemat = float4x4( 0.5, 0, 0, 0.5, + 0, -0.5, 0, 0.5, + 0, 0, 0.5, 0.5, + 0, 0, 0, 1 ); + #else + mat4 scalemat = mat4(0.5, 0.0, 0.0, 0.0, + 0.0, -0.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.5, 0.5, 0.5, 1.0); + #endif + + float4 texcoordProj = shMatrixMult(scalemat, shOutputPosition); + screenCoordsPassthrough = float3(texcoordProj.x, texcoordProj.y, texcoordProj.w); + + position = shInputPosition; + + depthPassthrough = shOutputPosition.z; + } + +#else + + // tweakables ---------------------------------------------------- + + #define VISIBILITY 1500.0 // how far you can look through water + + #define BIG_WAVES_X 0.3 // strength of big waves + #define BIG_WAVES_Y 0.3 + + #define MID_WAVES_X 0.3 // strength of middle sized waves + #define MID_WAVES_Y 0.15 + + #define SMALL_WAVES_X 0.15 // strength of small waves + #define SMALL_WAVES_Y 0.1 + + #define WAVE_CHOPPYNESS 0.15 // wave choppyness + #define WAVE_SCALE 75 // overall wave scale + + #define ABBERATION 0.001 // chromatic abberation amount + #define BUMP 1.5 // overall water surface bumpiness + #define REFL_BUMP 0.08 // reflection distortion amount + #define REFR_BUMP 0.06 // refraction distortion amount + + #define SCATTER_AMOUNT 3.0 // amount of sunlight scattering + #define SCATTER_COLOUR float3(0.0,1.0,0.95) // colour of sunlight scattering + + #define SUN_EXT float3(0.45, 0.55, 0.68) //sunlight extinction + + #define SPEC_HARDNESS 256 // specular highlights hardness + + + // --------------------------------------------------------------- + + + + float fresnel_dielectric(float3 Incoming, float3 Normal, float eta) + { + /* compute fresnel reflectance without explicitly computing + the refracted direction */ + float c = abs(dot(Incoming, Normal)); + float g = eta * eta - 1.0 + c * c; + float result; + + if(g > 0.0) { + g = sqrt(g); + float A =(g - c)/(g + c); + float B =(c *(g + c)- 1.0)/(c *(g - c)+ 1.0); + result = 0.5 * A * A *(1.0 + B * B); + } + else + result = 1.0; /* TIR (no refracted component) */ + + return result; + } + + SH_BEGIN_PROGRAM + shInput(float2, UV) + shInput(float3, screenCoordsPassthrough) + shInput(float4, position) + shInput(float, depthPassthrough) + + shUniform(float, far) @shAutoConstant(far, far_clip_distance) + + shSampler2D(reflectionMap) + shSampler2D(refractionMap) + shSampler2D(depthMap) + shSampler2D(normalMap) + + shUniform(float3, windDir_windSpeed) @shSharedParameter(windDir_windSpeed) + #define WIND_SPEED windDir_windSpeed.z + #define WIND_DIR windDir_windSpeed.xy + + shUniform(float, waterTimer) @shSharedParameter(waterTimer) + shUniform(float2, waterSunFade_sunHeight) @shSharedParameter(waterSunFade_sunHeight) + + shUniform(float4, sunPosition) @shAutoConstant(sunPosition, light_position, 0) + shUniform(float4, sunSpecular) @shAutoConstant(sunSpecular, light_specular_colour, 0) + + + + shUniform(float, renderTargetFlipping) @shAutoConstant(renderTargetFlipping, render_target_flipping) + + + shUniform(float3, fogColor) @shAutoConstant(fogColor, fog_colour) + shUniform(float4, fogParams) @shAutoConstant(fogParams, fog_params) + + shUniform(float4, cameraPos) @shAutoConstant(cameraPos, camera_position_object_space) + + + SH_START_PROGRAM + { + + float2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z; + screenCoords.y = (1-shSaturate(renderTargetFlipping))+renderTargetFlipping*screenCoords.y; + + float depth = shSample(depthMap, screenCoords).x * far - depthPassthrough; + float shoreFade = shSaturate(depth / 50.0); + + float2 nCoord = float2(0.0); + + nCoord = UV * (WAVE_SCALE * 0.05) + WIND_DIR * waterTimer * (WIND_SPEED*0.04); + float3 normal0 = 2.0 * shSample(normalMap, nCoord + float2(-waterTimer*0.015,-waterTimer*0.005)).rgb - 1.0; + nCoord = UV * (WAVE_SCALE * 0.1) + WIND_DIR * waterTimer * (WIND_SPEED*0.08)-(normal0.xy/normal0.zz)*WAVE_CHOPPYNESS; + float3 normal1 = 2.0 * shSample(normalMap, nCoord + float2(+waterTimer*0.020,+waterTimer*0.015)).rgb - 1.0; + + nCoord = UV * (WAVE_SCALE * 0.25) + WIND_DIR * waterTimer * (WIND_SPEED*0.07)-(normal1.xy/normal1.zz)*WAVE_CHOPPYNESS; + float3 normal2 = 2.0 * shSample(normalMap, nCoord + float2(-waterTimer*0.04,-waterTimer*0.03)).rgb - 1.0; + nCoord = UV * (WAVE_SCALE * 0.5) + WIND_DIR * waterTimer * (WIND_SPEED*0.09)-(normal2.xy/normal2.z)*WAVE_CHOPPYNESS; + float3 normal3 = 2.0 * shSample(normalMap, nCoord + float2(+waterTimer*0.03,+waterTimer*0.04)).rgb - 1.0; + + nCoord = UV * (WAVE_SCALE* 1.0) + WIND_DIR * waterTimer * (WIND_SPEED*0.4)-(normal3.xy/normal3.zz)*WAVE_CHOPPYNESS; + float3 normal4 = 2.0 * shSample(normalMap, nCoord + float2(-waterTimer*0.02,+waterTimer*0.1)).rgb - 1.0; + nCoord = UV * (WAVE_SCALE * 2.0) + WIND_DIR * waterTimer * (WIND_SPEED*0.7)-(normal4.xy/normal4.zz)*WAVE_CHOPPYNESS; + float3 normal5 = 2.0 * shSample(normalMap, nCoord + float2(+waterTimer*0.1,-waterTimer*0.06)).rgb - 1.0; + + + + float3 normal = (normal0 * BIG_WAVES_X + normal1 * BIG_WAVES_Y + + normal2 * MID_WAVES_X + normal3 * MID_WAVES_Y + + normal4 * SMALL_WAVES_X + normal5 * SMALL_WAVES_Y).xzy; + + normal = normalize(float3(normal.x * BUMP, normal.y, normal.z * BUMP)); + + // normal for sunlight scattering + float3 lNormal = (normal0 * BIG_WAVES_X*0.5 + normal1 * BIG_WAVES_Y*0.5 + + normal2 * MID_WAVES_X*0.2 + normal3 * MID_WAVES_Y*0.2 + + normal4 * SMALL_WAVES_X*0.1 + normal5 * SMALL_WAVES_Y*0.1).xzy; + lNormal = normalize(float3(lNormal.x * BUMP, lNormal.y, lNormal.z * BUMP)); + + + float3 lVec = normalize(sunPosition.xyz); + float3 vVec = normalize(position.xyz - cameraPos.xyz); + + + float isUnderwater = (cameraPos.y > 0) ? 0.0 : 1.0; + + // sunlight scattering + float3 pNormal = float3(0,1,0); + vec3 lR = reflect(lVec, lNormal); + vec3 llR = reflect(lVec, pNormal); + + float s = shSaturate(dot(lR, vVec)*2.0-1.2); + float lightScatter = shSaturate(dot(-lVec,lNormal)*0.7+0.3) * s * SCATTER_AMOUNT * waterSunFade_sunHeight.x * shSaturate(1.0-exp(-waterSunFade_sunHeight.y)); + float3 scatterColour = shLerp(vec3(SCATTER_COLOUR)*vec3(1.0,0.4,0.0), SCATTER_COLOUR, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); + + // fresnel + float ior = (cameraPos.y>0)?(1.333/1.0):(1.0/1.333); //air to water; water to air + float fresnel = fresnel_dielectric(-vVec, normal, ior); + + fresnel = shSaturate(fresnel); + + // reflection + float3 reflection = shSample(reflectionMap, screenCoords+(normal.xz*REFL_BUMP)).rgb; + + // refraction + float3 R = reflect(vVec, normal); + + float3 refraction = float3(0,0,0); + refraction.r = shSample(refractionMap, (screenCoords-(shoreFade * normal.xz*REFR_BUMP))*1.0).r; + refraction.g = shSample(refractionMap, (screenCoords-(shoreFade * normal.xz*REFR_BUMP))*1.0-(R.xy*ABBERATION)).g; + refraction.b = shSample(refractionMap, (screenCoords-(shoreFade * normal.xz*REFR_BUMP))*1.0-(R.xy*ABBERATION*2.0)).b; + + // brighten up the refraction underwater + refraction = (cameraPos.y < 0) ? shSaturate(refraction * 1.5) : refraction; + + // specular + float specular = pow(max(dot(R, lVec), 0.0),SPEC_HARDNESS); + + shOutputColour(0).xyz = shLerp( shLerp(refraction, scatterColour, lightScatter), reflection, fresnel) + specular * sunSpecular.xyz; + + // smooth transition to shore (above water only) + shOutputColour(0).xyz = shLerp(shOutputColour(0).xyz, refraction, (1-shoreFade) * (1-isUnderwater)); + + // fog + if (isUnderwater == 1) + { + float waterSunGradient = dot(-vVec, -lVec); + waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); + float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; + + float waterGradient = dot(-vVec, 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 + watercolour = mix(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); + + float darkness = VISIBILITY*2.0; + darkness = clamp((cameraPos.y+darkness)/darkness,0.2,1.0); + + + float fog = shSaturate(length(cameraPos.xyz-position.xyz) / VISIBILITY); + shOutputColour(0).xyz = shLerp(shOutputColour(0).xyz, watercolour * darkness, shSaturate(fog / waterext)); + } + else + { + float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w); + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColor, fogValue); + } + + } + +#endif + + +#endif diff --git a/files/materials/water.shaderset b/files/materials/water.shaderset new file mode 100644 index 0000000000..754ac8e49f --- /dev/null +++ b/files/materials/water.shaderset @@ -0,0 +1,15 @@ +shader_set water_vertex +{ + source water.shader + type vertex + profiles_cg vs_2_0 vp40 arbvp1 + profiles_hlsl vs_2_0 +} + +shader_set water_fragment +{ + source water.shader + type fragment + profiles_cg ps_2_x ps_2_0 ps fp40 arbfp1 + profiles_hlsl ps_2_0 +} diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index f41cdf54e8..ae007f023f 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -1,68 +1,72 @@ -# Minimal MyGUI build system for OpenMW # Copy resource files into the build directory set(SDIR ${CMAKE_CURRENT_SOURCE_DIR}) set(DDIR ${OpenMW_BINARY_DIR}/resources/mygui) -configure_file("${SDIR}/bigbars.png" "${DDIR}/bigbars.png" COPYONLY) -configure_file("${SDIR}/black.png" "${DDIR}/black.png" COPYONLY) -configure_file("${SDIR}/core.skin" "${DDIR}/core.skin" COPYONLY) -configure_file("${SDIR}/core.xml" "${DDIR}/core.xml" COPYONLY) -configure_file("${SDIR}/mwgui.png" "${DDIR}/mwgui.png" COPYONLY) -configure_file("${SDIR}/openmw_resources.xml" "${DDIR}/openmw_resources.xml" COPYONLY) -configure_file("${SDIR}/openmw_settings.xml" "${DDIR}/openmw_settings.xml" COPYONLY) -configure_file("${SDIR}/openmw_box.skin.xml" "${DDIR}/openmw_box.skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_button.skin.xml" "${DDIR}/openmw_button.skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_list.skin.xml" "${DDIR}/openmw_list.skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_edit.skin.xml" "${DDIR}/openmw_edit.skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_console.layout" "${DDIR}/openmw_console.layout" COPYONLY) -configure_file("${SDIR}/openmw_console.skin.xml" "${DDIR}/openmw_console.skin.xml" COPYONLY) -configure_file("${SDIR}/openmw.font.xml" "${DDIR}/openmw.font.xml" COPYONLY) -configure_file("${SDIR}/openmw_hud_box.skin.xml" "${DDIR}/openmw_hud_box.skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_hud_energybar.skin.xml" "${DDIR}/openmw_hud_energybar.skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_hud.layout" "${DDIR}/openmw_hud.layout" COPYONLY) -configure_file("${SDIR}/openmw_text_input.layout" "${DDIR}/openmw_text_input.layout" COPYONLY) -configure_file("${SDIR}/openmw_infobox.layout" "${DDIR}/openmw_infobox.layout" COPYONLY) -configure_file("${SDIR}/openmw_chargen_race.layout" "${DDIR}/openmw_chargen_race.layout" COPYONLY) -configure_file("${SDIR}/openmw_chargen_class.layout" "${DDIR}/openmw_chargen_class.layout" COPYONLY) -configure_file("${SDIR}/openmw_chargen_generate_class_result.layout" "${DDIR}/openmw_chargen_generate_class_result.layout" COPYONLY) -configure_file("${SDIR}/openmw_chargen_create_class.layout" "${DDIR}/openmw_chargen_create_class.layout" COPYONLY) -configure_file("${SDIR}/openmw_chargen_select_specialization.layout" "${DDIR}/openmw_chargen_select_specialization.layout" COPYONLY) -configure_file("${SDIR}/openmw_chargen_select_attribute.layout" "${DDIR}/openmw_chargen_select_attribute.layout" COPYONLY) -configure_file("${SDIR}/openmw_chargen_select_skill.layout" "${DDIR}/openmw_chargen_select_skill.layout" COPYONLY) -configure_file("${SDIR}/openmw_chargen_class_description.layout" "${DDIR}/openmw_chargen_class_description.layout" COPYONLY) -configure_file("${SDIR}/openmw_chargen_birth.layout" "${DDIR}/openmw_chargen_birth.layout" COPYONLY) -configure_file("${SDIR}/openmw_chargen_review.layout" "${DDIR}/openmw_chargen_review.layout" COPYONLY) -configure_file("${SDIR}/openmw_dialogue_window.layout" "${DDIR}/openmw_dialogue_window.layout" COPYONLY) -configure_file("${SDIR}/openmw_dialogue_window_skin.xml" "${DDIR}/openmw_dialogue_window_skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_inventory_window.layout" "${DDIR}/openmw_inventory_window.layout" COPYONLY) -configure_file("${SDIR}/openmw_container_window.layout" "${DDIR}/openmw_container_window.layout" COPYONLY) -configure_file("${SDIR}/openmw_layers.xml" "${DDIR}/openmw_layers.xml" COPYONLY) -configure_file("${SDIR}/openmw_mainmenu.layout" "${DDIR}/openmw_mainmenu.layout" COPYONLY) -configure_file("${SDIR}/openmw_mainmenu_skin.xml" "${DDIR}/openmw_mainmenu_skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_map_window.layout" "${DDIR}/openmw_map_window.layout" COPYONLY) -configure_file("${SDIR}/openmw_map_window_skin.xml" "${DDIR}/openmw_map_window_skin.xml" COPYONLY) -configure_file("${SDIR}/openmw.pointer.xml" "${DDIR}/openmw.pointer.xml" COPYONLY) -configure_file("${SDIR}/openmw_progress.skin.xml" "${DDIR}/openmw_progress.skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_stats_window.layout" "${DDIR}/openmw_stats_window.layout" COPYONLY) -configure_file("${SDIR}/openmw_text.skin.xml" "${DDIR}/openmw_text.skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_windows.skin.xml" "${DDIR}/openmw_windows.skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_messagebox.layout" "${DDIR}/openmw_messagebox.layout" COPYONLY) -configure_file("${SDIR}/openmw_interactive_messagebox.layout" "${DDIR}/openmw_interactive_messagebox.layout" COPYONLY) -configure_file("${SDIR}/openmw_journal.layout" "${DDIR}/openmw_journal.layout" COPYONLY) -configure_file("${SDIR}/openmw_journal_skin.xml" "${DDIR}/openmw_journal_skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_tooltips.layout" "${DDIR}/openmw_tooltips.layout" COPYONLY) -configure_file("${SDIR}/openmw_scroll.layout" "${DDIR}/openmw_scroll.layout" COPYONLY) -configure_file("${SDIR}/openmw_scroll_skin.xml" "${DDIR}/openmw_scroll_skin.xml" COPYONLY) -configure_file("${SDIR}/openmw_book.layout" "${DDIR}/openmw_book.layout" COPYONLY) -configure_file("${SDIR}/openmw_count_window.layout" "${DDIR}/openmw_count_window.layout" COPYONLY) -configure_file("${SDIR}/openmw_trade_window.layout" "${DDIR}/openmw_trade_window.layout" COPYONLY) -configure_file("${SDIR}/openmw_settings_window.layout" "${DDIR}/openmw_settings_window.layout" COPYONLY) -configure_file("${SDIR}/openmw_confirmation_dialog.layout" "${DDIR}/openmw_confirmation_dialog.layout" COPYONLY) -configure_file("${SDIR}/openmw_alchemy_window.layout" "${DDIR}/openmw_alchemy_window.layout" COPYONLY) -configure_file("${SDIR}/openmw_spell_window.layout" "${DDIR}/openmw_spell_window.layout" COPYONLY) -configure_file("${SDIR}/atlas1.cfg" "${DDIR}/atlas1.cfg" COPYONLY) -configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) -configure_file("${SDIR}/EBGaramond-Regular.ttf" "${DDIR}/EBGaramond-Regular.ttf" COPYONLY) -configure_file("${SDIR}/Obliviontt.zip" "${DDIR}/Obliviontt.zip" COPYONLY) -configure_file("${SDIR}/VeraMono.ttf" "${DDIR}/VeraMono.ttf" COPYONLY) +set(MYGUI_FILES + atlas1.cfg + bigbars.png + black.png + core.skin + core.xml + EBGaramond-Regular.ttf + mwgui.png + Obliviontt.zip + openmw_alchemy_window.layout + openmw_book.layout + openmw_box.skin.xml + openmw_button.skin.xml + openmw_chargen_birth.layout + openmw_chargen_class_description.layout + openmw_chargen_class.layout + openmw_chargen_create_class.layout + openmw_chargen_generate_class_result.layout + openmw_chargen_race.layout + openmw_chargen_review.layout + openmw_chargen_select_attribute.layout + openmw_chargen_select_skill.layout + openmw_chargen_select_specialization.layout + openmw_confirmation_dialog.layout + openmw_console.layout + openmw_console.skin.xml + openmw_container_window.layout + openmw_count_window.layout + openmw_dialogue_window.layout + openmw_dialogue_window_skin.xml + openmw_edit.skin.xml + openmw.font.xml + openmw_hud_box.skin.xml + openmw_hud_energybar.skin.xml + openmw_hud.layout + openmw_infobox.layout + openmw_interactive_messagebox.layout + openmw_inventory_window.layout + openmw_journal.layout + openmw_journal_skin.xml + openmw_layers.xml + openmw_list.skin.xml + openmw_mainmenu.layout + openmw_mainmenu_skin.xml + openmw_map_window.layout + openmw_map_window_skin.xml + openmw_messagebox.layout + openmw.pointer.xml + openmw_progress.skin.xml + openmw_resources.xml + openmw_scroll.layout + openmw_scroll_skin.xml + openmw_settings_window.layout + openmw_settings.xml + openmw_spell_window.layout + openmw_stats_window.layout + openmw_text_input.layout + openmw_text.skin.xml + openmw_tooltips.layout + openmw_trade_window.layout + openmw_windows.skin.xml + smallbars.png + VeraMono.ttf +) + + +copy_all_files(${CMAKE_CURRENT_SOURCE_DIR} ${DDIR} "${MYGUI_FILES}") diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 7c508b1e97..07c307324a 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -1,7 +1,10 @@ - + + + + @@ -100,6 +103,12 @@ + + + + + + @@ -179,6 +188,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_windows.skin.xml b/files/mygui/openmw_windows.skin.xml index b379f84ced..a9eb23d68a 100644 --- a/files/mygui/openmw_windows.skin.xml +++ b/files/mygui/openmw_windows.skin.xml @@ -322,6 +322,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/plugins.cfg.linux b/files/plugins.cfg.linux deleted file mode 100644 index 7b8d99e8fd..0000000000 --- a/files/plugins.cfg.linux +++ /dev/null @@ -1,11 +0,0 @@ -# Defines plugins to load - -# Define plugin folder -PluginFolder=${OGRE_PLUGIN_DIR_REL} - -# Define plugins -Plugin=RenderSystem_GL${DEBUG_SUFFIX} -Plugin=Plugin_ParticleFX${DEBUG_SUFFIX} -Plugin=Plugin_OctreeSceneManager${DEBUG_SUFFIX} -Plugin=Plugin_CgProgramManager${DEBUG_SUFFIX} - diff --git a/files/plugins.cfg.mac b/files/plugins.cfg.mac deleted file mode 100644 index fac18dc8f8..0000000000 --- a/files/plugins.cfg.mac +++ /dev/null @@ -1,12 +0,0 @@ -# Defines plugins to load - -# Define plugin folder -PluginFolder=${OGRE_PLUGIN_DIR} - -# Define plugins -Plugin=RenderSystem_GL${DEBUG_SUFFIX}.1.8.0 -Plugin=Plugin_ParticleFX${DEBUG_SUFFIX}.1.8.0 -Plugin=Plugin_OctreeSceneManager${DEBUG_SUFFIX}.1.8.0 -Plugin=Plugin_CgProgramManager${DEBUG_SUFFIX}.1.8.0 - - diff --git a/files/plugins.cfg.win32 b/files/plugins.cfg.win32 deleted file mode 100644 index 6b4e9ef9dc..0000000000 --- a/files/plugins.cfg.win32 +++ /dev/null @@ -1,13 +0,0 @@ -# Defines plugins to load - -# Define plugin folder -PluginFolder=.\ - -# Define plugins -Plugin=RenderSystem_Direct3D9${DEBUG_SUFFIX} -Plugin=RenderSystem_GL${DEBUG_SUFFIX} -Plugin=Plugin_ParticleFX${DEBUG_SUFFIX} -Plugin=Plugin_OctreeSceneManager${DEBUG_SUFFIX} -Plugin=Plugin_CgProgramManager${DEBUG_SUFFIX} - - diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 883f32ae07..a723e307c8 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -48,6 +48,8 @@ anisotropy = 4 # Number of texture mipmaps to generate num mipmaps = 5 +shader mode = + [Shadows] # Shadows are only supported when object shaders are on! enabled = false @@ -74,6 +76,8 @@ statics shadows = true # Fraction of the total shadow distance after which the shadow starts to fade out fade start = 0.8 +debug = false + [HUD] # FPS counter # 0: not visible diff --git a/files/shadows/depthshadowcaster.cg b/files/shadows/depthshadowcaster.cg deleted file mode 100644 index 3457a4f8d8..0000000000 --- a/files/shadows/depthshadowcaster.cg +++ /dev/null @@ -1,51 +0,0 @@ -void main_vp( - float4 position : POSITION, - float2 uv : TEXCOORD0, - - out float4 oPosition : POSITION, - out float2 oDepth : TEXCOORD0, - out float2 oUv : TEXCOORD1, - - uniform float4x4 wvpMat) -{ - // this is the view space position - oPosition = mul(wvpMat, position); - - // depth info for the fragment. - oDepth.x = oPosition.z; - oDepth.y = oPosition.w; - - // clamp z to zero. seem to do the trick. :-/ - oPosition.z = max(oPosition.z, 0); - - oUv = uv; -} - -void main_fp( - float2 depth : TEXCOORD0, - float2 uv : TEXCOORD1, - uniform sampler2D texture1 : register(s0), - - out float4 oColour : COLOR) -{ - float finalDepth = depth.x / depth.y; - - // use alpha channel of the first texture - float alpha = tex2D(texture1, uv).a; - - // discard if alpha is less than 0.5 - clip((alpha >= 0.5) ? 1 : -1); - - oColour = float4(finalDepth, finalDepth, finalDepth, 1); -} - -void main_fp_noalpha( - float2 depth : TEXCOORD0, - float2 uv : TEXCOORD1, - - out float4 oColour : COLOR) -{ - float finalDepth = depth.x / depth.y; - - oColour = float4(finalDepth, finalDepth, finalDepth, 1); -} diff --git a/files/shadows/depthshadowcaster.material b/files/shadows/depthshadowcaster.material deleted file mode 100644 index f645cad019..0000000000 --- a/files/shadows/depthshadowcaster.material +++ /dev/null @@ -1,73 +0,0 @@ -vertex_program depth_shadow_caster_vs cg -{ - source depthshadowcaster.cg - profiles vs_1_1 arbvp1 - entry_point main_vp - - default_params - { - param_named_auto wvpMat worldviewproj_matrix - } -} - -fragment_program depth_shadow_caster_ps cg -{ - source depthshadowcaster.cg - profiles ps_2_0 arbfp1 - entry_point main_fp - - default_params - { - } -} - -fragment_program depth_shadow_caster_ps_noalpha cg -{ - source depthshadowcaster.cg - profiles ps_2_0 arbfp1 - entry_point main_fp_noalpha - - default_params - { - } -} - -material depth_shadow_caster -{ - technique - { - pass - { - // force-disable fog (relevant for DirectX profiles below SM3 that always apply fixed function fog) - fog_override true - - vertex_program_ref depth_shadow_caster_vs - { - } - - fragment_program_ref depth_shadow_caster_ps - { - } - } - } -} - -material depth_shadow_caster_noalpha -{ - technique - { - pass - { - // force-disable fog (relevant for DirectX profiles below SM3 that always apply fixed function fog) - fog_override true - - vertex_program_ref depth_shadow_caster_vs - { - } - - fragment_program_ref depth_shadow_caster_ps_noalpha - { - } - } - } -} diff --git a/files/water/WaterNormal2.tga b/files/water/WaterNormal2.tga deleted file mode 100644 index 771d150419..0000000000 Binary files a/files/water/WaterNormal2.tga and /dev/null differ diff --git a/files/water/caustic_0.png b/files/water/caustic_0.png deleted file mode 100644 index fee464860e..0000000000 Binary files a/files/water/caustic_0.png and /dev/null differ diff --git a/files/water/perlinvolume.dds b/files/water/perlinvolume.dds deleted file mode 100644 index bd8147d49f..0000000000 Binary files a/files/water/perlinvolume.dds and /dev/null differ diff --git a/files/water/underwater.cg b/files/water/underwater.cg deleted file mode 100644 index 829d34347c..0000000000 --- a/files/water/underwater.cg +++ /dev/null @@ -1,61 +0,0 @@ -void main_vp -( - in float4 inPos : POSITION, - - out float4 pos : POSITION, - out float2 uv0 : TEXCOORD0, - out float4 noiseCoord : TEXCOORD1, - - uniform float4x4 worldViewProj, - uniform float timeVal, - uniform float scale -) -{ - // Use standardise transform, so work accord with render system specific (RS depth, requires texture flipping, etc) - pos = mul(worldViewProj, inPos); - - // The input positions adjusted by texel offsets, so clean up inaccuracies - inPos.xy = sign(inPos.xy); - - // Convert to image-space - uv0 = (float2(inPos.x, -inPos.y) + 1.0f) * 0.5f; - noiseCoord = (pos + timeVal) * scale; -} - - - -float4 main_fp_nomrt (float2 iTexCoord : TEXCOORD0, - float3 noiseCoord : TEXCOORD1, - uniform sampler2D RT : register(s0), - uniform sampler2D NormalMap : register(s1), - uniform sampler2D CausticMap : register(s2)) : COLOR -{ - float4 normal = tex2D(NormalMap, noiseCoord) * 2 - 1; - - float4 col = tex2D(RT, iTexCoord + normal.xy * 0.015) + - (tex2D(CausticMap, noiseCoord) / 5); - col.xyz = lerp(col.xyz, float3(0.15, 0.40, 0.40), 0.4); - return col; - -} - - -float4 main_fp (float2 iTexCoord : TEXCOORD0, - float3 noiseCoord : TEXCOORD1, - uniform float far, - uniform sampler2D RT : register(s0), - uniform sampler2D NormalMap : register(s1), - uniform sampler2D CausticMap : register(s2), - uniform sampler2D DepthMap : register(s3)) : COLOR -{ - float4 normal = tex2D(NormalMap, noiseCoord) * 2 - 1; - - float depth = tex2D(DepthMap, iTexCoord + normal.xy * 0.015).r * far; - depth = saturate(depth / 2000.f); - - float4 color = tex2D(RT, iTexCoord + normal.xy * 0.015) + - (tex2D(CausticMap, noiseCoord) / 5); - color.xyz = lerp(color.xyz, float3(0.15, 0.40, 0.40), 0.4); - - return lerp(color, float4(0.15, 0.40, 0.40, 1), depth); -} diff --git a/files/water/underwater_dome.mesh b/files/water/underwater_dome.mesh new file mode 100644 index 0000000000..64ca569c22 Binary files /dev/null and b/files/water/underwater_dome.mesh differ diff --git a/files/water/water.cg b/files/water/water.cg deleted file mode 100644 index ad0ff57f7e..0000000000 --- a/files/water/water.cg +++ /dev/null @@ -1,121 +0,0 @@ -void main_vp -( - in float4 iPos : POSITION - , in float2 iUv : TEXCOORD0 - - , out float4 oPos : POSITION - , out float3 oScreenCoords : TEXCOORD0 - , out float2 oUv : TEXCOORD1 - , out float oDepth : TEXCOORD2 - , out float4 oEyeVector : TEXCOORD3 - - , uniform float4x4 wvpMat - , uniform float4 camPosObjSpace -) -{ - oPos = mul(wvpMat, iPos); - - oUv = iUv * 10; // uv scale - oDepth = oPos.z; - - float4x4 scalemat = float4x4( 0.5, 0, 0, 0.5, - 0, -0.5, 0, 0.5, - 0, 0, 0.5, 0.5, - 0, 0, 0, 1 ); - float4 texcoordProj = mul(scalemat, oPos); - oScreenCoords = float3(texcoordProj.x, texcoordProj.y, texcoordProj.w); - - oEyeVector = camPosObjSpace - iPos; -} - -void main_fp -( - out float4 oColor : COLOR - - , in float3 iScreenCoords : TEXCOORD0 - , in float2 iUv : TEXCOORD1 - , in float iDepth : TEXCOORD2 - , in float4 iEyeVector : TEXCOORD3 - , uniform float renderTargetFlipping - , uniform float4 lightPosObjSpace0 - , uniform float4 lightSpecularColour0 - - , uniform sampler2D reflectionMap : register(s0) - , uniform sampler2D refractionMap : register(s1) - , uniform sampler2D depthMap : register(s2) - , uniform sampler2D normalMap : register(s3) - , uniform float time - , uniform float far - , uniform float4 fogParams - , uniform float4 fogColour - , uniform float isUnderwater -) -{ - - float2 screenCoords = iScreenCoords.xy / iScreenCoords.z; - screenCoords.y = (1-saturate(renderTargetFlipping))+renderTargetFlipping*screenCoords.y; - - // No need for transparency since we are using a refraction map - oColor.a = 1; - - // Sample screen-space depth map and subtract pixel depth to get the real water depth - float depthTex = tex2D(depthMap, screenCoords).r; - float depth1 = depthTex * far - iDepth; - depth1 = saturate(depth1 / 500.f); - - // Simple wave effect. to be replaced by something better - float2 uv1 = iUv + time * float2(0.5, 0); - float2 uv2 = iUv + time * float2(0, 0.5); - float2 uv3 = iUv + time * float2(-0.5, 0); - float2 uv4 = iUv + time * float2(0, -0.5); - float4 normal = tex2D(normalMap, uv1) + tex2D(normalMap, uv2) + tex2D(normalMap, uv3) + tex2D(normalMap, uv4); - normal = normal / 4.f; - normal = 2*normal - 1; - - float2 screenCoords_reflect = screenCoords + normal.yx * 0.05; - float2 screenCoords_refract = screenCoords + normal.yx * 0.05 * depth1; - - // Sample depth again with the refracted coordinates - depthTex = tex2D(depthMap, screenCoords_refract).r; - float depth2 = (depthTex * far - iDepth) / 500.f; - depth2 = (depthTex == 0 ? 1 : depth2); - // if depth2 is less than 0, this means we would refract something which is above water, - // which we don't want to - so in that case, don't refract - if (depth2 < 0.25) // delta due to inaccuracies - { - screenCoords_refract = screenCoords; - depth2 = depth1; - } - depth2 = saturate(depth2); - - float4 reflection = tex2D(reflectionMap, screenCoords_reflect); - float4 refraction = tex2D(refractionMap, screenCoords_refract); - - // tangent to object space - normal.xyz = normal.xzy; - - iEyeVector.xyz = normalize(iEyeVector.xyz); - - // fresnel - float facing = 1.0 - max(abs(dot(iEyeVector.xyz, normal.xyz)), 0); - float reflectionFactor = saturate(0.35 + 0.65 * pow(facing, 2)); - - // specular - float3 lightDir = normalize(lightPosObjSpace0.xyz); // assumes that light 0 is a directional light - float3 halfVector = normalize(iEyeVector + lightDir); - float specular = pow(max(dot(normal.xyz, halfVector.xyz), 0), 64); - - float opacity = depth2 * saturate(reflectionFactor + specular); - opacity *= (1-isUnderwater); - - reflection.xyz += lightSpecularColour0.xyz * specular; - - oColor.xyz = lerp(refraction.xyz, reflection.xyz, opacity); - - oColor.xyz = lerp(oColor.xyz, float3(0.15, 0.40, 0.40), isUnderwater*0.6); // underwater tint color - oColor.xyz = lerp(oColor.xyz, float3(0.15, 0.40, 0.40), saturate(isUnderwater * (iDepth / 2000.f))); // underwater fog - - // add fog - //float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); - //oColor.xyz = lerp(oColor.xyz, fogColour, fogValue); -} diff --git a/files/water/water.compositor b/files/water/water.compositor deleted file mode 100644 index 8d9c3cb396..0000000000 --- a/files/water/water.compositor +++ /dev/null @@ -1,46 +0,0 @@ -compositor UnderwaterNoMRT -{ - technique - { - texture rt0 target_width target_height PF_R8G8B8 - - target rt0 { input previous } - - target_output - { - // Start with clear output - input none - - pass render_quad - { - material Water/CompositorNoMRT - input 0 rt0 - } - } - } -} - - -compositor Underwater -{ - technique - { - texture_ref scene gbuffer mrt_output - texture rt0 target_width target_height PF_R8G8B8 - - target rt0 { input previous } - - target_output - { - // Start with clear output - input none - - pass render_quad - { - material Water/Compositor - input 0 rt0 - input 3 scene 1 - } - } - } -} diff --git a/files/water/water.material b/files/water/water.material deleted file mode 100644 index d1f7fcf494..0000000000 --- a/files/water/water.material +++ /dev/null @@ -1,221 +0,0 @@ -vertex_program UnderwaterEffectVP cg -{ - source underwater.cg - entry_point main_vp - profiles vs_1_1 arbvp1 - - default_params - { - param_named_auto worldViewProj worldviewproj_matrix - } -} - - -fragment_program UnderwaterEffectFP_NoMRT cg -{ - source underwater.cg - entry_point main_fp_nomrt - profiles ps_2_0 arbfp1 -} - -fragment_program UnderwaterEffectFP cg -{ - source underwater.cg - entry_point main_fp - profiles ps_2_0 arbfp1 -} - -vertex_program Water_VP cg -{ - source water.cg - entry_point main_vp - profiles vs_2_x arbvp1 - - default_params - { - param_named_auto wvpMat worldviewproj_matrix - } -} - -fragment_program Water_FP cg -{ - source water.cg - entry_point main_fp - profiles ps_2_x arbfp1 -} - -material Water -{ - technique - { - pass - { - cull_hardware none - - vertex_program_ref Water_VP - { - param_named_auto camPosObjSpace camera_position_object_space - } - fragment_program_ref Water_FP - { - param_named_auto time time 0.1 - //param_named_auto fogColour fog_colour - //param_named_auto fogParams fog_params - param_named_auto renderTargetFlipping render_target_flipping - param_named_auto far far_clip_distance - param_named_auto lightPosObjSpace0 light_position_object_space 0 - param_named_auto lightSpecularColour0 light_specular_colour 0 - param_named isUnderwater float 0 - } - - texture_unit reflectionMap - { - texture WaterReflection - tex_address_mode clamp - } - - texture_unit refractionMap - { - tex_address_mode clamp - } - - texture_unit depthMap - { - tex_address_mode clamp - } - - texture_unit normalMap - { - texture WaterNormal2.tga - } - } - } - - technique - { - scheme Fallback - pass - { - cull_hardware none - scene_blend alpha_blend - depth_write off - diffuse 0 0 0 1 - emissive 0.6 0.7 1.0 - ambient 0 0 0 - texture_unit - { - // texture names set via code - scale 0.1 0.1 - alpha_op_ex source1 src_manual src_current 0.7 - } - } - } - -} - -material Water_Fallback -{ - technique - { - scheme Fallback - pass - { - cull_hardware none - scene_blend alpha_blend - depth_write off - diffuse 0 0 0 1 - emissive 0.6 0.7 1.0 - ambient 0 0 0 - texture_unit - { - // texture names set via code - scale 0.1 0.1 - alpha_op_ex source1 src_manual src_current 0.7 - } - } - } -} - -material Water/CompositorNoMRT -{ - technique - { - pass - { - depth_check off - vertex_program_ref UnderwaterEffectVP - { - param_named_auto timeVal time 0.25 - param_named scale float 0.1 - } - - fragment_program_ref UnderwaterEffectFP_NoMRT - { - } - - texture_unit RT - { - tex_coord_set 0 - tex_address_mode clamp - filtering linear linear linear - } - - texture_unit - { - texture WaterNormal2.tga 2d - tex_coord_set 1 - //tex_address_mode clamp - filtering linear linear linear - } - texture_unit - { - texture caustic_0.png 2d - tex_coord_set 2 - //tex_address_mode clamp - filtering linear linear linear - } - } - } -} - -material Water/Compositor -{ - technique - { - pass - { - depth_check off - vertex_program_ref UnderwaterEffectVP - { - param_named_auto timeVal time 0.25 - param_named scale float 0.1 - } - - fragment_program_ref UnderwaterEffectFP - { - param_named_auto far far_clip_distance - } - - texture_unit RT - { - tex_coord_set 0 - tex_address_mode clamp - } - - texture_unit - { - texture WaterNormal2.tga 2d - tex_coord_set 2 - } - texture_unit - { - texture caustic_0.png 2d - tex_coord_set 3 - } - - texture_unit DepthMap - { - } - } - } -} diff --git a/files/water/water_nm.png b/files/water/water_nm.png new file mode 100644 index 0000000000..361431a0ef Binary files /dev/null and b/files/water/water_nm.png differ diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index f2f4b4c81e..e40bdf708a 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -9,7 +9,10 @@ #include "OgreTexture.h" #include "OgreHardwarePixelBuffer.h" +#include + #include +#include #include using namespace Ogre; @@ -70,7 +73,6 @@ float OgreRenderer::getFPS() } void OgreRenderer::configure(const std::string &logPath, - const std::string &pluginCfg, const std::string& renderSystem, bool _logging) { @@ -86,13 +88,41 @@ void OgreRenderer::configure(const std::string &logPath, // Disable logging log->setDebugOutputEnabled(false); - #if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) || defined(ENABLE_PLUGIN_CgProgramManager) || defined(ENABLE_PLUGIN_OctreeSceneManager) || defined(ENABLE_PLUGIN_ParticleFX) mRoot = new Root("", "", ""); + + #if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) || defined(ENABLE_PLUGIN_CgProgramManager) || defined(ENABLE_PLUGIN_OctreeSceneManager) || defined(ENABLE_PLUGIN_ParticleFX) loadPlugins(); - #else - mRoot = new Root(pluginCfg, "", ""); #endif + std::string pluginDir; + const char* pluginEnv = getenv("OPENMW_OGRE_PLUGIN_DIR"); + if (pluginEnv) + pluginDir = pluginEnv; + else + { +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + pluginDir = ".\\"; +#endif +#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE + pluginDir = OGRE_PLUGIN_DIR; +#endif +#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX + pluginDir = OGRE_PLUGIN_DIR_REL; +#endif + } + + std::string glPlugin = std::string(pluginDir) + "/RenderSystem_GL" + OGRE_PLUGIN_DEBUG_SUFFIX; + if (boost::filesystem::exists(glPlugin + ".so") || boost::filesystem::exists(glPlugin + ".dll")) + mRoot->loadPlugin (glPlugin); + + std::string dxPlugin = std::string(pluginDir) + "/RenderSystem_Direct3D9" + OGRE_PLUGIN_DEBUG_SUFFIX; + if (boost::filesystem::exists(dxPlugin + ".so") || boost::filesystem::exists(dxPlugin + ".dll")) + mRoot->loadPlugin (dxPlugin); + + std::string cgPlugin = std::string(pluginDir) + "/Plugin_CgProgramManager" + OGRE_PLUGIN_DEBUG_SUFFIX; + if (boost::filesystem::exists(cgPlugin + ".so") || boost::filesystem::exists(cgPlugin + ".dll")) + mRoot->loadPlugin (cgPlugin); + RenderSystem* rs = mRoot->getRenderSystemByName(renderSystem); if (rs == 0) throw std::runtime_error ("RenderSystem with name " + renderSystem + " not found, make sure the plugins are loaded"); diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index c7c30c8d4f..247c8f95a2 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -110,7 +110,6 @@ namespace OEngine set up the Root and logging classes. */ void configure( const std::string &logPath, // Path to directory where to store log files - const std::string &pluginCfg, // plugin.cfg file const std::string &renderSystem, bool _logging); // Enable or disable logging