1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-21 10:53:51 +00:00
This commit is contained in:
greye 2012-07-23 20:44:03 +04:00
commit a62c684222
87 changed files with 3391 additions and 3922 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "extern/shiny"]
path = extern/shiny
url = git@github.com:scrawl/shiny.git

View file

@ -20,14 +20,6 @@ set (OPENMW_VERSION_RELEASE 0)
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") 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 # doxygen main page
configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp") configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp")
@ -194,14 +186,21 @@ if (UNIX AND NOT APPLE)
find_package (Threads) find_package (Threads)
endif() 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)
endif()
find_package(OGRE REQUIRED) find_package(OGRE REQUIRED)
find_package(MyGUI 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(OIS REQUIRED)
find_package(OpenAL REQUIRED) find_package(OpenAL REQUIRED)
find_package(Bullet REQUIRED) find_package(Bullet REQUIRED)
IF(OGRE_STATIC) IF(OGRE_STATIC)
find_package(Cg REQUIRED) find_package(Cg)
IF(WIN32) 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}) 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) ELSE(WIN32)
@ -230,6 +229,22 @@ if (APPLE)
${OGRE_Plugin_ParticleFX_LIBRARY_REL}) ${OGRE_Plugin_ParticleFX_LIBRARY_REL})
endif (APPLE) 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/)
add_subdirectory(files/mygui) add_subdirectory(files/mygui)
@ -254,15 +269,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
"${OpenMW_BINARY_DIR}/openmw.cfg.install") "${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") 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 configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
"${OpenMW_BINARY_DIR}/openmw.desktop") "${OpenMW_BINARY_DIR}/openmw.desktop")
endif() endif()
@ -284,13 +292,8 @@ if (APPLE)
set(OGRE_PLUGIN_DIR "${OGRE_PLUGIN_DIR}/") 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_2 ${OGRE_PLUGIN_DIR})
set(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}) set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_2})
configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist
@ -337,7 +340,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}/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}/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}/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 resources
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "share/games/openmw/" FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT "Resources") INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "share/games/openmw/" FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT "Resources")
@ -354,7 +356,7 @@ if(DPKG_PROGRAM)
SET(CPACK_DEBIAN_PACKAGE_NAME "openmw") SET(CPACK_DEBIAN_PACKAGE_NAME "openmw")
SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}") SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}")
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher mwiniimporter;MWiniImporter") 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") SET(CPACK_DEBIAN_PACKAGE_SECTION "Games")
@ -375,7 +377,6 @@ if(WIN32)
INSTALL(FILES ${dll_files} DESTINATION ".") INSTALL(FILES ${dll_files} DESTINATION ".")
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg")
INSTALL(FILES INSTALL(FILES
"${OpenMW_BINARY_DIR}/plugins.cfg"
"${OpenMW_SOURCE_DIR}/readme.txt" "${OpenMW_SOURCE_DIR}/readme.txt"
"${OpenMW_SOURCE_DIR}/GPL3.txt" "${OpenMW_SOURCE_DIR}/GPL3.txt"
"${OpenMW_SOURCE_DIR}/OFL.txt" "${OpenMW_SOURCE_DIR}/OFL.txt"
@ -439,6 +440,9 @@ if(WIN32)
include(CPack) include(CPack)
endif(WIN32) endif(WIN32)
# Extern
add_subdirectory (extern/shiny)
# Components # Components
add_subdirectory (components) add_subdirectory (components)
@ -544,7 +548,6 @@ if (APPLE)
install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) 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(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}/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}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)

View file

@ -1,6 +1,9 @@
#include <QtGui> #include <QtGui>
#include <cstdlib>
#include <boost/math/common_factor.hpp> #include <boost/math/common_factor.hpp>
#include <boost/filesystem.hpp>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
@ -70,20 +73,13 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent)
bool GraphicsPage::setupOgre() 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 // Create a log manager so we can surpress debug text to stdout/stderr
Ogre::LogManager* logMgr = OGRE_NEW Ogre::LogManager; Ogre::LogManager* logMgr = OGRE_NEW Ogre::LogManager;
logMgr->createLog((mCfgMgr.getLogPath().string() + "/launcherOgre.log"), true, false, false); logMgr->createLog((mCfgMgr.getLogPath().string() + "/launcherOgre.log"), true, false, false);
try try
{ {
#if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9)
mOgre = new Ogre::Root("", "", "./launcherOgre.log"); mOgre = new Ogre::Root("", "", "./launcherOgre.log");
#else
mOgre = new Ogre::Root(pluginCfg.toStdString(), "", "./launcherOgre.log");
#endif
} }
catch(Ogre::Exception &ex) catch(Ogre::Exception &ex)
{ {
@ -93,7 +89,6 @@ bool GraphicsPage::setupOgre()
msgBox.setIcon(QMessageBox::Critical); msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(tr("<br><b>Failed to create the Ogre::Root object</b><br><br> \ msgBox.setText(tr("<br><b>Failed to create the Ogre::Root object</b><br><br> \
Make sure the plugins.cfg is present and valid.<br><br> \
Press \"Show Details...\" for more information.<br>")); Press \"Show Details...\" for more information.<br>"));
msgBox.setDetailedText(ogreError); msgBox.setDetailedText(ogreError);
msgBox.exec(); msgBox.exec();
@ -102,6 +97,32 @@ bool GraphicsPage::setupOgre()
return false; 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 #ifdef ENABLE_PLUGIN_GL
mGLPlugin = new Ogre::GLPlugin(); mGLPlugin = new Ogre::GLPlugin();
mOgre->installPlugin(mGLPlugin); mOgre->installPlugin(mGLPlugin);

View file

@ -15,7 +15,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender add_openmw_dir (mwrender
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects 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 compositors
) )
@ -100,6 +100,8 @@ target_link_libraries(openmw
${BULLET_LIBRARIES} ${BULLET_LIBRARIES}
${MYGUI_LIBRARIES} ${MYGUI_LIBRARIES}
${MYGUI_PLATFORM_LIBRARIES} ${MYGUI_PLATFORM_LIBRARIES}
"shiny"
"shiny.OgrePlatform"
components components
) )

View file

@ -292,7 +292,6 @@ void OMW::Engine::go()
} }
mOgre->configure( mOgre->configure(
mCfgMgr.getLogPath().string(), mCfgMgr.getLogPath().string(),
mCfgMgr.getPluginsConfigPath().string(),
renderSystem, renderSystem,
false); false);

View file

@ -74,6 +74,14 @@ namespace
return "16 : 10"; return "16 : 10";
return boost::lexical_cast<std::string>(xaspect) + " : " + boost::lexical_cast<std::string>(yaspect); return boost::lexical_cast<std::string>(xaspect) + " : " + boost::lexical_cast<std::string>(yaspect);
} }
std::string hlslGlsl ()
{
if (Ogre::Root::getSingleton ().getRenderSystem ()->getName ().find("OpenGL") == std::string::npos)
return "hlsl";
else
return "glsl";
}
} }
namespace MWGui namespace MWGui
@ -103,8 +111,19 @@ namespace MWGui
getWidget(mReflectObjectsButton, "ReflectObjectsButton"); getWidget(mReflectObjectsButton, "ReflectObjectsButton");
getWidget(mReflectActorsButton, "ReflectActorsButton"); getWidget(mReflectActorsButton, "ReflectActorsButton");
getWidget(mReflectTerrainButton, "ReflectTerrainButton"); 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); 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); mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mWaterShaderButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mWaterShaderButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mReflectObjectsButton->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); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected);
mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); 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); mMasterVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mVoiceVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mVoiceVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mEffectsVolumeSlider->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"); std::string tf = Settings::Manager::getString("texture filtering", "General");
mTextureFilteringButton->setCaption(textureFilteringToStr(tf)); mTextureFilteringButton->setCaption(textureFilteringToStr(tf));
mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(Settings::Manager::getInt("anisotropy", "General")) + ")"); mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(Settings::Manager::getInt("anisotropy", "General")) + ")");
mAnisotropyBox->setVisible(tf == "anisotropic");
float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-sViewDistMin)/(sViewDistMax-sViewDistMin); float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-sViewDistMin)/(sViewDistMax-sViewDistMin);
int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val; int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val;
@ -185,9 +211,27 @@ namespace MWGui
mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1)); mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1));
mWaterShaderButton->setCaptionWithReplacing(Settings::Manager::getBool("shader", "Water") ? "#{sOn}" : "#{sOff}"); 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}"); mReflectActorsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect actors", "Water") ? "#{sOn}" : "#{sOff}");
mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "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()) if (!MWRender::RenderingManager::waterShaderSupported())
{ {
@ -237,6 +281,25 @@ namespace MWGui
mResolutionList->setIndexSelected(MyGUI::ITEM_NONE); 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) void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender)
{ {
std::string on = mWindowManager.getGameSettingString("sOn", "On"); std::string on = mWindowManager.getGameSettingString("sOn", "On");
@ -291,6 +354,10 @@ namespace MWGui
{ {
if (_sender == mWaterShaderButton) if (_sender == mWaterShaderButton)
Settings::Manager::setBool("shader", "Water", newState); Settings::Manager::setBool("shader", "Water", newState);
else if (_sender == mUnderwaterButton)
{
Settings::Manager::setBool("underwater effect", "Water", newState);
}
else if (_sender == mReflectObjectsButton) else if (_sender == mReflectObjectsButton)
{ {
Settings::Manager::setBool("reflect misc", "Water", newState); Settings::Manager::setBool("reflect misc", "Water", newState);
@ -301,11 +368,68 @@ namespace MWGui
Settings::Manager::setBool("reflect actors", "Water", newState); Settings::Manager::setBool("reflect actors", "Water", newState);
else if (_sender == mReflectTerrainButton) else if (_sender == mReflectTerrainButton)
Settings::Manager::setBool("reflect terrain", "Water", newState); 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(); apply();
} }
} }
void SettingsWindow::onShadersToggled(MyGUI::Widget* _sender)
{
std::string val = static_cast<MyGUI::Button*>(_sender)->getCaption();
if (val == "off")
val = hlslGlsl();
else if (val == hlslGlsl())
val = "cg";
else
val = "off";
static_cast<MyGUI::Button*>(_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) void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender)
{ {
int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 3; int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 3;
@ -328,7 +452,6 @@ namespace MWGui
next = "none"; next = "none";
mTextureFilteringButton->setCaption(textureFilteringToStr(next)); mTextureFilteringButton->setCaption(textureFilteringToStr(next));
mAnisotropyBox->setVisible(next == "anisotropic");
Settings::Manager::setString("texture filtering", "General", next); Settings::Manager::setString("texture filtering", "General", next);
apply(); apply();

View file

@ -42,6 +42,16 @@ namespace MWGui
MyGUI::Button* mReflectObjectsButton; MyGUI::Button* mReflectObjectsButton;
MyGUI::Button* mReflectActorsButton; MyGUI::Button* mReflectActorsButton;
MyGUI::Button* mReflectTerrainButton; 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 // audio
MyGUI::ScrollBar* mMasterVolumeSlider; MyGUI::ScrollBar* mMasterVolumeSlider;
@ -59,6 +69,9 @@ namespace MWGui
void onResolutionAccept(); void onResolutionAccept();
void onResolutionCancel(); void onResolutionCancel();
void onShadersToggled(MyGUI::Widget* _sender);
void onShadowTextureSize(MyGUI::Widget* _sender);
void apply(); void apply();
}; };
} }

View file

@ -229,7 +229,7 @@ void LocalMap::render(const float x, const float y,
vp->setVisibilityMask(RV_Map); vp->setVisibilityMask(RV_Map);
// use fallback techniques without shadows and without mrt // use fallback techniques without shadows and without mrt
vp->setMaterialScheme("Fallback"); vp->setMaterialScheme("local_map");
rtt->update(); rtt->update();

View file

@ -450,3 +450,18 @@ void Objects::update(const float dt)
it = mLights.erase(it); it = mLights.erase(it);
} }
} }
void Objects::rebuildStaticGeometry()
{
for (std::map<MWWorld::CellStore *, Ogre::StaticGeometry*>::iterator it = mStaticGeometry.begin(); it != mStaticGeometry.end(); ++it)
{
it->second->destroy();
it->second->build();
}
for (std::map<MWWorld::CellStore *, Ogre::StaticGeometry*>::iterator it = mStaticGeometrySmall.begin(); it != mStaticGeometrySmall.end(); ++it)
{
it->second->destroy();
it->second->build();
}
}

View file

@ -93,6 +93,8 @@ public:
void removeCell(MWWorld::CellStore* store); void removeCell(MWWorld::CellStore* store);
void buildStaticGeometry(MWWorld::CellStore &cell); void buildStaticGeometry(MWWorld::CellStore &cell);
void setMwRoot(Ogre::SceneNode* root); void setMwRoot(Ogre::SceneNode* root);
void rebuildStaticGeometry();
}; };
} }
#endif #endif

View file

@ -14,14 +14,14 @@ enum RenderQueueGroups
RQG_Main = Ogre::RENDER_QUEUE_MAIN, 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_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) // Sky late (sun & sun flare)
RQG_SkiesLate = Ogre::RENDER_QUEUE_SKIES_LATE RQG_SkiesLate = Ogre::RENDER_QUEUE_SKIES_LATE
}; };
@ -49,12 +49,12 @@ enum VisibilityFlags
RV_Sky = 64, RV_Sky = 64,
// Sun glare (not visible in reflection) // not visible in reflection
RV_Glare = 128, RV_NoReflection = 128,
RV_OcclusionQuery = 256, 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) /// \todo markers (normally hidden)
}; };

View file

@ -14,6 +14,9 @@
#include <OgreCompositionPass.h> #include <OgreCompositionPass.h>
#include <OgreHardwarePixelBuffer.h> #include <OgreHardwarePixelBuffer.h>
#include <extern/shiny/Main/Factory.hpp>
#include <extern/shiny/Platforms/Ogre/OgrePlatform.hpp>
#include <components/esm/loadstat.hpp> #include <components/esm/loadstat.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
@ -27,7 +30,6 @@
#include "../mwinput/inputmanager.hpp" // FIXME #include "../mwinput/inputmanager.hpp" // FIXME
#include "shadows.hpp" #include "shadows.hpp"
#include "shaderhelper.hpp"
#include "localmap.hpp" #include "localmap.hpp"
#include "water.hpp" #include "water.hpp"
#include "compositors.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) 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) :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.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5);
mRendering.setWindowEventListener(this); mRendering.setWindowEventListener(this);
@ -47,6 +58,21 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
mWater = 0; 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 //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 //fog type is set to FOG_NONE then the initially created terrain won't have any fog
configureFog(1, ColourValue(1,1,1)); configureFog(1, ColourValue(1,1,1));
@ -68,18 +94,26 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
// Load resources // Load resources
ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
// Due to the huge world size of MW, we'll want camera-relative rendering. // causes light flicker in opengl when moving..
// This prevents precision artifacts when moving very far from the origin. //mRendering.getScene()->setCameraRelativeRendering(true);
mRendering.getScene()->setCameraRelativeRendering(true);
// disable unsupported effects // disable unsupported effects
const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); //const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
if (!waterShaderSupported()) if (!waterShaderSupported())
Settings::Manager::setBool("shader", "Water", false); Settings::Manager::setBool("shader", "Water", false);
if ( !(caps->isShaderProfileSupported("fp40") || caps->isShaderProfileSupported("ps_4_0")) if (!Settings::Manager::getBool("shaders", "Objects"))
|| !Settings::Manager::getBool("shaders", "Objects"))
Settings::Manager::setBool("enabled", "Shadows", false); 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<sh::Vector3> (new sh::Vector3(0,0,0)));
sh::Factory::getInstance ().setSharedParameter ("waterEnabled", sh::makeProperty<sh::FloatValue> (new sh::FloatValue(0.0)));
applyCompositors(); applyCompositors();
// Turn the entire scene (represented by the 'root' node) -90 // 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()); cameraPitchNode->attachObject(mRendering.getCamera());
mShadows = new Shadows(&mRendering); mShadows = new Shadows(&mRendering);
mShaderHelper = new ShaderHelper(this);
mTerrainManager = new TerrainManager(mRendering.getScene(), this); mTerrainManager = new TerrainManager(mRendering.getScene(), this);
@ -124,7 +157,6 @@ RenderingManager::~RenderingManager ()
delete mPlayer; delete mPlayer;
delete mSkyManager; delete mSkyManager;
delete mDebugging; delete mDebugging;
delete mShaderHelper;
delete mShadows; delete mShadows;
delete mTerrainManager; delete mTerrainManager;
delete mLocalMap; delete mLocalMap;
@ -237,7 +269,7 @@ void RenderingManager::update (float duration){
checkUnderwater(); checkUnderwater();
mWater->update(); mWater->update(duration);
} }
void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){ void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){
if(store->cell->data.flags & store->cell->HasWater if(store->cell->data.flags & store->cell->HasWater
@ -336,6 +368,9 @@ void RenderingManager::configureFog(MWWorld::Ptr::CellStore &mCell)
color.setAsABGR (mCell.cell->ambi.fog); color.setAsABGR (mCell.cell->ambi.fog);
configureFog(mCell.cell->ambi.fogDensity, color); configureFog(mCell.cell->ambi.fogDensity, color);
if (mWater)
mWater->setViewportBackground (Ogre::ColourValue(0.8f, 0.9f, 1.0f));
} }
void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour) void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour)
@ -350,11 +385,12 @@ void RenderingManager::configureFog(const float density, const Ogre::ColourValue
mRendering.getCamera()->setFarClipDistance ( max / density ); mRendering.getCamera()->setFarClipDistance ( max / density );
mRendering.getViewport()->setBackgroundColour (colour); 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) if (mWater)
mWater->setViewportBackground(colour); mWater->setViewportBackground (colour);
sh::Factory::getInstance ().setSharedParameter ("viewportBackground",
sh::makeProperty<sh::Vector3> (new sh::Vector3(colour.r, colour.g, colour.b)));
} }
@ -517,12 +553,14 @@ Shadows* RenderingManager::getShadows()
void RenderingManager::switchToInterior() void RenderingManager::switchToInterior()
{ {
mRendering.getScene()->setCameraRelativeRendering(false); // causes light flicker in opengl when moving..
//mRendering.getScene()->setCameraRelativeRendering(false);
} }
void RenderingManager::switchToExterior() 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) Ogre::Vector4 RenderingManager::boundingBoxToScreen(Ogre::AxisAlignedBox bounds)
@ -607,7 +645,38 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
else if (it->second == "shader" && it->first == "Water") else if (it->second == "shader" && it->first == "Water")
{ {
applyCompositors(); 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 +740,9 @@ void RenderingManager::applyCompositors()
{ {
mCompositors->addCompositor("gbuffer", 0); mCompositors->addCompositor("gbuffer", 0);
mCompositors->setCompositorEnabled("gbuffer", true); mCompositors->setCompositorEnabled("gbuffer", true);
mCompositors->addCompositor("Underwater", 1);
mCompositors->addCompositor("gbufferFinalizer", 2); mCompositors->addCompositor("gbufferFinalizer", 2);
mCompositors->setCompositorEnabled("gbufferFinalizer", true); mCompositors->setCompositorEnabled("gbufferFinalizer", true);
} }
else
{
mCompositors->addCompositor("UnderwaterNoMRT", 0);
}
if (mWater) if (mWater)
mWater->assignTextures(); mWater->assignTextures();

View file

@ -32,10 +32,14 @@ namespace MWWorld
class CellStore; class CellStore;
} }
namespace sh
{
class Factory;
}
namespace MWRender namespace MWRender
{ {
class Shadows; class Shadows;
class ShaderHelper;
class LocalMap; class LocalMap;
class Water; class Water;
class Compositors; class Compositors;
@ -162,6 +166,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList
private: private:
sh::Factory* mFactory;
void setAmbientMode(); void setAmbientMode();
void setMenuTransparency(float val); void setMenuTransparency(float val);
@ -204,8 +210,6 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList
MWRender::Shadows* mShadows; MWRender::Shadows* mShadows;
MWRender::ShaderHelper* mShaderHelper;
MWRender::Compositors* mCompositors; MWRender::Compositors* mCompositors;
}; };

View file

@ -1,309 +0,0 @@
#include "shaderhelper.hpp"
#include "renderingmanager.hpp"
#include "shadows.hpp"
#include <OgreHighLevelGpuProgramManager.h>
#include <OgreHighLevelGpuProgram.h>
#include <OgreGpuProgramParams.h>
#include <OgreShadowCameraSetupPSSM.h>
#include <components/settings/settings.hpp>
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; i<numsplits; ++i)
{
outStream <<
" out float4 oLightSpacePos"<<i<<" : TEXCOORD"<<i+5<<", \n"
" uniform float4x4 texViewProjMatrix"<<i<<", \n";
}
outStream <<
" uniform float4x4 worldMatrix, \n";
}
outStream <<
" uniform float4x4 worldViewProj \n"
") \n"
"{ \n"
" oVertexColour = colour; \n"
" oUV = uv; \n"
" oNormal = normal; \n"
" oPosition = mul( worldViewProj, position ); \n"
" oDepth = oPosition.z; \n"
" oPositionObjSpace = position; \n";
if (shadows && !split) outStream <<
" oLightSpacePos0 = mul(texViewProjMatrix0, mul(worldMatrix, position)); \n";
else
{
outStream <<
" float4 wPos = mul(worldMatrix, position); \n";
for (int i=0; i<numsplits; ++i)
{
outStream <<
" oLightSpacePos"<<i<<" = mul(texViewProjMatrix"<<i<<", wPos); \n";
}
}
outStream <<
"}";
vertex->setSource(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; i<numsplits; ++i)
{
vertex->getDefaultParameters()->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<numsplits; ++i)
{
outStream <<
" uniform sampler2D shadowMap"<<i<<" : register(s"<<i+1<<"), \n"
" float4 lightSpacePos"<<i<<" : TEXCOORD"<<i+5<<", \n"
" uniform float4 invShadowmapSize"<<i<<", \n";
}
}
if (mrt) outStream <<
" out float4 oColor1 : COLOR1, \n"
" uniform float far, \n";
for (int i=0; i<num_lights; ++i)
{
outStream <<
" uniform float4 lightDiffuse"<<i<<", \n"
" uniform float4 lightPositionObjSpace"<<i<<", \n"
" uniform float4 lightAttenuation"<<i<<", \n";
}
outStream <<
" uniform float4 lightAmbient, \n"
" uniform float4 ambient, \n"
" uniform float4 diffuse, \n"
" uniform float4 emissive \n"
") \n"
"{ \n"
" float4 tex = tex2D(texture, uv); \n"
" float d; \n"
" float attn; \n"
" float3 lightDir; \n"
" float3 lightColour = float3(0, 0, 0); \n";
for (int i=0; i<num_lights; ++i)
{
outStream <<
" lightDir = lightPositionObjSpace"<<i<<".xyz - (positionObjSpace.xyz * lightPositionObjSpace"<<i<<".w); \n"
// pre-multiply light color with attenuation factor
" d = length( lightDir ); \n"
" attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n"
" lightDiffuse"<<i<<" *= attn; \n";
if (i == 0 && shadows)
{
outStream <<
" float shadow; \n";
if (!split) outStream <<
" shadow = depthShadow(shadowMap, lightSpacePos0, invShadowmapSize0.xy); \n";
else
{
for (int j=0; j<numsplits; ++j)
{
std::string channel;
if (j==0) channel = "x";
else if (j==1) channel = "y";
else if (j==2) channel = "z";
if (j==0)
outStream << " if (iDepth <= pssmSplitPoints." << channel << ") \n";
else if (j < numsplits - 1)
outStream << " else if (iDepth <= pssmSplitPoints." << channel << ") \n";
else
outStream << " else \n";
outStream <<
" { \n"
" shadow = depthShadow(shadowMap" << j << ", lightSpacePos" << j << ", invShadowmapSize" << j << ".xy); \n"
" } \n";
}
}
outStream <<
" float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; \n"
" float fade = 1-((iDepth - shadowFar_fadeStart.y) / fadeRange); \n"
" shadow = (iDepth > 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"<<i<<".xyz;\n";
}
else outStream <<
" lightColour.xyz += lit(dot(normalize(lightDir), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
}
outStream <<
" float3 lightingFinal = lightColour.xyz * diffuse.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
" float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); \n"
" oColor.xyz = saturate(lerp(lightingFinal * tex.xyz * vertexColour.xyz, fogColour.xyz, fogValue)); \n" // saturate output to prevent negative output colors - TODO: replace this once there is HDR-rendering
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n";
if (mrt) outStream <<
" oColor1 = float4(iDepth / far, 0, 0, (oColor.a == 1)); \n"; // only write to MRT if alpha is 1
outStream <<
"}";
fragment->setSource(outStream.str());
fragment->load();
for (int i=0; i<num_lights; ++i)
{
fragment->getDefaultParameters()->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);
}
}

View file

@ -1,29 +0,0 @@
#ifndef GAME_SHADERHELPER_H
#define GAME_SHADERHELPER_H
#include <string>
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

View file

@ -12,6 +12,8 @@
#include <OgreOverlayContainer.h> #include <OgreOverlayContainer.h>
#include <OgreOverlayManager.h> #include <OgreOverlayManager.h>
#include <extern/shiny/Main/Factory.hpp>
#include "renderconst.hpp" #include "renderconst.hpp"
using namespace Ogre; using namespace Ogre;
@ -34,6 +36,9 @@ void Shadows::recreate()
bool split = Settings::Manager::getBool("split", "Shadows"); bool split = Settings::Manager::getBool("split", "Shadows");
//const bool split = false; //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) if (!enabled)
{ {
mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE); mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
@ -53,7 +58,7 @@ void Shadows::recreate()
mSceneMgr->setShadowTextureSelfShadow(true); mSceneMgr->setShadowTextureSelfShadow(true);
mSceneMgr->setShadowCasterRenderBackFaces(true); mSceneMgr->setShadowCasterRenderBackFaces(true);
mSceneMgr->setShadowTextureCasterMaterial("depth_shadow_caster"); mSceneMgr->setShadowTextureCasterMaterial("openmw_shadowcaster_default");
mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R); mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R);
mSceneMgr->setShadowDirectionalLightExtrusionDistance(1000000); mSceneMgr->setShadowDirectionalLightExtrusionDistance(1000000);
@ -84,18 +89,27 @@ void Shadows::recreate()
mSceneMgr->setShadowTextureConfig(i, texsize/4, texsize/4, Ogre::PF_FLOAT32_R);*/ 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<sh::Vector3>(splitPoints));
shadowCameraSetup = ShadowCameraSetupPtr(mPSSMSetup); shadowCameraSetup = ShadowCameraSetupPtr(mPSSMSetup);
} }
else else
{ {
LiSPSMShadowCameraSetup* lispsmSetup = new LiSPSMShadowCameraSetup(); LiSPSMShadowCameraSetup* lispsmSetup = new LiSPSMShadowCameraSetup();
lispsmSetup->setOptimalAdjustFactor(2); lispsmSetup->setOptimalAdjustFactor(64);
//lispsmSetup->setCameraLightDirectionThreshold(Degree(0)); //lispsmSetup->setCameraLightDirectionThreshold(Degree(0));
//lispsmSetup->setUseAggressiveFocusRegion(false); //lispsmSetup->setUseAggressiveFocusRegion(false);
shadowCameraSetup = ShadowCameraSetupPtr(lispsmSetup); shadowCameraSetup = ShadowCameraSetupPtr(lispsmSetup);
} }
mSceneMgr->setShadowCameraSetup(shadowCameraSetup); mSceneMgr->setShadowCameraSetup(shadowCameraSetup);
sh::Vector4* shadowFar_fadeStart = new sh::Vector4(mShadowFar, mFadeStart * mShadowFar, 0, 0);
sh::Factory::getInstance ().setSharedParameter ("shadowFar_fadeStart", sh::makeProperty<sh::Vector4>(shadowFar_fadeStart));
// Set visibility mask for the shadow render textures // Set visibility mask for the shadow render textures
int visibilityMask = RV_Actors * Settings::Manager::getBool("actor shadows", "Shadows") int visibilityMask = RV_Actors * Settings::Manager::getBool("actor shadows", "Shadows")
+ (RV_Statics + RV_StaticsSmall) * Settings::Manager::getBool("statics 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 ----------------------------------- // --------------------------- Debug overlays to display the content of shadow maps -----------------------------------
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
/* if (Settings::Manager::getBool("debug", "Shadows"))
OverlayManager& mgr = OverlayManager::getSingleton(); {
Overlay* overlay; 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);
OverlayContainer* debugPanel; // destroy if already exists
if ((overlay = mgr.getByName("DebugOverlay")))
// destroy container if exists mgr.destroy(overlay);
try
{ overlay = mgr.create("DebugOverlay");
if (debugPanel = for (size_t i = 0; i < (split ? 3 : 1); ++i) {
static_cast<OverlayContainer*>( TexturePtr tex = mRendering->getScene()->getShadowTexture(i);
mgr.getOverlayElement("Ogre/DebugTexPanel" + StringConverter::toString(i)
))) // Set up a debug panel to display the shadow
mgr.destroyOverlayElement(debugPanel);
} if (MaterialManager::getSingleton().resourceExists("Ogre/DebugTexture" + StringConverter::toString(i)))
catch (Ogre::Exception&) {} MaterialManager::getSingleton().remove("Ogre/DebugTexture" + StringConverter::toString(i));
MaterialPtr debugMat = MaterialManager::getSingleton().create(
debugPanel = (OverlayContainer*) "Ogre/DebugTexture" + StringConverter::toString(i),
(OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugTexPanel" + StringConverter::toString(i))); ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
debugPanel->_setPosition(0.8, i*0.25);
debugPanel->_setDimensions(0.2, 0.24); debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
debugPanel->setMaterialName(debugMat->getName()); TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName());
debugPanel->show(); t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
overlay->add2D(debugPanel);
overlay->show(); OverlayContainer* debugPanel;
}
*/ // destroy container if exists
try
{
if ((debugPanel =
static_cast<OverlayContainer*>(
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() PSSMShadowCameraSetup* Shadows::getPSSMSetup()

View file

@ -15,8 +15,12 @@
#include <OgreOverlayManager.h> #include <OgreOverlayManager.h>
#include <OgreOverlayContainer.h> #include <OgreOverlayContainer.h>
#include <boost/lexical_cast.hpp>
#include <components/nifogre/ogre_nif_loader.hpp> #include <components/nifogre/ogre_nif_loader.hpp>
#include <extern/shiny/Platforms/Ogre/OgreMaterial.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -29,15 +33,51 @@ using namespace Ogre;
BillboardObject::BillboardObject( const String& textureName, BillboardObject::BillboardObject( const String& textureName,
const float initialSize, const float initialSize,
const Vector3& position, 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<sh::StringValue>(new sh::StringValue(textureName)));
sh::Factory::getInstance().getMaterialInstance ("BillboardMaterial"+StringConverter::toString(bodyCount))->setListener(this);
mBBSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount));
bodyCount++;
} }
BillboardObject::BillboardObject() 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) void BillboardObject::setVisible(const bool visible)
{ {
mBBSet->setVisible(visible); mBBSet->setVisible(visible);
@ -50,7 +90,14 @@ void BillboardObject::setSize(const float size)
void BillboardObject::setVisibility(const float visibility) 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<sh::OgreMaterial*>(mMaterial->getMaterial ())->getOgreMaterial ();
for (int i=0; i<m->getNumTechniques(); ++i)
{
Ogre::Technique* t = m->getTechnique(i);
if (t->getNumPasses ())
t->getPass(0)->setDiffuse (0,0,0, visibility);
}
} }
void BillboardObject::setPosition(const Vector3& pPosition) void BillboardObject::setPosition(const Vector3& pPosition)
@ -76,7 +123,14 @@ void BillboardObject::setVisibilityFlags(int flags)
void BillboardObject::setColour(const ColourValue& pColour) void BillboardObject::setColour(const ColourValue& pColour)
{ {
mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour); mColour = pColour;
Ogre::MaterialPtr m = static_cast<sh::OgreMaterial*>(mMaterial->getMaterial ())->getOgreMaterial ();
for (int i=0; i<m->getNumTechniques(); ++i)
{
Ogre::Technique* t = m->getTechnique(i);
if (t->getNumPasses ())
t->getPass(0)->setSelfIllumination (pColour);
}
} }
void BillboardObject::setRenderQueue(unsigned int id) void BillboardObject::setRenderQueue(unsigned int id)
@ -89,178 +143,13 @@ SceneNode* BillboardObject::getNode()
return mNode; 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, Moon::Moon( const String& textureName,
const float initialSize, const float initialSize,
const Vector3& position, 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); setVisibility(1.0);
mPhase = Moon::Phase_Full; mPhase = Moon::Phase_Full;
@ -271,11 +160,6 @@ void Moon::setType(const Moon::Type& type)
mType = 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) void Moon::setPhase(const Moon::Phase& phase)
{ {
// Colour texture // Colour texture
@ -295,7 +179,10 @@ void Moon::setPhase(const Moon::Phase& phase)
textureName += ".dds"; 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; 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 if (i>= 33 && i <= 48) alpha = 64; // second bottom-most row
else alpha = 255; 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<uint8>(255); uint8 tmpR = static_cast<uint8>(255);
uint8 tmpG = static_cast<uint8>(255); uint8 tmpG = static_cast<uint8>(255);
uint8 tmpB = static_cast<uint8>(255); uint8 tmpB = static_cast<uint8>(255);
uint8 tmpA = static_cast<uint8>(alpha); uint8 tmpA = static_cast<uint8>(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 // Modify
*((uint32*)currentVertex) = tmpR | (tmpG << 8) | (tmpB << 16) | (tmpA << 24); *((uint32*)currentVertex) = tmpR | (tmpG << 8) | (tmpB << 16) | (tmpA << 24);
@ -387,8 +261,6 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
, mSceneMgr(NULL) , mSceneMgr(NULL)
, mAtmosphereDay(NULL) , mAtmosphereDay(NULL)
, mAtmosphereNight(NULL) , mAtmosphereNight(NULL)
, mCloudMaterial()
, mAtmosphereMaterial()
, mCloudFragmentShader() , mCloudFragmentShader()
, mClouds() , mClouds()
, mNextClouds() , mNextClouds()
@ -396,8 +268,6 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
, mCloudOpacity(0.0f) , mCloudOpacity(0.0f)
, mCloudSpeed(0.0f) , mCloudSpeed(0.0f)
, mStarsOpacity(0.0f) , mStarsOpacity(0.0f)
, mThunderOverlay(NULL)
, mThunderTextureUnit(NULL)
, mRemainingTransitionTime(0.0f) , mRemainingTransitionTime(0.0f)
, mGlareFade(0.0f) , mGlareFade(0.0f)
, mGlare(0.0f) , mGlare(0.0f)
@ -406,6 +276,8 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
, mMasserEnabled(true) , mMasserEnabled(true)
, mSecundaEnabled(true) , mSecundaEnabled(true)
, mCreated(false) , mCreated(false)
, mCloudAnimationTimer(0.f)
, mMoonRed(false)
{ {
mSceneMgr = pMwRoot->getCreator(); mSceneMgr = pMwRoot->getCreator();
mRootNode = mCamera->getParentSceneNode()->createChildSceneNode(); mRootNode = mCamera->getParentSceneNode()->createChildSceneNode();
@ -415,45 +287,42 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
void SkyManager::create() void SkyManager::create()
{ {
/// \todo preload all the textures and meshes that are used for sky rendering sh::Factory::getInstance().setSharedParameter ("cloudBlendFactor",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(0)));
sh::Factory::getInstance().setSharedParameter ("cloudOpacity",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(1)));
sh::Factory::getInstance().setSharedParameter ("cloudColour",
sh::makeProperty<sh::Vector3>(new sh::Vector3(1,1,1)));
sh::Factory::getInstance().setSharedParameter ("cloudAnimationTimer",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(0)));
sh::Factory::getInstance().setSharedParameter ("nightFade",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(0)));
sh::Factory::getInstance().setTextureAlias ("cloud_texture_1", "");
sh::Factory::getInstance().setTextureAlias ("cloud_texture_2", "");
// Create overlay used for thunderstorm // Create overlay used for thunderstorm
MaterialPtr material = MaterialManager::getSingleton().create( "ThunderMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); mLightning = mSceneMgr->createLight();
Pass* pass = material->getTechnique(0)->getPass(0); mLightning->setType (Ogre::Light::LT_DIRECTIONAL);
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA); mLightning->setDirection (Ogre::Vector3(0.3, -0.7, 0.3));
mThunderTextureUnit = pass->createTextureUnitState(); mLightning->setVisible (false);
mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f)); mLightning->setDiffuseColour (ColourValue(3,3,3));
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();
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->setType(Moon::Type_Secunda);
mSecunda->setRenderQueue(RQG_SkiesEarly+4); 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->setRenderQueue(RQG_SkiesEarly+3);
mMasser->setType(Moon::Type_Masser); 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); 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->setRenderQueue(RQG_SkiesLate);
mSunGlare->setVisibilityFlags(RV_Glare); mSunGlare->setVisibilityFlags(RV_NoReflection);
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
// Stars // Stars
/// \todo sky_night_02.nif (available in Bloodmoon)
MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif"); MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif");
Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif"); Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif");
night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1); night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1);
@ -463,73 +332,17 @@ void SkyManager::create()
mAtmosphereNight = mRootNode->createChildSceneNode(); mAtmosphereNight = mRootNode->createChildSceneNode();
mAtmosphereNight->attachObject(night1_ent); 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; i<night1_ent->getNumSubEntities(); ++i) for (unsigned int i=0; i<night1_ent->getNumSubEntities(); ++i)
{ {
MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial(); std::string matName = "openmw_stars_" + boost::lexical_cast<std::string>(i);
mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); sh::MaterialInstance* m = sh::Factory::getInstance ().createMaterialInstance (matName, "openmw_stars");
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); std::string textureName = sh::retrieveValue<sh::StringValue>(
mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); sh::Factory::getInstance().getMaterialInstance(night1_ent->getSubEntity (i)->getMaterialName ())->getProperty("diffuseMap"), NULL).get();
mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); m->setProperty ("texture", sh::makeProperty<sh::StringValue>(new sh::StringValue(textureName)));
mp->getTechnique(0)->getPass(0)->setVertexProgram(stars_vp->getName());
mp->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName()); night1_ent->getSubEntity(i)->setMaterialName (matName);
mp->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false);
mStarsMaterials[i] = mp;
} }
// Atmosphere (day) // Atmosphere (day)
@ -543,62 +356,7 @@ void SkyManager::create()
atmosphere_ent->setVisibilityFlags(RV_Sky); atmosphere_ent->setVisibilityFlags(RV_Sky);
mAtmosphereDay = mRootNode->createChildSceneNode(); mAtmosphereDay = mRootNode->createChildSceneNode();
mAtmosphereDay->attachObject(atmosphere_ent); mAtmosphereDay->attachObject(atmosphere_ent);
mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial(); atmosphere_ent->getSubEntity (0)->setMaterialName ("openmw_atmosphere");
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());
// Clouds // Clouds
NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif"); NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif");
@ -607,94 +365,11 @@ void SkyManager::create()
clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5); clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5);
SceneNode* clouds_node = mRootNode->createChildSceneNode(); SceneNode* clouds_node = mRootNode->createChildSceneNode();
clouds_node->attachObject(clouds_ent); clouds_node->attachObject(clouds_ent);
mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial(); clouds_ent->getSubEntity(0)->setMaterialName ("openmw_clouds");
mCloudMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false);
clouds_ent->setCastShadows(false); 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); 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; mCreated = true;
} }
@ -723,24 +398,28 @@ void SkyManager::update(float duration)
if (!mEnabled) return; if (!mEnabled) return;
// UV Scroll the clouds // 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<sh::FloatValue>(new sh::FloatValue(mCloudAnimationTimer)));
/// \todo improve this /// \todo improve this
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) ); mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
mSecunda->setPhase ( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) ); mSecunda->setPhase ( static_cast<Moon::Phase>( (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) 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) if (mGlareFade > mGlare)
{ {
mGlareFade -= duration*5; mGlareFade -= duration*10;
if (mGlareFade < mGlare) mGlareFade = mGlare; if (mGlareFade < mGlare) mGlareFade = mGlare;
} }
else if (mGlareFade < mGlare) else if (mGlareFade < mGlare)
{ {
mGlareFade += duration*5; mGlareFade += duration*10;
if (mGlareFade > mGlare) mGlareFade = mGlare; if (mGlareFade > mGlare) mGlareFade = mGlare;
} }
@ -782,42 +461,37 @@ void SkyManager::disable()
void SkyManager::setMoonColour (bool red) void SkyManager::setMoonColour (bool red)
{ {
if (!mCreated) return; mMoonRed = red;
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));
} }
void SkyManager::setWeather(const MWWorld::WeatherResult& weather) void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
{ {
if (!mCreated) return; if (!mCreated) return;
if (mClouds != weather.mCloudTexture) 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; mClouds = weather.mCloudTexture;
} }
if (mNextClouds != weather.mNextCloudTexture) 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; mNextClouds = weather.mNextCloudTexture;
} }
if (mCloudBlendFactor != weather.mCloudBlendFactor) if (mCloudBlendFactor != weather.mCloudBlendFactor)
{ {
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("transitionFactor", Real(weather.mCloudBlendFactor));
mCloudBlendFactor = weather.mCloudBlendFactor; mCloudBlendFactor = weather.mCloudBlendFactor;
sh::Factory::getInstance().setSharedParameter ("cloudBlendFactor",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(weather.mCloudBlendFactor)));
} }
if (mCloudOpacity != weather.mCloudOpacity) if (mCloudOpacity != weather.mCloudOpacity)
{ {
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(weather.mCloudOpacity));
mCloudOpacity = weather.mCloudOpacity; mCloudOpacity = weather.mCloudOpacity;
sh::Factory::getInstance().setSharedParameter ("cloudOpacity",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(weather.mCloudOpacity)));
} }
if (mCloudColour != weather.mSunColor) 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.g*0.7 + weather.mAmbientColor.g*0.7,
weather.mSunColor.b*0.7 + weather.mAmbientColor.b*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<sh::Vector3>(new sh::Vector3(clr.r, clr.g, clr.b)));
mCloudColour = weather.mSunColor; mCloudColour = weather.mSunColor;
} }
if (mSkyColour != weather.mSkyColor) if (mSkyColour != weather.mSkyColor)
{ {
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(weather.mSkyColor);
mMasser->setSkyColour(weather.mSkyColor);
mSecunda->setSkyColour(weather.mSkyColor);
mSkyColour = weather.mSkyColor; mSkyColour = weather.mSkyColor;
sh::Factory::getInstance().setSharedParameter ("atmosphereColour", sh::makeProperty<sh::Vector4>(new sh::Vector4(
weather.mSkyColor.r, weather.mSkyColor.g, weather.mSkyColor.b, weather.mSkyColor.a)));
} }
if (mCloudSpeed != weather.mCloudSpeed) mCloudSpeed = weather.mCloudSpeed;
{
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("speed", Real(weather.mCloudSpeed));
mCloudSpeed = weather.mCloudSpeed;
}
if (weather.mNight && mStarsOpacity != weather.mNightFade) if (weather.mNight && mStarsOpacity != weather.mNightFade)
{ {
@ -851,12 +522,15 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
else else
{ {
mAtmosphereNight->setVisible(true); 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<sh::FloatValue>(new sh::FloatValue(weather.mNightFade)));
mStarsOpacity = weather.mNightFade; mStarsOpacity = weather.mNightFade;
} }
} }
float strength; float strength;
float timeofday_angle = std::abs(mSunGlare->getPosition().z/mSunGlare->getPosition().length()); float timeofday_angle = std::abs(mSunGlare->getPosition().z/mSunGlare->getPosition().length());
if (timeofday_angle <= 0.44) if (timeofday_angle <= 0.44)
@ -897,6 +571,10 @@ void SkyManager::setSunDirection(const Vector3& direction)
if (!mCreated) return; if (!mCreated) return;
mSun->setPosition(direction); mSun->setPosition(direction);
mSunGlare->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<sh::Vector2>(new sh::Vector2(fade, height)));
} }
void SkyManager::setMasserDirection(const Vector3& direction) void SkyManager::setMasserDirection(const Vector3& direction)
@ -931,16 +609,22 @@ void SkyManager::secundaDisable()
mSecundaEnabled = false; mSecundaEnabled = false;
} }
void SkyManager::setThunder(const float factor) void SkyManager::setLightningStrength(const float factor)
{ {
if (!mCreated) return; if (!mCreated) return;
if (factor > 0.f) if (factor > 0.f)
{ {
mThunderOverlay->show(); mLightning->setDiffuseColour (ColourValue(2*factor, 2*factor, 2*factor));
mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, factor*0.6); mLightning->setVisible(true);
} }
else 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) void SkyManager::setMasserFade(const float fade)
@ -986,3 +670,10 @@ void SkyManager::scaleSky(float scale)
{ {
mRootNode->setScale(scale, scale, scale); mRootNode->setScale(scale, scale, scale);
} }
void SkyManager::setGlareEnabled (bool enabled)
{
if (!mCreated)
return;
mSunGlare->setVisible (mSunEnabled && enabled);
}

View file

@ -7,6 +7,8 @@
#include <OgreColourValue.h> #include <OgreColourValue.h>
#include <OgreHighLevelGpuProgram.h> #include <OgreHighLevelGpuProgram.h>
#include <extern/shiny/Main/Factory.hpp>
#include "sky.hpp" #include "sky.hpp"
#include "../mwworld/weather.hpp" #include "../mwworld/weather.hpp"
@ -25,16 +27,20 @@ namespace Ogre
namespace MWRender namespace MWRender
{ {
class BillboardObject class BillboardObject : public sh::MaterialInstanceListener
{ {
public: public:
BillboardObject( const Ogre::String& textureName, BillboardObject( const Ogre::String& textureName,
const float size, const float size,
const Ogre::Vector3& position, const Ogre::Vector3& position,
Ogre::SceneNode* rootNode Ogre::SceneNode* rootNode,
const std::string& material
); );
BillboardObject(); BillboardObject();
void requestedConfiguration (sh::MaterialInstance* m, const std::string& configuration);
void createdConfiguration (sh::MaterialInstance* m, const std::string& configuration);
virtual ~BillboardObject() {} virtual ~BillboardObject() {}
void setColour(const Ogre::ColourValue& pColour); void setColour(const Ogre::ColourValue& pColour);
@ -50,13 +56,10 @@ namespace MWRender
Ogre::SceneNode* getNode(); Ogre::SceneNode* getNode();
protected: protected:
virtual void init(const Ogre::String& textureName, float mVisibility;
const float size, Ogre::ColourValue mColour;
const Ogre::Vector3& position,
Ogre::SceneNode* rootNode);
Ogre::SceneNode* mNode; Ogre::SceneNode* mNode;
Ogre::MaterialPtr mMaterial; sh::MaterialInstance* mMaterial;
Ogre::BillboardSet* mBBSet; Ogre::BillboardSet* mBBSet;
}; };
@ -70,7 +73,8 @@ namespace MWRender
Moon( const Ogre::String& textureName, Moon( const Ogre::String& textureName,
const float size, const float size,
const Ogre::Vector3& position, const Ogre::Vector3& position,
Ogre::SceneNode* rootNode Ogre::SceneNode* rootNode,
const std::string& material
); );
virtual ~Moon() {} virtual ~Moon() {}
@ -95,7 +99,6 @@ namespace MWRender
void setPhase(const Phase& phase); void setPhase(const Phase& phase);
void setType(const Type& type); void setType(const Type& type);
void setSkyColour(const Ogre::ColourValue& colour);
Phase getPhase() const; Phase getPhase() const;
unsigned int getPhaseInt() const; unsigned int getPhaseInt() const;
@ -137,9 +140,6 @@ namespace MWRender
void setMoonColour (bool red); void setMoonColour (bool red);
///< change Secunda colour to red ///< change Secunda colour to red
void setCloudsOpacity(float opacity);
///< change opacity of the clouds
void setWeather(const MWWorld::WeatherResult& weather); void setWeather(const MWWorld::WeatherResult& weather);
Ogre::SceneNode* getSunNode(); Ogre::SceneNode* getSunNode();
@ -164,9 +164,11 @@ namespace MWRender
void secundaEnable(); void secundaEnable();
void secundaDisable(); void secundaDisable();
void setThunder(const float factor); void setLightningStrength(const float factor);
void setLightningDirection(const Ogre::Vector3& dir);
void setGlare(const float glare); void setGlare(const float glare);
void setGlareEnabled(bool enabled);
Ogre::Vector3 getRealSunPos(); Ogre::Vector3 getRealSunPos();
void setSkyPosition(const Ogre::Vector3& position); void setSkyPosition(const Ogre::Vector3& position);
@ -176,10 +178,14 @@ namespace MWRender
private: private:
bool mCreated; bool mCreated;
bool mMoonRed;
float mHour; float mHour;
int mDay; int mDay;
int mMonth; int mMonth;
float mCloudAnimationTimer;
BillboardObject* mSun; BillboardObject* mSun;
BillboardObject* mSunGlare; BillboardObject* mSunGlare;
Moon* mMasser; Moon* mMasser;
@ -192,11 +198,6 @@ namespace MWRender
Ogre::SceneNode* mAtmosphereDay; Ogre::SceneNode* mAtmosphereDay;
Ogre::SceneNode* mAtmosphereNight; Ogre::SceneNode* mAtmosphereNight;
Ogre::MaterialPtr mCloudMaterial;
Ogre::MaterialPtr mAtmosphereMaterial;
Ogre::MaterialPtr mStarsMaterials[7];
Ogre::HighLevelGpuProgramPtr mCloudFragmentShader; Ogre::HighLevelGpuProgramPtr mCloudFragmentShader;
// remember some settings so we don't have to apply them again if they didnt change // 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 mCloudColour;
Ogre::ColourValue mSkyColour; Ogre::ColourValue mSkyColour;
Ogre::Overlay* mThunderOverlay; Ogre::Light* mLightning;
Ogre::TextureUnitState* mThunderTextureUnit;
float mRemainingTransitionTime; float mRemainingTransitionTime;

View file

@ -28,22 +28,22 @@ namespace MWRender
mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend) mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend)
{ {
mTerrainGlobals = OGRE_NEW TerrainGlobalOptions(); mTerrainGlobals = OGRE_NEW TerrainGlobalOptions();
TerrainMaterialGeneratorPtr matGen; TerrainMaterialGeneratorPtr matGen;
TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB(); TerrainMaterial* matGenP = new TerrainMaterial();
matGen.bind(matGenP); matGen.bind(matGenP);
mTerrainGlobals->setDefaultMaterialGenerator(matGen); mTerrainGlobals->setDefaultMaterialGenerator(matGen);
TerrainMaterialGenerator::Profile* const activeProfile = TerrainMaterialGenerator::Profile* const activeProfile =
mTerrainGlobals->getDefaultMaterialGenerator() mTerrainGlobals->getDefaultMaterialGenerator()
->getActiveProfile(); ->getActiveProfile();
mActiveProfile = static_cast<TerrainMaterialGeneratorB::SM2Profile*>(activeProfile); mActiveProfile = static_cast<TerrainMaterial::Profile*>(activeProfile);
//The pixel error should be as high as possible without it being noticed //The pixel error should be as high as possible without it being noticed
//as it governs how fast mesh quality decreases. //as it governs how fast mesh quality decreases.
mTerrainGlobals->setMaxPixelError(8); mTerrainGlobals->setMaxPixelError(8);
mTerrainGlobals->setLayerBlendMapSize(32); mTerrainGlobals->setLayerBlendMapSize(32);
mTerrainGlobals->setDefaultGlobalColourMapSize(65);
//10 (default) didn't seem to be quite enough //10 (default) didn't seem to be quite enough
mTerrainGlobals->setSkirtSize(128); mTerrainGlobals->setSkirtSize(128);
@ -52,26 +52,6 @@ namespace MWRender
//this seemed the distance where it wasn't too noticeable //this seemed the distance where it wasn't too noticeable
mTerrainGlobals->setCompositeMapDistance(mWorldSize*2); 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, mTerrainGroup.setOrigin(Vector3(mWorldSize/2,
0, 0,
-mWorldSize/2)); -mWorldSize/2));
@ -178,23 +158,20 @@ namespace MWRender
terrain->setVisibilityFlags(RV_Terrain); terrain->setVisibilityFlags(RV_Terrain);
terrain->setRenderQueueGroup(RQG_Main); terrain->setRenderQueueGroup(RQG_Main);
// disable or enable global colour map (depends on available vertex colours)
if ( land->landData->usingColours ) if ( land->landData->usingColours )
{ {
// disable or enable global colour map (depends on available vertex colours)
mActiveProfile->setGlobalColourMapEnabled(true);
TexturePtr vertex = getVertexColours(land, TexturePtr vertex = getVertexColours(land,
cellX, cellY, cellX, cellY,
x*(mLandSize-1), x*(mLandSize-1),
y*(mLandSize-1), y*(mLandSize-1),
mLandSize); mLandSize);
//this is a hack to get around the fact that Ogre seems to mActiveProfile->setGlobalColourMapEnabled(true);
//corrupt the global colour map leading to rendering errors mActiveProfile->setGlobalColourMap (terrain, vertex->getName());
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() );
} }
else
mActiveProfile->setGlobalColourMapEnabled (false);
} }
} }
} }

View file

@ -46,7 +46,7 @@ namespace MWRender{
RenderingManager* mRendering; RenderingManager* mRendering;
Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile; TerrainMaterial::Profile* mActiveProfile;
/** /**
* The length in verticies of a single terrain block. * The length in verticies of a single terrain block.

File diff suppressed because it is too large Load diff

View file

@ -26,246 +26,59 @@ THE SOFTWARE.
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
*/ */
#ifndef __Ogre_TerrainMaterialGeneratorB_H__ #ifndef MWRENDER_TERRAINMATERIAL_H
#define __Ogre_TerrainMaterialGeneratorB_H__ #define MWRENDER_TERRAINMATERIAL_H
#include "OgreTerrainPrerequisites.h" #include "OgreTerrainPrerequisites.h"
#include "OgreTerrainMaterialGenerator.h" #include "OgreTerrainMaterialGenerator.h"
#include "OgreGpuProgramParams.h" #include "OgreGpuProgramParams.h"
namespace Ogre namespace sh
{ {
class PSSMShadowCameraSetup; class MaterialInstance;
}
/** \addtogroup Optional Components namespace MWRender
* @{ {
*/
/** \addtogroup Terrain
* Some details on the terrain component
* @{
*/
class TerrainMaterial : public Ogre::TerrainMaterialGenerator
{
public:
/** A TerrainMaterialGenerator which can cope with normal mapped, specular mapped class Profile : public Ogre::TerrainMaterialGenerator::Profile
terrain. {
@note Requires the Cg plugin to render correctly public:
*/ Profile(Ogre::TerrainMaterialGenerator* parent, const Ogre::String& name, const Ogre::String& desc);
class TerrainMaterialGeneratorB : public TerrainMaterialGenerator virtual ~Profile();
{
public:
TerrainMaterialGeneratorB();
~TerrainMaterialGeneratorB();
/** Shader model 2 profile target. virtual bool isVertexCompressionSupported() const { return false; }
*/
class SM2Profile : public TerrainMaterialGenerator::Profile
{
public:
SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc);
~SM2Profile();
bool isVertexCompressionSupported() const {return false;} virtual Ogre::MaterialPtr generate(const Ogre::Terrain* terrain);
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);
void setShadowFar(float far); virtual Ogre::MaterialPtr generateForCompositeMap(const Ogre::Terrain* terrain);
void setShadowFadeStart(float fadestart);
/** Whether to support normal mapping per layer in the shader (default true). virtual Ogre::uint8 getMaxLayers(const Ogre::Terrain* terrain) const;
*/
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);
/** Whether to use PSSM support dynamic texture shadows, and if so the virtual void updateParams(const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain);
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; }
int getNumberOfLightsSupported() const; virtual void updateParamsForCompositeMap(const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain);
/// Internal virtual void requestOptions(Ogre::Terrain* terrain);
bool _isSM3Available() const { return mSM3Available; }
protected:
enum TechniqueType void setGlobalColourMapEnabled(bool enabled);
{ void setGlobalColourMap (Ogre::Terrain* terrain, const std::string& name);
HIGH_LOD,
LOW_LOD,
RENDER_COMPOSITE_MAP
};
void addTechnique(const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt);
/// Interface definition for helper class to generate shaders private:
class ShaderHelper : public TerrainAlloc sh::MaterialInstance* mMaterial;
{
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);
size_t mShadowSamplerStartHi; bool mGlobalColourMap;
size_t mShadowSamplerStartLo;
}; };
/// 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 #endif

View file

@ -8,11 +8,20 @@
#include <OgreCompositorInstance.h> #include <OgreCompositorInstance.h>
#include <OgreCompositorChain.h> #include <OgreCompositorChain.h>
#include <OgreRoot.h> #include <OgreRoot.h>
#include <OgreOverlayManager.h>
#include <OgreOverlayContainer.h>
#include <OgreOverlayElement.h>
#include "sky.hpp" #include "sky.hpp"
#include "renderingmanager.hpp" #include "renderingmanager.hpp"
#include "compositors.hpp" #include "compositors.hpp"
#include <extern/shiny/Main/Factory.hpp>
#include <extern/shiny/Platforms/Ogre/OgreMaterial.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
using namespace Ogre; using namespace Ogre;
namespace MWRender namespace MWRender
@ -22,10 +31,18 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
mCamera (camera), mSceneManager (camera->getSceneManager()), mCamera (camera), mSceneManager (camera->getSceneManager()),
mIsUnderwater(false), mVisibilityFlags(0), mIsUnderwater(false), mVisibilityFlags(0),
mReflectionTarget(0), mActive(1), mToggled(1), mReflectionTarget(0), mActive(1), mToggled(1),
mReflectionRenderActive(false), mRendering(rend) mReflectionRenderActive(false), mRendering(rend),
mOldFarClip(0), mOldFarClip2(0),
mWaterTimer(0.f)
{ {
mSky = rend->getSkyManager(); mSky = rend->getSkyManager();
sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty<sh::Vector3>(new sh::Vector3(0.5, -0.8, 0.2)));
sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(0)));
sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty<sh::Vector2>(new sh::Vector2(1, 0.6)));
mMaterial = MaterialManager::getSingleton().getByName("Water");
mTop = cell->water; mTop = cell->water;
mIsUnderwater = false; mIsUnderwater = false;
@ -40,7 +57,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
mWater->setCastShadows(false); mWater->setCastShadows(false);
mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode(); mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
mWaterNode->setPosition(0, mTop, 0);
mReflectionCamera = mSceneManager->createCamera("ReflectionCamera"); mReflectionCamera = mSceneManager->createCamera("ReflectionCamera");
@ -53,27 +69,38 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
applyRTT(); applyRTT();
applyVisibilityMask(); applyVisibilityMask();
createMaterial();
mWater->setMaterial(mMaterial); 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); mSceneManager->addRenderQueueListener(this);
assignTextures(); assignTextures();
setHeight(mTop);
sh::MaterialInstance* m = sh::Factory::getInstance ().getMaterialInstance ("Water");
m->setListener (this);
// ---------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------
// ---------------------------------- reflection debug overlay ---------------------------------- // ---------------------------------- reflection debug overlay ----------------------------------
// ---------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------
/* /*
if (Settings::Manager::getBool("shader", "Water")) if (Settings::Manager::getBool("shader", "Water"))
{ {
OverlayManager& mgr = OverlayManager::getSingleton(); OverlayManager& mgr = OverlayManager::getSingleton();
Overlay* overlay; Overlay* overlay;
// destroy if already exists // destroy if already exists
if (overlay = mgr.getByName("ReflectionDebugOverlay")) if ((overlay = mgr.getByName("ReflectionDebugOverlay")))
mgr.destroy(overlay); mgr.destroy(overlay);
overlay = mgr.create("ReflectionDebugOverlay"); overlay = mgr.create("ReflectionDebugOverlay");
@ -85,18 +112,17 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false); debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName()); debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(mReflectionTexture->getName());
t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
OverlayContainer* debugPanel; OverlayContainer* debugPanel;
// destroy container if exists // destroy container if exists
try try
{ {
if (debugPanel = if ((debugPanel =
static_cast<OverlayContainer*>( static_cast<OverlayContainer*>(
mgr.getOverlayElement("Ogre/ReflectionDebugTexPanel" mgr.getOverlayElement("Ogre/ReflectionDebugTexPanel"
))) ))))
mgr.destroyOverlayElement(debugPanel); mgr.destroyOverlayElement(debugPanel);
} }
catch (Ogre::Exception&) {} catch (Ogre::Exception&) {}
@ -110,13 +136,15 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
overlay->add2D(debugPanel); overlay->add2D(debugPanel);
overlay->show(); overlay->show();
} }
*/ */
} }
void Water::setActive(bool active) void Water::setActive(bool active)
{ {
mActive = active; mActive = active;
updateVisible(); updateVisible();
sh::Factory::getInstance ().setSharedParameter ("waterEnabled", sh::makeProperty<sh::FloatValue> (new sh::FloatValue(active ? 1.0 : 0.0)));
} }
Water::~Water() Water::~Water()
@ -144,8 +172,14 @@ void Water::changeCell(const ESM::Cell* cell)
void Water::setHeight(const float height) void Water::setHeight(const float height)
{ {
mTop = height; mTop = height;
mWaterPlane = Plane(Vector3::UNIT_Y, 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); mWaterNode->setPosition(0, height, 0);
sh::Factory::getInstance ().setSharedParameter ("waterLevel", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(height)));
} }
void Water::toggle() void Water::toggle()
@ -158,36 +192,16 @@ void Water::checkUnderwater(float y)
{ {
if (!mActive) if (!mActive)
{ {
mRendering->getCompositors()->setCompositorEnabled(mCompositorName, false);
return; return;
} }
if ((mIsUnderwater && y > mTop) || !mWater->isVisible() || mCamera->getPolygonMode() != Ogre::PM_SOLID) 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; mIsUnderwater = false;
} }
if (!mIsUnderwater && y < mTop && mWater->isVisible() && mCamera->getPolygonMode() == Ogre::PM_SOLID) 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; mIsUnderwater = true;
} }
@ -211,12 +225,11 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt)
mReflectionCamera->setFOVy(mCamera->getFOVy()); mReflectionCamera->setFOVy(mCamera->getFOVy());
mReflectionRenderActive = true; mReflectionRenderActive = true;
/// \todo For some reason this camera is delayed for 1 frame, which causes ugly sky reflection behaviour.. /// \todo the reflection render (and probably all renderingmanager-updates) lag behind 1 camera frame for some reason
/// to circumvent this we just scale the sky up, so it's not that noticable
Vector3 pos = mCamera->getRealPosition(); Vector3 pos = mCamera->getRealPosition();
pos.y = mTop*2 - pos.y; pos.y = mTop*2 - pos.y;
mSky->setSkyPosition(pos); mSky->setSkyPosition(pos);
mSky->scaleSky(mCamera->getFarClipDistance() / 5000.f); mSky->scaleSky(mCamera->getFarClipDistance() / 50.f);
mReflectionCamera->enableReflection(mWaterPlane); mReflectionCamera->enableReflection(mWaterPlane);
} }
} }
@ -233,48 +246,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() void Water::assignTextures()
{ {
if (Settings::Manager::getBool("shader", "Water")) if (Settings::Manager::getBool("shader", "Water"))
{ {
CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mRendering->getViewport())->getCompositor("gbuffer"); CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mRendering->getViewport())->getCompositor("gbuffer");
TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0); TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0);
TextureUnitState* tus = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState("refractionMap"); sh::Factory::getInstance ().setTextureAlias ("WaterRefraction", colorTexture->getName());
if (tus != 0)
tus->setTexture(colorTexture);
TexturePtr depthTexture = compositor->getTextureInstance("mrt_output", 1); TexturePtr depthTexture = compositor->getTextureInstance("mrt_output", 1);
tus = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState("depthMap"); sh::Factory::getInstance ().setTextureAlias ("SceneDepth", depthTexture->getName());
if (tus != 0)
tus->setTexture(depthTexture);
} }
} }
@ -288,7 +271,7 @@ void Water::updateVisible()
{ {
mWater->setVisible(mToggled && mActive); mWater->setVisible(mToggled && mActive);
if (mReflectionTarget) if (mReflectionTarget)
mReflectionTarget->setActive(mToggled && mActive && !mIsUnderwater); mReflectionTarget->setActive(mToggled && mActive);
} }
void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation)
@ -296,22 +279,48 @@ 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) // We don't want the sky to get clipped by custom near clip plane (the water plane)
if (queueGroupId < 20 && mReflectionRenderActive) if (queueGroupId < 20 && mReflectionRenderActive)
{ {
mOldFarClip = mReflectionCamera->getFarClipDistance ();
mReflectionCamera->disableCustomNearClipPlane(); mReflectionCamera->disableCustomNearClipPlane();
mReflectionCamera->setFarClipDistance (1000000000);
Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); 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) void Water::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation)
{ {
if (queueGroupId < 20 && mReflectionRenderActive) if (queueGroupId < 20 && mReflectionRenderActive)
{ {
mReflectionCamera->enableCustomNearClipPlane(mWaterPlane); mReflectionCamera->setFarClipDistance (mOldFarClip);
if (!mIsUnderwater)
mReflectionCamera->enableCustomNearClipPlane(mErrorPlane);
Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS()); 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<sh::FloatValue>(new sh::FloatValue(mWaterTimer)));
mRendering->getSkyManager ()->setGlareEnabled (!mIsUnderwater);
} }
void Water::applyRTT() void Water::applyRTT()
@ -336,14 +345,14 @@ void Water::applyRTT()
vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f)); vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f));
vp->setShadowsEnabled(false); vp->setShadowsEnabled(false);
// use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain) // 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->addListener(this);
rtt->setActive(true); rtt->setActive(true);
mReflectionTarget = rtt; mReflectionTarget = rtt;
}
mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT"; sh::Factory::getInstance ().setTextureAlias ("WaterReflection", mReflectionTexture->getName());
}
} }
void Water::applyVisibilityMask() void Water::applyVisibilityMask()
@ -386,7 +395,6 @@ void Water::processChangedSettings(const Settings::CategorySettingVector& settin
{ {
applyRTT(); applyRTT();
applyVisibilityMask(); applyVisibilityMask();
createMaterial();
mWater->setMaterial(mMaterial); mWater->setMaterial(mMaterial);
assignTextures(); assignTextures();
} }
@ -394,4 +402,29 @@ void Water::processChangedSettings(const Settings::CategorySettingVector& settin
applyVisibilityMask(); 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<sh::OgreMaterial*>(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 } // namespace

View file

@ -13,6 +13,8 @@
#include "renderconst.hpp" #include "renderconst.hpp"
#include <extern/shiny/Main/MaterialInstance.hpp>
namespace Ogre namespace Ogre
{ {
class Camera; class Camera;
@ -29,21 +31,30 @@ namespace MWRender {
class RenderingManager; class RenderingManager;
/// Water rendering /// 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; static const int CELL_SIZE = 8192;
Ogre::Camera *mCamera; Ogre::Camera *mCamera;
Ogre::SceneManager *mSceneManager; Ogre::SceneManager *mSceneManager;
Ogre::Plane mWaterPlane; Ogre::Plane mWaterPlane;
Ogre::Plane mErrorPlane;
Ogre::SceneNode *mWaterNode; Ogre::SceneNode *mWaterNode;
Ogre::Entity *mWater; Ogre::Entity *mWater;
//Ogre::SceneNode* mUnderwaterDome;
bool mIsUnderwater; bool mIsUnderwater;
bool mActive; bool mActive;
bool mToggled; bool mToggled;
int mTop; int mTop;
int mOldFarClip;
int mOldFarClip2;
float mWaterTimer;
bool mReflectionRenderActive; bool mReflectionRenderActive;
Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY); Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY);
@ -65,7 +76,6 @@ namespace MWRender {
std::string mCompositorName; std::string mCompositorName;
void createMaterial();
Ogre::MaterialPtr mMaterial; Ogre::MaterialPtr mMaterial;
Ogre::Camera* mReflectionCamera; Ogre::Camera* mReflectionCamera;
@ -83,7 +93,7 @@ namespace MWRender {
void setActive(bool active); void setActive(bool active);
void toggle(); void toggle();
void update(); void update(float dt);
void assignTextures(); void assignTextures();
@ -95,6 +105,9 @@ namespace MWRender {
void changeCell(const ESM::Cell* cell); void changeCell(const ESM::Cell* cell);
void setHeight(const float height); 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);
}; };
} }

View file

@ -181,16 +181,15 @@ namespace MWWorld
playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90; 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.rightmove = -iter->second.x;
pm_ref.forwardmove = -iter->second.y; pm_ref.forwardmove = -iter->second.y;
pm_ref.upmove = iter->second.z; pm_ref.upmove = iter->second.z;
} }

View file

@ -476,8 +476,7 @@ WeatherResult WeatherManager::transition(float factor)
result.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor); result.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor);
result.mFogDepth = lerp(current.mFogDepth, other.mFogDepth); result.mFogDepth = lerp(current.mFogDepth, other.mFogDepth);
result.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed); result.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed);
//result.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed); result.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed);
result.mCloudSpeed = current.mCloudSpeed;
result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity); result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity);
result.mGlareView = lerp(current.mGlareView, other.mGlareView); result.mGlareView = lerp(current.mGlareView, other.mGlareView);
result.mNightFade = lerp(current.mNightFade, other.mNightFade); result.mNightFade = lerp(current.mNightFade, other.mNightFade);
@ -689,13 +688,13 @@ void WeatherManager::update(float duration)
mThunderFlash -= duration; mThunderFlash -= duration;
if (mThunderFlash > 0) if (mThunderFlash > 0)
mRendering->getSkyManager()->setThunder( mThunderFlash / WeatherGlobals::mThunderThreshold ); mRendering->getSkyManager()->setLightningStrength( mThunderFlash / WeatherGlobals::mThunderThreshold );
else else
{ {
srand(time(NULL)); srand(time(NULL));
mThunderChanceNeeded = rand() % 100; mThunderChanceNeeded = rand() % 100;
mThunderChance = 0; mThunderChance = 0;
mRendering->getSkyManager()->setThunder( 0.f ); mRendering->getSkyManager()->setLightningStrength( 0.f );
} }
} }
else else
@ -706,14 +705,14 @@ void WeatherManager::update(float duration)
{ {
mThunderFlash = WeatherGlobals::mThunderThreshold; mThunderFlash = WeatherGlobals::mThunderThreshold;
mRendering->getSkyManager()->setThunder( mThunderFlash / WeatherGlobals::mThunderThreshold ); mRendering->getSkyManager()->setLightningStrength( mThunderFlash / WeatherGlobals::mThunderThreshold );
mThunderSoundDelay = WeatherGlobals::mThunderSoundDelay; mThunderSoundDelay = WeatherGlobals::mThunderSoundDelay;
} }
} }
} }
else else
mRendering->getSkyManager()->setThunder(0.f); mRendering->getSkyManager()->setLightningStrength(0.f);
mRendering->setAmbientColour(result.mAmbientColor); mRendering->setAmbientColour(result.mAmbientColor);
mRendering->sunEnable(); mRendering->sunEnable();
@ -725,7 +724,7 @@ void WeatherManager::update(float duration)
{ {
mRendering->sunDisable(); mRendering->sunDisable();
mRendering->skyDisable(); mRendering->skyDisable();
mRendering->getSkyManager()->setThunder(0.f); mRendering->getSkyManager()->setLightningStrength(0.f);
} }
// play sounds // play sounds

View file

@ -22,3 +22,10 @@ endforeach (f)
endforeach (u) endforeach (u)
source_group ("components\\${dir}" FILES ${files}) source_group ("components\\${dir}" FILES ${files})
endmacro (add_component_dir) 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)

View file

@ -15,7 +15,6 @@ namespace Files
{ {
static const char* const openmwCfgFile = "openmw.cfg"; static const char* const openmwCfgFile = "openmw.cfg";
static const char* const pluginsCfgFile = "plugins.cfg";
const char* const mwToken = "?mw?"; const char* const mwToken = "?mw?";
const char* const localToken = "?local?"; const char* const localToken = "?local?";
@ -29,17 +28,6 @@ ConfigurationManager::ConfigurationManager()
boost::filesystem::create_directories(mFixedPath.getUserPath()); 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(); mLogPath = mFixedPath.getUserPath();
} }
@ -164,11 +152,6 @@ const boost::filesystem::path& ConfigurationManager::getInstallPath() const
return mFixedPath.getInstallPath(); return mFixedPath.getInstallPath();
} }
const boost::filesystem::path& ConfigurationManager::getPluginsConfigPath() const
{
return mPluginsCfgPath;
}
const boost::filesystem::path& ConfigurationManager::getLogPath() const const boost::filesystem::path& ConfigurationManager::getLogPath() const
{ {
return mLogPath; return mLogPath;

View file

@ -40,7 +40,6 @@ struct ConfigurationManager
const boost::filesystem::path& getLocalDataPath() const; const boost::filesystem::path& getLocalDataPath() const;
const boost::filesystem::path& getInstallPath() const; const boost::filesystem::path& getInstallPath() const;
const boost::filesystem::path& getPluginsConfigPath() const;
const boost::filesystem::path& getLogPath() const; const boost::filesystem::path& getLogPath() const;
private: private:
@ -57,7 +56,6 @@ struct ConfigurationManager
FixedPathType mFixedPath; FixedPathType mFixedPath;
boost::filesystem::path mPluginsCfgPath;
boost::filesystem::path mLogPath; boost::filesystem::path mLogPath;
TokensMappingContainer mTokensMapping; TokensMappingContainer mTokensMapping;

View file

@ -33,6 +33,11 @@
#include <OgreSubMesh.h> #include <OgreSubMesh.h>
#include <OgreRoot.h> #include <OgreRoot.h>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <extern/shiny/Main/Factory.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/nifoverrides/nifoverrides.hpp> #include <components/nifoverrides/nifoverrides.hpp>
@ -207,139 +212,82 @@ void NIFLoader::createMaterial(const Ogre::String &name,
const Ogre::Vector3 &emissive, const Ogre::Vector3 &emissive,
float glossiness, float alpha, float glossiness, float alpha,
int alphaFlags, float alphaTest, 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<sh::Vector3> (
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<sh::Vector4> (
new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha)));
/* if(!mSkel.isNull()){ instance->setProperty ("specular", sh::makeProperty<sh::Vector4> (
material->removeAllTechniques(); new sh::Vector4(specular.x, specular.y, specular.z, glossiness)));
Ogre::Technique* tech = material->createTechnique(); instance->setProperty ("emissive", sh::makeProperty<sh::Vector3> (
//tech->setSchemeName("blahblah"); new sh::Vector3(emissive.x, emissive.y, emissive.z)));
Pass* pass = tech->createPass();
pass->setVertexProgram("Ogre/BasicVertexPrograms/AmbientOneTexture");*/
instance->setProperty ("diffuseMap", sh::makeProperty(texName));
// This assigns the texture to this material. If the texture name is if (vertexColor)
// a file name, and this file exists (in a resource directory), it instance->setProperty ("has_vertex_colour", sh::makeProperty<sh::BooleanValue>(new sh::BooleanValue(true)));
// 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.
// Add transparency if NiAlphaProperty was present
if (!texName.empty()) if (alphaFlags != -1)
{ {
Ogre::Pass *pass = material->getTechnique(0)->getPass(0); // The 237 alpha flags are by far the most common. Check
/*TextureUnitState *txt =*/ // NiAlphaProperty in nif/property.h if you need to decode
pass->createTextureUnitState(texName); // other values. 237 basically means normal transparencly.
if (alphaFlags == 237)
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)
{ {
std::cout << "Alpha flags set!" << endl; NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName);
if ((alphaFlags&1)) if (result.first)
{ {
pass->setDepthWriteEnabled(false); instance->setProperty("alpha_rejection",
pass->setSceneBlending(getBlendFactor((alphaFlags>>1)&0xf), sh::makeProperty<sh::StringValue>(new sh::StringValue("greater_equal " + boost::lexical_cast<std::string>(result.second))));
getBlendFactor((alphaFlags>>5)&0xf));
} }
else 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); // Enable transparency
if (result.first) instance->setProperty("scene_blend", sh::makeProperty<sh::StringValue>(new sh::StringValue("alpha_blend")));
{ instance->setProperty("depth_write", sh::makeProperty<sh::StringValue>(new sh::StringValue("off")));
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;
}
} }
else
warn("Unhandled alpha setting for texture " + texName);
} }
else 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));
} }
else
if (Settings::Manager::getBool("enabled", "Shadows")) pass->setDepthWriteEnabled(true); */
{
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);
} }
// Takes a name and adds a unique part to it. This is just used to // 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; NiTexturingProperty *t = NULL;
NiMaterialProperty *m = NULL; NiMaterialProperty *m = NULL;
NiAlphaProperty *a = 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 // Scan the property list for material information
PropertyList &list = shape->props; PropertyList &list = shape->props;
@ -659,6 +609,8 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
m = static_cast<NiMaterialProperty*>(pr); m = static_cast<NiMaterialProperty*>(pr);
else if (pr->recType == RC_NiAlphaProperty) else if (pr->recType == RC_NiAlphaProperty)
a = static_cast<NiAlphaProperty*>(pr); a = static_cast<NiAlphaProperty*>(pr);
//else if (pr->recType == RC_NiVertexColorProperty)
//v = static_cast<NiVertexColorProperty*>(pr);
} }
// Texture // Texture
@ -727,7 +679,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
{ {
//std::cout << "new"; //std::cout << "new";
createMaterial(material, d->ambient, d->diffuse, d->specular, d->emissive, 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)); MaterialMap.insert(std::make_pair(texName,material));
} }
} }
@ -737,7 +689,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
// material for it. // material for it.
const Ogre::Vector3 zero(0.0f), one(1.0f); const Ogre::Vector3 zero(0.0f), one(1.0f);
createMaterial(material, one, one, zero, zero, 0.0f, 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) ... } // End of material block, if(!hidden) ...

View file

@ -117,7 +117,8 @@ class NIFLoader : Ogre::ManualResourceLoader
const Ogre::Vector3 &emissive, const Ogre::Vector3 &emissive,
float glossiness, float alpha, float glossiness, float alpha,
int alphaFlags, float alphaTest, int alphaFlags, float alphaTest,
const Ogre::String &texName); const Ogre::String &texName,
bool vertexColor);
void findRealTexture(Ogre::String &texName); void findRealTexture(Ogre::String &texName);

View file

@ -3,6 +3,7 @@ CREDITS
Current Developers: Current Developers:
Aleksandar Jovanov Aleksandar Jovanov
Alexander “Ace” Olofsson Alexander “Ace” Olofsson
Artem “greye” Kotsynyak
athile athile
BrotherBrick BrotherBrick
Cris “Mirceam” Mihalache Cris “Mirceam” Mihalache

1
extern/shiny vendored Submodule

@ -0,0 +1 @@
Subproject commit 5546a5bd8474ef328dfedae2df42126cdaf9515f

View file

@ -1,16 +1,50 @@
project(resources) project(resources)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/caustic_0.png "${OpenMW_BINARY_DIR}/resources/water/caustic_0.png" COPYONLY) set(WATER_FILES
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/underwater.cg "${OpenMW_BINARY_DIR}/resources/water/underwater.cg" COPYONLY) underwater_dome.mesh
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/perlinvolume.dds "${OpenMW_BINARY_DIR}/resources/water/perlinvolume.dds" COPYONLY) water_nm.png
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)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.cg "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.cg" COPYONLY) set(GBUFFER_FILES
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.material "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.material" COPYONLY) gbuffer.compositor
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.compositor "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.compositor" COPYONLY) )
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/shadows/depthshadowcaster.material "${OpenMW_BINARY_DIR}/resources/shadows/depthshadowcaster.material" COPYONLY) set(MATERIAL_FILES
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/shadows/depthshadowcaster.cg "${OpenMW_BINARY_DIR}/resources/shadows/depthshadowcaster.cg" COPYONLY) 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}")

View file

@ -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;
}

View file

@ -9,16 +9,21 @@ compositor gbuffer
target mrt_output target mrt_output
{ {
input none input none
pass clear pass clear
{ {
// make sure to set this to the viewport background color from outside
colour_value 0 0 0 1 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 pass render_scene
{ {
// Renders everything except water // Renders everything except water
first_render_queue 0 first_render_queue 0
last_render_queue 70 last_render_queue 50
} }
} }
@ -29,7 +34,7 @@ compositor gbuffer
pass render_quad pass render_quad
{ {
material RenderScene material quad
input 0 mrt_output 0 input 0 mrt_output 0
} }
} }
@ -61,12 +66,12 @@ compositor gbufferFinalizer
} }
pass render_quad pass render_quad
{ {
material RenderSceneNoDepth material quad_noDepthWrite
input 0 previousscene input 0 previousscene
} }
pass render_scene pass render_scene
{ {
first_render_queue 71 first_render_queue 51
last_render_queue 100 last_render_queue 100
} }
} }
@ -78,7 +83,7 @@ compositor gbufferFinalizer
} }
pass render_quad pass render_quad
{ {
material RenderSceneNoDepth material quad_noDepthWrite
input 0 no_mrt_output input 0 no_mrt_output
} }
} }

View file

@ -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
}
}
}
}

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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
}

159
files/materials/core.h Normal file
View file

@ -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

View file

@ -0,0 +1,51 @@
#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)
shSampler2D(alphaMap)
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;
shOutputColour(0).a = shSample(alphaMap, UV).a * materialDiffuse.a;
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

View file

@ -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
}

View file

@ -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
}
}
}

View file

@ -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

View file

@ -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
}

View file

@ -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
}

35
files/materials/quad.mat Normal file
View file

@ -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
}
}

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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
}
}
}

View file

@ -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

View file

@ -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
}

45
files/materials/shadows.h Normal file
View file

@ -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;
}

108
files/materials/sky.mat Normal file
View file

@ -0,0 +1,108 @@
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
}
texture_unit alphaMap
{
direct_texture textures\tx_secunda_full.dds
}
}
}
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
}
}
}

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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
}

View file

@ -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;
}

55
files/materials/water.mat Normal file
View file

@ -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
}

View file

@ -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

View file

@ -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
}

View file

@ -1,68 +1,72 @@
# Minimal MyGUI build system for OpenMW
# Copy resource files into the build directory # Copy resource files into the build directory
set(SDIR ${CMAKE_CURRENT_SOURCE_DIR}) set(SDIR ${CMAKE_CURRENT_SOURCE_DIR})
set(DDIR ${OpenMW_BINARY_DIR}/resources/mygui) set(DDIR ${OpenMW_BINARY_DIR}/resources/mygui)
configure_file("${SDIR}/bigbars.png" "${DDIR}/bigbars.png" COPYONLY) set(MYGUI_FILES
configure_file("${SDIR}/black.png" "${DDIR}/black.png" COPYONLY) atlas1.cfg
configure_file("${SDIR}/core.skin" "${DDIR}/core.skin" COPYONLY) bigbars.png
configure_file("${SDIR}/core.xml" "${DDIR}/core.xml" COPYONLY) black.png
configure_file("${SDIR}/mwgui.png" "${DDIR}/mwgui.png" COPYONLY) core.skin
configure_file("${SDIR}/openmw_resources.xml" "${DDIR}/openmw_resources.xml" COPYONLY) core.xml
configure_file("${SDIR}/openmw_settings.xml" "${DDIR}/openmw_settings.xml" COPYONLY) EBGaramond-Regular.ttf
configure_file("${SDIR}/openmw_box.skin.xml" "${DDIR}/openmw_box.skin.xml" COPYONLY) mwgui.png
configure_file("${SDIR}/openmw_button.skin.xml" "${DDIR}/openmw_button.skin.xml" COPYONLY) Obliviontt.zip
configure_file("${SDIR}/openmw_list.skin.xml" "${DDIR}/openmw_list.skin.xml" COPYONLY) openmw_alchemy_window.layout
configure_file("${SDIR}/openmw_edit.skin.xml" "${DDIR}/openmw_edit.skin.xml" COPYONLY) openmw_book.layout
configure_file("${SDIR}/openmw_console.layout" "${DDIR}/openmw_console.layout" COPYONLY) openmw_box.skin.xml
configure_file("${SDIR}/openmw_console.skin.xml" "${DDIR}/openmw_console.skin.xml" COPYONLY) openmw_button.skin.xml
configure_file("${SDIR}/openmw.font.xml" "${DDIR}/openmw.font.xml" COPYONLY) openmw_chargen_birth.layout
configure_file("${SDIR}/openmw_hud_box.skin.xml" "${DDIR}/openmw_hud_box.skin.xml" COPYONLY) openmw_chargen_class_description.layout
configure_file("${SDIR}/openmw_hud_energybar.skin.xml" "${DDIR}/openmw_hud_energybar.skin.xml" COPYONLY) openmw_chargen_class.layout
configure_file("${SDIR}/openmw_hud.layout" "${DDIR}/openmw_hud.layout" COPYONLY) openmw_chargen_create_class.layout
configure_file("${SDIR}/openmw_text_input.layout" "${DDIR}/openmw_text_input.layout" COPYONLY) openmw_chargen_generate_class_result.layout
configure_file("${SDIR}/openmw_infobox.layout" "${DDIR}/openmw_infobox.layout" COPYONLY) openmw_chargen_race.layout
configure_file("${SDIR}/openmw_chargen_race.layout" "${DDIR}/openmw_chargen_race.layout" COPYONLY) openmw_chargen_review.layout
configure_file("${SDIR}/openmw_chargen_class.layout" "${DDIR}/openmw_chargen_class.layout" COPYONLY) openmw_chargen_select_attribute.layout
configure_file("${SDIR}/openmw_chargen_generate_class_result.layout" "${DDIR}/openmw_chargen_generate_class_result.layout" COPYONLY) openmw_chargen_select_skill.layout
configure_file("${SDIR}/openmw_chargen_create_class.layout" "${DDIR}/openmw_chargen_create_class.layout" COPYONLY) openmw_chargen_select_specialization.layout
configure_file("${SDIR}/openmw_chargen_select_specialization.layout" "${DDIR}/openmw_chargen_select_specialization.layout" COPYONLY) openmw_confirmation_dialog.layout
configure_file("${SDIR}/openmw_chargen_select_attribute.layout" "${DDIR}/openmw_chargen_select_attribute.layout" COPYONLY) openmw_console.layout
configure_file("${SDIR}/openmw_chargen_select_skill.layout" "${DDIR}/openmw_chargen_select_skill.layout" COPYONLY) openmw_console.skin.xml
configure_file("${SDIR}/openmw_chargen_class_description.layout" "${DDIR}/openmw_chargen_class_description.layout" COPYONLY) openmw_container_window.layout
configure_file("${SDIR}/openmw_chargen_birth.layout" "${DDIR}/openmw_chargen_birth.layout" COPYONLY) openmw_count_window.layout
configure_file("${SDIR}/openmw_chargen_review.layout" "${DDIR}/openmw_chargen_review.layout" COPYONLY) openmw_dialogue_window.layout
configure_file("${SDIR}/openmw_dialogue_window.layout" "${DDIR}/openmw_dialogue_window.layout" COPYONLY) openmw_dialogue_window_skin.xml
configure_file("${SDIR}/openmw_dialogue_window_skin.xml" "${DDIR}/openmw_dialogue_window_skin.xml" COPYONLY) openmw_edit.skin.xml
configure_file("${SDIR}/openmw_inventory_window.layout" "${DDIR}/openmw_inventory_window.layout" COPYONLY) openmw.font.xml
configure_file("${SDIR}/openmw_container_window.layout" "${DDIR}/openmw_container_window.layout" COPYONLY) openmw_hud_box.skin.xml
configure_file("${SDIR}/openmw_layers.xml" "${DDIR}/openmw_layers.xml" COPYONLY) openmw_hud_energybar.skin.xml
configure_file("${SDIR}/openmw_mainmenu.layout" "${DDIR}/openmw_mainmenu.layout" COPYONLY) openmw_hud.layout
configure_file("${SDIR}/openmw_mainmenu_skin.xml" "${DDIR}/openmw_mainmenu_skin.xml" COPYONLY) openmw_infobox.layout
configure_file("${SDIR}/openmw_map_window.layout" "${DDIR}/openmw_map_window.layout" COPYONLY) openmw_interactive_messagebox.layout
configure_file("${SDIR}/openmw_map_window_skin.xml" "${DDIR}/openmw_map_window_skin.xml" COPYONLY) openmw_inventory_window.layout
configure_file("${SDIR}/openmw.pointer.xml" "${DDIR}/openmw.pointer.xml" COPYONLY) openmw_journal.layout
configure_file("${SDIR}/openmw_progress.skin.xml" "${DDIR}/openmw_progress.skin.xml" COPYONLY) openmw_journal_skin.xml
configure_file("${SDIR}/openmw_stats_window.layout" "${DDIR}/openmw_stats_window.layout" COPYONLY) openmw_layers.xml
configure_file("${SDIR}/openmw_text.skin.xml" "${DDIR}/openmw_text.skin.xml" COPYONLY) openmw_list.skin.xml
configure_file("${SDIR}/openmw_windows.skin.xml" "${DDIR}/openmw_windows.skin.xml" COPYONLY) openmw_mainmenu.layout
configure_file("${SDIR}/openmw_messagebox.layout" "${DDIR}/openmw_messagebox.layout" COPYONLY) openmw_mainmenu_skin.xml
configure_file("${SDIR}/openmw_interactive_messagebox.layout" "${DDIR}/openmw_interactive_messagebox.layout" COPYONLY) openmw_map_window.layout
configure_file("${SDIR}/openmw_journal.layout" "${DDIR}/openmw_journal.layout" COPYONLY) openmw_map_window_skin.xml
configure_file("${SDIR}/openmw_journal_skin.xml" "${DDIR}/openmw_journal_skin.xml" COPYONLY) openmw_messagebox.layout
configure_file("${SDIR}/openmw_tooltips.layout" "${DDIR}/openmw_tooltips.layout" COPYONLY) openmw.pointer.xml
configure_file("${SDIR}/openmw_scroll.layout" "${DDIR}/openmw_scroll.layout" COPYONLY) openmw_progress.skin.xml
configure_file("${SDIR}/openmw_scroll_skin.xml" "${DDIR}/openmw_scroll_skin.xml" COPYONLY) openmw_resources.xml
configure_file("${SDIR}/openmw_book.layout" "${DDIR}/openmw_book.layout" COPYONLY) openmw_scroll.layout
configure_file("${SDIR}/openmw_count_window.layout" "${DDIR}/openmw_count_window.layout" COPYONLY) openmw_scroll_skin.xml
configure_file("${SDIR}/openmw_trade_window.layout" "${DDIR}/openmw_trade_window.layout" COPYONLY) openmw_settings_window.layout
configure_file("${SDIR}/openmw_settings_window.layout" "${DDIR}/openmw_settings_window.layout" COPYONLY) openmw_settings.xml
configure_file("${SDIR}/openmw_confirmation_dialog.layout" "${DDIR}/openmw_confirmation_dialog.layout" COPYONLY) openmw_spell_window.layout
configure_file("${SDIR}/openmw_alchemy_window.layout" "${DDIR}/openmw_alchemy_window.layout" COPYONLY) openmw_stats_window.layout
configure_file("${SDIR}/openmw_spell_window.layout" "${DDIR}/openmw_spell_window.layout" COPYONLY) openmw_text_input.layout
configure_file("${SDIR}/atlas1.cfg" "${DDIR}/atlas1.cfg" COPYONLY) openmw_text.skin.xml
configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) openmw_tooltips.layout
configure_file("${SDIR}/EBGaramond-Regular.ttf" "${DDIR}/EBGaramond-Regular.ttf" COPYONLY) openmw_trade_window.layout
configure_file("${SDIR}/Obliviontt.zip" "${DDIR}/Obliviontt.zip" COPYONLY) openmw_windows.skin.xml
configure_file("${SDIR}/VeraMono.ttf" "${DDIR}/VeraMono.ttf" COPYONLY) smallbars.png
VeraMono.ttf
)
copy_all_files(${CMAKE_CURRENT_SOURCE_DIR} ${DDIR} "${MYGUI_FILES}")

View file

@ -1,7 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout"> <MyGUI type="Layout">
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 390 390" name="_Main"> <Widget type="Window" skin="MW_Window_NoCaption" layer="Windows" position="0 0 400 414" name="_Main">
<Property key="MinSize" value="400 414"/>
<Property key="MaxSize" value="400 414"/>
<Widget type="TabControl" skin="TabControl" position="8 8 368 340" align="Left Top" name="SettingsTab"> <Widget type="TabControl" skin="TabControl" position="8 8 368 340" align="Left Top" name="SettingsTab">
<Property key="ButtonAutoWidth" value="true"/> <Property key="ButtonAutoWidth" value="true"/>
@ -100,6 +103,12 @@
</Widget> </Widget>
<Widget type="Button" skin="MW_Button" position="212 34 34 24" align="Left Top" name="VSyncButton"/> <Widget type="Button" skin="MW_Button" position="212 34 34 24" align="Left Top" name="VSyncButton"/>
<Widget type="TextBox" skin="SandText" position="262 104 120 24" align="Left Top">
<Property key="Caption" value="Shaders"/>
</Widget>
<Widget type="Button" skin="MW_Button" position="212 104 44 24" align="Left Top" name="ShadersButton"/>
<Widget type="TextBox" skin="SandText" position="74 163 250 24" align="Left Top"> <Widget type="TextBox" skin="SandText" position="74 163 250 24" align="Left Top">
<Property key="Caption" value="Show frames per second"/> <Property key="Caption" value="Show frames per second"/>
</Widget> </Widget>
@ -179,6 +188,55 @@
<Widget type="Button" skin="MW_Button" position="4 56 34 24" align="Left Top" name="ReflectTerrainButton"/> <Widget type="Button" skin="MW_Button" position="4 56 34 24" align="Left Top" name="ReflectTerrainButton"/>
</Widget> </Widget>
<Widget type="TextBox" skin="SandText" position="42 200 120 24" align="Left Top">
<Property key="Caption" value="Underwater effects (caustics, fog)"/>
</Widget>
<Widget type="Button" skin="MW_Button" position="4 200 34 24" align="Left Top" name="UnderwaterButton"/>
</Widget>
<Widget type="TabItem" skin="" position="4 28 344 272">
<Property key="Caption" value=" Shadows "/>
<Widget type="TextBox" skin="SandText" position="42 4 120 24" align="Left Top">
<Property key="Caption" value="Enabled"/>
</Widget>
<Widget type="Button" skin="MW_Button" position="4 4 34 24" align="Left Top" name="ShadowsEnabledButton"/>
<Widget type="Widget" skin="" position="24 32 300 230">
<Widget type="TextBox" skin="SandText" position="42 0 300 24" align="Left Top">
<Property key="Caption" value="Large distance (PSSM3)"/>
</Widget>
<Widget type="Button" skin="MW_Button" position="4 0 34 24" align="Left Top" name="ShadowsLargeDistance"/>
<Widget type="TextBox" skin="SandText" position="72 28 120 24" align="Left Top">
<Property key="Caption" value="Texture size"/>
</Widget>
<Widget type="Button" skin="MW_Button" position="4 28 64 24" align="Left Top" name="ShadowsTextureSize"/>
<Widget type="TextBox" skin="SandText" position="42 56 120 24" align="Left Top">
<Property key="Caption" value="Actor shadows"/>
</Widget>
<Widget type="Button" skin="MW_Button" position="4 56 34 24" align="Left Top" name="ActorShadows"/>
<Widget type="TextBox" skin="SandText" position="42 84 120 24" align="Left Top">
<Property key="Caption" value="World shadows"/>
</Widget>
<Widget type="Button" skin="MW_Button" position="4 84 34 24" align="Left Top" name="StaticsShadows"/>
<Widget type="TextBox" skin="SandText" position="42 112 120 24" align="Left Top">
<Property key="Caption" value="Misc shadows"/>
</Widget>
<Widget type="Button" skin="MW_Button" position="4 112 34 24" align="Left Top" name="MiscShadows"/>
<Widget type="TextBox" skin="SandText" position="42 172 120 24" align="Left Top">
<Property key="Caption" value="Debug overlay"/>
</Widget>
<Widget type="Button" skin="MW_Button" position="4 172 34 24" align="Left Top" name="ShadowsDebug"/>
</Widget>
</Widget> </Widget>
</Widget> </Widget>

View file

@ -322,6 +322,80 @@
</Child> </Child>
</Skin> </Skin>
<Skin name = "MW_Window_NoCaption" size = "256 54">
<Property key="FontName" value = "Default" />
<Property key="TextAlign" value = "ALIGN_CENTER" />
<Property key="TextColour" value = "0.8 0.8 0.8" />
<Property key="Snap" value = "true" />
<Property key="MinSize" value="64 64"/>
<Child type="Widget" skin="BlackBG" offset = "8 28 240 18" align = "ALIGN_STRETCH" name = "Client"/>
<!-- Outer borders -->
<Child type="Widget" skin="TB_T" offset="4 0 248 4" align="ALIGN_TOP ALIGN_HSTRETCH" name="Action">
<Property key="Scale" value = "0 1 0 -1"/>
</Child>
<Child type="Widget" skin="TB_L" offset="0 4 4 46" align="ALIGN_LEFT ALIGN_VSTRETCH" name="Action">
<Property key="Scale" value = "1 0 -1 0"/>
</Child>
<Child type="Widget" skin="TB_B" offset="4 50 248 4" align="ALIGN_BOTTOM ALIGN_HSTRETCH" name="Action">
<Property key="Scale" value = "0 0 0 1"/>
</Child>
<Child type="Widget" skin="TB_R" offset="252 4 4 46" align="ALIGN_RIGHT ALIGN_VSTRETCH" name="Action">
<Property key="Scale" value = "0 0 1 0"/>
</Child>
<Child type="Widget" skin="TB_BR" offset="252 50 4 4" align="ALIGN_RIGHT ALIGN_BOTTOM" name="Action">
<Property key="Scale" value = "0 0 1 1"/>
</Child>
<Child type="Widget" skin="TB_BL" offset="0 50 4 4" align="ALIGN_LEFT ALIGN_BOTTOM" name="Action">
<Property key="Scale" value = "1 0 -1 1"/>
</Child>
<Child type="Widget" skin="TB_TR" offset="252 0 4 4" align="ALIGN_RIGHT ALIGN_TOP" name="Action">
<Property key="Scale" value = "0 1 1 -1"/>
</Child>
<Child type="Widget" skin="TB_TL" offset="0 0 4 4" align="ALIGN_LEFT ALIGN_TOP" name="Action">
<Property key="Scale" value = "1 1 -1 -1"/>
</Child>
<!-- Inner borders -->
<Child type="Widget" skin="TB_T" offset="8 24 240 4" align="ALIGN_TOP ALIGN_HSTRETCH" name="Action">
<Property key="Scale" value = "0 1 0 -1"/>
</Child>
<Child type="Widget" skin="TB_L" offset="4 28 4 18" align="ALIGN_LEFT ALIGN_VSTRETCH" name="Action">
<Property key="Scale" value = "1 0 -1 0"/>
</Child>
<Child type="Widget" skin="TB_B" offset="8 46 240 4" align="ALIGN_BOTTOM ALIGN_HSTRETCH" name="Action">
<Property key="Scale" value = "0 0 0 1"/>
</Child>
<Child type="Widget" skin="TB_R" offset="248 28 4 18" align="ALIGN_RIGHT ALIGN_VSTRETCH" name="Action">
<Property key="Scale" value = "0 0 1 0"/>
</Child>
<Child type="Widget" skin="TB_BR" offset="248 46 4 4" align="ALIGN_BOTTOM ALIGN_RIGHT" name="Action">
<Property key="Scale" value = "0 0 1 1"/>
</Child>
<Child type="Widget" skin="TB_BL" offset="4 46 4 4" align="ALIGN_BOTTOM ALIGN_LEFT" name="Action">
<Property key="Scale" value = "1 0 -1 1"/>
</Child>
<Child type="Widget" skin="TB_TR" offset="248 24 4 4" align="ALIGN_TOP ALIGN_RIGHT" name="Action">
<Property key="Scale" value = "0 1 1 -1"/>
</Child>
<Child type="Widget" skin="TB_TL" offset="4 24 4 4" align="ALIGN_TOP ALIGN_LEFT" name="Action">
<Property key="Scale" value = "1 1 -1 -1"/>
</Child>
<!-- Caption -->
<Child type="Widget" skin="HB_ALL" offset="4 4 248 20" align = "ALIGN_TOP ALIGN_HSTRETCH">
<Property key="Scale" value = "1 1 0 0"/>
</Child>
<!-- This invisible button makes it possible to move the
window by dragging the caption. -->
<Child type="Button" offset="4 4 248 20" align="ALIGN_HSTRETCH ALIGN_TOP" name="Action">
<Property key="Scale" value = "1 1 0 0"/>
</Child>
</Skin>
<Skin name = "MW_Window_Pinnable" size = "256 54"> <Skin name = "MW_Window_Pinnable" size = "256 54">
<Property key="FontName" value = "Default" /> <Property key="FontName" value = "Default" />
<Property key="TextAlign" value = "ALIGN_CENTER" /> <Property key="TextAlign" value = "ALIGN_CENTER" />

View file

@ -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}

View file

@ -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

View file

@ -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}

View file

@ -48,6 +48,8 @@ anisotropy = 4
# Number of texture mipmaps to generate # Number of texture mipmaps to generate
num mipmaps = 5 num mipmaps = 5
shader mode =
[Shadows] [Shadows]
# Shadows are only supported when object shaders are on! # Shadows are only supported when object shaders are on!
enabled = false enabled = false
@ -74,6 +76,8 @@ statics shadows = true
# Fraction of the total shadow distance after which the shadow starts to fade out # Fraction of the total shadow distance after which the shadow starts to fade out
fade start = 0.8 fade start = 0.8
debug = false
[HUD] [HUD]
# FPS counter # FPS counter
# 0: not visible # 0: not visible

View file

@ -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);
}

View file

@ -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
{
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

View file

@ -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);
}

Binary file not shown.

View file

@ -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);
}

View file

@ -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
}
}
}
}

View file

@ -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
{
}
}
}
}

BIN
files/water/water_nm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -9,7 +9,10 @@
#include "OgreTexture.h" #include "OgreTexture.h"
#include "OgreHardwarePixelBuffer.h" #include "OgreHardwarePixelBuffer.h"
#include <boost/filesystem.hpp>
#include <cassert> #include <cassert>
#include <cstdlib>
#include <stdexcept> #include <stdexcept>
using namespace Ogre; using namespace Ogre;
@ -70,7 +73,6 @@ float OgreRenderer::getFPS()
} }
void OgreRenderer::configure(const std::string &logPath, void OgreRenderer::configure(const std::string &logPath,
const std::string &pluginCfg,
const std::string& renderSystem, const std::string& renderSystem,
bool _logging) bool _logging)
{ {
@ -86,13 +88,41 @@ void OgreRenderer::configure(const std::string &logPath,
// Disable logging // Disable logging
log->setDebugOutputEnabled(false); 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("", "", ""); 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(); loadPlugins();
#else
mRoot = new Root(pluginCfg, "", "");
#endif #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); RenderSystem* rs = mRoot->getRenderSystemByName(renderSystem);
if (rs == 0) if (rs == 0)
throw std::runtime_error ("RenderSystem with name " + renderSystem + " not found, make sure the plugins are loaded"); throw std::runtime_error ("RenderSystem with name " + renderSystem + " not found, make sure the plugins are loaded");

View file

@ -110,7 +110,6 @@ namespace OEngine
set up the Root and logging classes. */ set up the Root and logging classes. */
void configure( void configure(
const std::string &logPath, // Path to directory where to store log files const std::string &logPath, // Path to directory where to store log files
const std::string &pluginCfg, // plugin.cfg file
const std::string &renderSystem, const std::string &renderSystem,
bool _logging); // Enable or disable logging bool _logging); // Enable or disable logging