Merge remote branch 'scrawl/shadersystem' into shadersystem

Attention: We have submodules again. Don't forget to update!

Conflicts:
	components/files/configurationmanager.cpp
actorid
Marc Zinnschlag 13 years ago
commit 2c5d3d8df9

3
.gitmodules vendored

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

@ -20,14 +20,6 @@ set (OPENMW_VERSION_RELEASE 0)
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
# Debug suffix for plugins
set(DEBUG_SUFFIX "")
if (DEFINED CMAKE_BUILD_TYPE)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(DEBUG_SUFFIX "_d")
endif()
endif()
# doxygen main page
configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp")
@ -194,14 +186,25 @@ if (UNIX AND NOT APPLE)
find_package (Threads)
endif()
set(BOOST_COMPONENTS system filesystem program_options thread)
if (Boost_VERSION LESS 104900)
set(SHINY_USE_WAVE_SYSTEM_INSTALL TRUE)
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} wave)
else()
set(SHINY_USE_WAVE_SYSTEM_INSTALL FALSE)
endif()
MESSAGE(STATUS ${BOOST_COMPONENTS})
find_package(OGRE REQUIRED)
find_package(MyGUI REQUIRED)
find_package(Boost REQUIRED COMPONENTS system filesystem program_options thread)
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
find_package(OIS REQUIRED)
find_package(OpenAL REQUIRED)
find_package(Bullet REQUIRED)
IF(OGRE_STATIC)
find_package(Cg REQUIRED)
find_package(Cg)
IF(WIN32)
set(OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_Plugin_CgProgramManager_INCLUDE_DIRS} ${OGRE_Plugin_OctreeSceneManager_INCLUDE_DIRS} ${OGRE_Plugin_ParticleFX_INCLUDE_DIRS} ${OGRE_RenderSystem_Direct3D9_INCLUDE_DIRS} ${OGRE_RenderSystem_GL_INCLUDE_DIRS})
ELSE(WIN32)
@ -230,6 +233,22 @@ if (APPLE)
${OGRE_Plugin_ParticleFX_LIBRARY_REL})
endif (APPLE)
# Set up Ogre plugin folder & debug suffix
set(DEBUG_SUFFIX "")
if (DEFINED CMAKE_BUILD_TYPE)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(DEBUG_SUFFIX "_d")
add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d")
else()
add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="")
endif()
endif()
add_definitions(-DOGRE_PLUGIN_DIR_REL="${OGRE_PLUGIN_DIR_REL}")
add_definitions(-DOGRE_PLUGIN_DIR_DBG="${OGRE_PLUGIN_DIR_DBG}")
add_definitions(-DOGRE_PLUGIN_DIR="${OGRE_PLUGIN_DIR}")
add_subdirectory(files/)
add_subdirectory(files/mygui)
@ -254,15 +273,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
"${OpenMW_BINARY_DIR}/openmw.cfg.install")
if (WIN32)
configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.win32
"${OpenMW_BINARY_DIR}/plugins.cfg" COPYONLY)
endif (WIN32)
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.linux
"${OpenMW_BINARY_DIR}/plugins.cfg")
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
"${OpenMW_BINARY_DIR}/openmw.desktop")
endif()
@ -284,13 +296,8 @@ if (APPLE)
set(OGRE_PLUGIN_DIR "${OGRE_PLUGIN_DIR}/")
configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.mac
"${OpenMW_BINARY_DIR}/plugins.cfg")
set(OGRE_PLUGIN_DIR_2 ${OGRE_PLUGIN_DIR})
set(OGRE_PLUGIN_DIR "")
configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.mac
"${OpenMW_BINARY_DIR}/plugins.cfg.install")
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_2})
configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist
@ -337,7 +344,6 @@ if(DPKG_PROGRAM)
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "../etc/openmw/" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
#Install resources
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "share/games/openmw/" FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT "Resources")
@ -354,7 +360,7 @@ if(DPKG_PROGRAM)
SET(CPACK_DEBIAN_PACKAGE_NAME "openmw")
SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}")
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher mwiniimporter;MWiniImporter")
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "nvidia-cg-toolkit (>= 2.1), libboost-filesystem1.46.1 (>= 1.46.1), libboost-program-options1.46.1 (>= 1.46.1), libboost-system1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)")
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libboost-filesystem1.46.1 (>= 1.46.1), libboost-program-options1.46.1 (>= 1.46.1), libboost-system1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)")
SET(CPACK_DEBIAN_PACKAGE_SECTION "Games")
@ -375,7 +381,6 @@ if(WIN32)
INSTALL(FILES ${dll_files} DESTINATION ".")
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg")
INSTALL(FILES
"${OpenMW_BINARY_DIR}/plugins.cfg"
"${OpenMW_SOURCE_DIR}/readme.txt"
"${OpenMW_SOURCE_DIR}/GPL3.txt"
"${OpenMW_SOURCE_DIR}/OFL.txt"
@ -439,6 +444,9 @@ if(WIN32)
include(CPack)
endif(WIN32)
# Extern
add_subdirectory (extern/shiny)
# Components
add_subdirectory (components)
@ -544,7 +552,6 @@ if (APPLE)
install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg.install" RENAME "plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)

@ -1,6 +1,9 @@
#include <QtGui>
#include <cstdlib>
#include <boost/math/common_factor.hpp>
#include <boost/filesystem.hpp>
#include <components/files/configurationmanager.hpp>
#include <components/settings/settings.hpp>
@ -70,20 +73,13 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent)
bool GraphicsPage::setupOgre()
{
QString pluginCfg = mCfgMgr.getPluginsConfigPath().string().c_str();
QFile file(pluginCfg);
// Create a log manager so we can surpress debug text to stdout/stderr
Ogre::LogManager* logMgr = OGRE_NEW Ogre::LogManager;
logMgr->createLog((mCfgMgr.getLogPath().string() + "/launcherOgre.log"), true, false, false);
try
{
#if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9)
mOgre = new Ogre::Root("", "", "./launcherOgre.log");
#else
mOgre = new Ogre::Root(pluginCfg.toStdString(), "", "./launcherOgre.log");
#endif
}
catch(Ogre::Exception &ex)
{
@ -93,7 +89,6 @@ bool GraphicsPage::setupOgre()
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(tr("<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>"));
msgBox.setDetailedText(ogreError);
msgBox.exec();
@ -102,6 +97,32 @@ bool GraphicsPage::setupOgre()
return false;
}
std::string pluginDir;
const char* pluginEnv = getenv("OPENMW_OGRE_PLUGIN_DIR");
if (pluginEnv)
pluginDir = pluginEnv;
else
{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
pluginDir = ".\\";
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
pluginDir = OGRE_PLUGIN_DIR;
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
pluginDir = OGRE_PLUGIN_DIR_REL;
#endif
}
std::string glPlugin = std::string(pluginDir) + "/RenderSystem_GL" + OGRE_PLUGIN_DEBUG_SUFFIX;
if (boost::filesystem::exists(glPlugin + ".so") || boost::filesystem::exists(glPlugin + ".dll"))
mOgre->loadPlugin (glPlugin);
std::string dxPlugin = std::string(pluginDir) + "/RenderSystem_Direct3D9" + OGRE_PLUGIN_DEBUG_SUFFIX;
if (boost::filesystem::exists(dxPlugin + ".so") || boost::filesystem::exists(dxPlugin + ".dll"))
mOgre->loadPlugin (dxPlugin);
#ifdef ENABLE_PLUGIN_GL
mGLPlugin = new Ogre::GLPlugin();
mOgre->installPlugin(mGLPlugin);

@ -15,7 +15,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
renderinginterface localmap occlusionquery terrain terrainmaterial water shadows shaderhelper
renderinginterface localmap occlusionquery terrain terrainmaterial water shadows
compositors
)
@ -100,6 +100,8 @@ target_link_libraries(openmw
${BULLET_LIBRARIES}
${MYGUI_LIBRARIES}
${MYGUI_PLATFORM_LIBRARIES}
"shiny"
"shiny.OgrePlatform"
components
)

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

@ -74,6 +74,14 @@ namespace
return "16 : 10";
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
@ -103,8 +111,19 @@ namespace MWGui
getWidget(mReflectObjectsButton, "ReflectObjectsButton");
getWidget(mReflectActorsButton, "ReflectActorsButton");
getWidget(mReflectTerrainButton, "ReflectTerrainButton");
getWidget(mShadersButton, "ShadersButton");
getWidget(mShadowsEnabledButton, "ShadowsEnabledButton");
getWidget(mShadowsLargeDistance, "ShadowsLargeDistance");
getWidget(mShadowsTextureSize, "ShadowsTextureSize");
getWidget(mActorShadows, "ActorShadows");
getWidget(mStaticsShadows, "StaticsShadows");
getWidget(mMiscShadows, "MiscShadows");
getWidget(mShadowsDebug, "ShadowsDebug");
getWidget(mUnderwaterButton, "UnderwaterButton");
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked);
mUnderwaterButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mShadersButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShadersToggled);
mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mWaterShaderButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mReflectObjectsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
@ -120,6 +139,14 @@ namespace MWGui
mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected);
mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mShadowsEnabledButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mShadowsLargeDistance->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mShadowsTextureSize->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShadowTextureSize);
mActorShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mStaticsShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mMiscShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mShadowsDebug->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mMasterVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mVoiceVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mEffectsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
@ -172,7 +199,6 @@ namespace MWGui
std::string tf = Settings::Manager::getString("texture filtering", "General");
mTextureFilteringButton->setCaption(textureFilteringToStr(tf));
mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(Settings::Manager::getInt("anisotropy", "General")) + ")");
mAnisotropyBox->setVisible(tf == "anisotropic");
float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-sViewDistMin)/(sViewDistMax-sViewDistMin);
int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val;
@ -185,9 +211,27 @@ namespace MWGui
mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1));
mWaterShaderButton->setCaptionWithReplacing(Settings::Manager::getBool("shader", "Water") ? "#{sOn}" : "#{sOff}");
mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect objects", "Water") ? "#{sOn}" : "#{sOff}");
mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect statics", "Water") ? "#{sOn}" : "#{sOff}");
mReflectActorsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect actors", "Water") ? "#{sOn}" : "#{sOff}");
mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "Water") ? "#{sOn}" : "#{sOff}");
mUnderwaterButton->setCaptionWithReplacing(Settings::Manager::getBool("underwater effect", "Water") ? "#{sOn}" : "#{sOff}");
mShadowsTextureSize->setCaption (Settings::Manager::getString ("texture size", "Shadows"));
mShadowsLargeDistance->setCaptionWithReplacing(Settings::Manager::getBool("split", "Shadows") ? "#{sOn}" : "#{sOff}");
mShadowsEnabledButton->setCaptionWithReplacing(Settings::Manager::getBool("enabled", "Shadows") ? "#{sOn}" : "#{sOff}");
mActorShadows->setCaptionWithReplacing(Settings::Manager::getBool("actor shadows", "Shadows") ? "#{sOn}" : "#{sOff}");
mStaticsShadows->setCaptionWithReplacing(Settings::Manager::getBool("statics shadows", "Shadows") ? "#{sOn}" : "#{sOff}");
mMiscShadows->setCaptionWithReplacing(Settings::Manager::getBool("misc shadows", "Shadows") ? "#{sOn}" : "#{sOff}");
mShadowsDebug->setCaptionWithReplacing(Settings::Manager::getBool("debug", "Shadows") ? "#{sOn}" : "#{sOff}");
std::string shaders;
if (!Settings::Manager::getBool("shaders", "Objects"))
shaders = "off";
else
{
shaders = Settings::Manager::getString("shader mode", "General");
}
mShadersButton->setCaption (shaders);
if (!MWRender::RenderingManager::waterShaderSupported())
{
@ -237,6 +281,25 @@ namespace MWGui
mResolutionList->setIndexSelected(MyGUI::ITEM_NONE);
}
void SettingsWindow::onShadowTextureSize(MyGUI::Widget* _sender)
{
std::string size = mShadowsTextureSize->getCaption();
if (size == "512")
size = "1024";
else if (size == "1024")
size = "2048";
else if (size == "2048")
size = "4096";
else
size = "512";
mShadowsTextureSize->setCaption(size);
Settings::Manager::setString("texture size", "Shadows", size);
apply();
}
void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender)
{
std::string on = mWindowManager.getGameSettingString("sOn", "On");
@ -291,6 +354,10 @@ namespace MWGui
{
if (_sender == mWaterShaderButton)
Settings::Manager::setBool("shader", "Water", newState);
else if (_sender == mUnderwaterButton)
{
Settings::Manager::setBool("underwater effect", "Water", newState);
}
else if (_sender == mReflectObjectsButton)
{
Settings::Manager::setBool("reflect misc", "Water", newState);
@ -301,11 +368,68 @@ namespace MWGui
Settings::Manager::setBool("reflect actors", "Water", newState);
else if (_sender == mReflectTerrainButton)
Settings::Manager::setBool("reflect terrain", "Water", newState);
else if (_sender == mShadowsEnabledButton)
Settings::Manager::setBool("enabled", "Shadows", newState);
else if (_sender == mShadowsLargeDistance)
Settings::Manager::setBool("split", "Shadows", newState);
else if (_sender == mActorShadows)
Settings::Manager::setBool("actor shadows", "Shadows", newState);
else if (_sender == mStaticsShadows)
Settings::Manager::setBool("statics shadows", "Shadows", newState);
else if (_sender == mMiscShadows)
Settings::Manager::setBool("misc shadows", "Shadows", newState);
else if (_sender == mShadowsDebug)
Settings::Manager::setBool("debug", "Shadows", newState);
apply();
}
}
void SettingsWindow::onShadersToggled(MyGUI::Widget* _sender)
{
std::string val = static_cast<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)
{
int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 3;
@ -328,7 +452,6 @@ namespace MWGui
next = "none";
mTextureFilteringButton->setCaption(textureFilteringToStr(next));
mAnisotropyBox->setVisible(next == "anisotropic");
Settings::Manager::setString("texture filtering", "General", next);
apply();

@ -42,6 +42,16 @@ namespace MWGui
MyGUI::Button* mReflectObjectsButton;
MyGUI::Button* mReflectActorsButton;
MyGUI::Button* mReflectTerrainButton;
MyGUI::Button* mShadersButton;
MyGUI::Button* mUnderwaterButton;
MyGUI::Button* mShadowsEnabledButton;
MyGUI::Button* mShadowsLargeDistance;
MyGUI::Button* mShadowsTextureSize;
MyGUI::Button* mActorShadows;
MyGUI::Button* mStaticsShadows;
MyGUI::Button* mMiscShadows;
MyGUI::Button* mShadowsDebug;
// audio
MyGUI::ScrollBar* mMasterVolumeSlider;
@ -59,6 +69,9 @@ namespace MWGui
void onResolutionAccept();
void onResolutionCancel();
void onShadersToggled(MyGUI::Widget* _sender);
void onShadowTextureSize(MyGUI::Widget* _sender);
void apply();
};
}

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

@ -450,3 +450,18 @@ void Objects::update(const float dt)
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();
}
}

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

@ -14,13 +14,13 @@ enum RenderQueueGroups
RQG_Main = Ogre::RENDER_QUEUE_MAIN,
RQG_Water = Ogre::RENDER_QUEUE_7+1,
RQG_Alpha = Ogre::RENDER_QUEUE_MAIN+1,
RQG_Alpha = Ogre::RENDER_QUEUE_MAIN,
RQG_OcclusionQuery = Ogre::RENDER_QUEUE_6,
RQG_UnderWater = Ogre::RENDER_QUEUE_7+1,
RQG_UnderWater = Ogre::RENDER_QUEUE_4,
RQG_OcclusionQuery = Ogre::RENDER_QUEUE_8,
RQG_Water = Ogre::RENDER_QUEUE_7+1,
// Sky late (sun & sun flare)
RQG_SkiesLate = Ogre::RENDER_QUEUE_SKIES_LATE
@ -49,12 +49,12 @@ enum VisibilityFlags
RV_Sky = 64,
// Sun glare (not visible in reflection)
RV_Glare = 128,
// not visible in reflection
RV_NoReflection = 128,
RV_OcclusionQuery = 256,
RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water,
RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water
/// \todo markers (normally hidden)
};

@ -14,6 +14,9 @@
#include <OgreCompositionPass.h>
#include <OgreHardwarePixelBuffer.h>
#include <extern/shiny/Main/Factory.hpp>
#include <extern/shiny/Platforms/Ogre/OgrePlatform.hpp>
#include <components/esm/loadstat.hpp>
#include <components/settings/settings.hpp>
@ -27,7 +30,6 @@
#include "../mwinput/inputmanager.hpp" // FIXME
#include "shadows.hpp"
#include "shaderhelper.hpp"
#include "localmap.hpp"
#include "water.hpp"
#include "compositors.hpp"
@ -40,6 +42,15 @@ namespace MWRender {
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine)
:mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0)
{
// select best shader mode
if (Settings::Manager::getString("shader mode", "General") == "")
{
if (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") == std::string::npos)
Settings::Manager::setString("shader mode", "General", "hlsl");
else
Settings::Manager::setString("shader mode", "General", "glsl");
}
mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5);
mRendering.setWindowEventListener(this);
@ -47,6 +58,21 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
mWater = 0;
// material system
sh::OgrePlatform* platform = new sh::OgrePlatform("General", (resDir / "materials").string());
platform->setCacheFolder ("./");
mFactory = new sh::Factory(platform);
sh::Language lang;
std::string l = Settings::Manager::getString("shader mode", "General");
if (l == "glsl")
lang = sh::Language_GLSL;
else if (l == "hlsl")
lang = sh::Language_HLSL;
else
lang = sh::Language_CG;
mFactory->setCurrentLanguage (lang);
//The fog type must be set before any terrain objects are created as if the
//fog type is set to FOG_NONE then the initially created terrain won't have any fog
configureFog(1, ColourValue(1,1,1));
@ -68,18 +94,26 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
// Load resources
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
// Due to the huge world size of MW, we'll want camera-relative rendering.
// This prevents precision artifacts when moving very far from the origin.
mRendering.getScene()->setCameraRelativeRendering(true);
// causes light flicker in opengl when moving..
//mRendering.getScene()->setCameraRelativeRendering(true);
// disable unsupported effects
const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
//const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
if (!waterShaderSupported())
Settings::Manager::setBool("shader", "Water", false);
if ( !(caps->isShaderProfileSupported("fp40") || caps->isShaderProfileSupported("ps_4_0"))
|| !Settings::Manager::getBool("shaders", "Objects"))
if (!Settings::Manager::getBool("shaders", "Objects"))
Settings::Manager::setBool("enabled", "Shadows", false);
sh::Factory::getInstance ().setGlobalSetting ("mrt_output", useMRT() ? "true" : "false");
sh::Factory::getInstance ().setGlobalSetting ("fog", "true");
sh::Factory::getInstance ().setGlobalSetting ("lighting", "true");
sh::Factory::getInstance ().setGlobalSetting ("num_lights", Settings::Manager::getString ("num lights", "Objects"));
sh::Factory::getInstance ().setGlobalSetting ("underwater_effects", Settings::Manager::getString("underwater effect", "Water"));
sh::Factory::getInstance ().setGlobalSetting ("simple_water", Settings::Manager::getBool("shader", "Water") ? "false" : "true");
sh::Factory::getInstance ().setSharedParameter ("viewportBackground", sh::makeProperty<sh::Vector3> (new sh::Vector3(0,0,0)));
sh::Factory::getInstance ().setSharedParameter ("waterEnabled", sh::makeProperty<sh::FloatValue> (new sh::FloatValue(0.0)));
applyCompositors();
// Turn the entire scene (represented by the 'root' node) -90
@ -100,7 +134,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
cameraPitchNode->attachObject(mRendering.getCamera());
mShadows = new Shadows(&mRendering);
mShaderHelper = new ShaderHelper(this);
mTerrainManager = new TerrainManager(mRendering.getScene(), this);
@ -124,7 +157,6 @@ RenderingManager::~RenderingManager ()
delete mPlayer;
delete mSkyManager;
delete mDebugging;
delete mShaderHelper;
delete mShadows;
delete mTerrainManager;
delete mLocalMap;
@ -237,7 +269,7 @@ void RenderingManager::update (float duration){
checkUnderwater();
mWater->update();
mWater->update(duration);
}
void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){
if(store->cell->data.flags & store->cell->HasWater
@ -350,11 +382,9 @@ void RenderingManager::configureFog(const float density, const Ogre::ColourValue
mRendering.getCamera()->setFarClipDistance ( max / density );
mRendering.getViewport()->setBackgroundColour (colour);
CompositorInstance* inst = CompositorManager::getSingleton().getCompositorChain(mRendering.getViewport())->getCompositor("gbuffer");
if (inst != 0)
inst->getCompositor()->getTechnique(0)->getTargetPass(0)->getPass(0)->setClearColour(colour);
if (mWater)
mWater->setViewportBackground(colour);
sh::Factory::getInstance ().setSharedParameter ("viewportBackground",
sh::makeProperty<sh::Vector3> (new sh::Vector3(colour.r, colour.g, colour.b)));
}
@ -517,12 +547,14 @@ Shadows* RenderingManager::getShadows()
void RenderingManager::switchToInterior()
{
mRendering.getScene()->setCameraRelativeRendering(false);
// causes light flicker in opengl when moving..
//mRendering.getScene()->setCameraRelativeRendering(false);
}
void RenderingManager::switchToExterior()
{
mRendering.getScene()->setCameraRelativeRendering(true);
// causes light flicker in opengl when moving..
//mRendering.getScene()->setCameraRelativeRendering(true);
}
Ogre::Vector4 RenderingManager::boundingBoxToScreen(Ogre::AxisAlignedBox bounds)
@ -607,7 +639,38 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
else if (it->second == "shader" && it->first == "Water")
{
applyCompositors();
mShaderHelper->applyShaders();
sh::Factory::getInstance ().setGlobalSetting ("mrt_output", useMRT() ? "true" : "false");
sh::Factory::getInstance ().setGlobalSetting ("simple_water", Settings::Manager::getBool("shader", "Water") ? "false" : "true");
mObjects.rebuildStaticGeometry ();
}
else if (it->second == "underwater effect" && it->first == "Water")
{
sh::Factory::getInstance ().setGlobalSetting ("underwater_effects", Settings::Manager::getString("underwater effect", "Water"));
mObjects.rebuildStaticGeometry ();
}
else if (it->second == "shaders" && it->first == "Objects")
{
sh::Factory::getInstance ().setShadersEnabled (Settings::Manager::getBool("shaders", "Objects"));
mObjects.rebuildStaticGeometry ();
}
else if (it->second == "shader mode" && it->first == "General")
{
sh::Language lang;
std::string l = Settings::Manager::getString("shader mode", "General");
if (l == "glsl")
lang = sh::Language_GLSL;
else if (l == "hlsl")
lang = sh::Language_HLSL;
else
lang = sh::Language_CG;
sh::Factory::getInstance ().setCurrentLanguage (lang);
mObjects.rebuildStaticGeometry ();
}
else if (it->first == "Shadows")
{
mShadows->recreate ();
mObjects.rebuildStaticGeometry ();
}
}
@ -671,14 +734,9 @@ void RenderingManager::applyCompositors()
{
mCompositors->addCompositor("gbuffer", 0);
mCompositors->setCompositorEnabled("gbuffer", true);
mCompositors->addCompositor("Underwater", 1);
mCompositors->addCompositor("gbufferFinalizer", 2);
mCompositors->setCompositorEnabled("gbufferFinalizer", true);
}
else
{
mCompositors->addCompositor("UnderwaterNoMRT", 0);
}
if (mWater)
mWater->assignTextures();

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

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

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

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

@ -15,8 +15,12 @@
#include <OgreOverlayManager.h>
#include <OgreOverlayContainer.h>
#include <boost/lexical_cast.hpp>
#include <components/nifogre/ogre_nif_loader.hpp>
#include <extern/shiny/Platforms/Ogre/OgreMaterial.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
@ -29,15 +33,51 @@ using namespace Ogre;
BillboardObject::BillboardObject( const String& textureName,
const float initialSize,
const Vector3& position,
SceneNode* rootNode)
SceneNode* rootNode,
const std::string& material)
{
init(textureName, initialSize, position, rootNode);
SceneManager* sceneMgr = rootNode->getCreator();
Vector3 finalPosition = position.normalisedCopy() * 1000.f;
static unsigned int bodyCount=0;
/// \todo These billboards are not 100% correct, might want to revisit them later
mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1);
mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize);
mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON);
mBBSet->setCommonDirection( -position.normalisedCopy() );
mBBSet->setVisibilityFlags(RV_Sky);
mNode = rootNode->createChildSceneNode();
mNode->setPosition(finalPosition);
mNode->attachObject(mBBSet);
mBBSet->createBillboard(0,0,0);
mBBSet->setCastShadows(false);
mMaterial = sh::Factory::getInstance().createMaterialInstance ("BillboardMaterial"+StringConverter::toString(bodyCount), material);
mMaterial->setProperty("texture", sh::makeProperty<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()
{
}
void BillboardObject::requestedConfiguration (sh::MaterialInstance* m, const std::string& configuration)
{
}
void BillboardObject::createdConfiguration (sh::MaterialInstance* m, const std::string& configuration)
{
setVisibility(mVisibility);
setColour(mColour);
}
void BillboardObject::setVisible(const bool visible)
{
mBBSet->setVisible(visible);
@ -50,7 +90,14 @@ void BillboardObject::setSize(const float size)
void BillboardObject::setVisibility(const float visibility)
{
mMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, visibility);
mVisibility = visibility;
Ogre::MaterialPtr m = static_cast<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)
@ -76,7 +123,14 @@ void BillboardObject::setVisibilityFlags(int flags)
void BillboardObject::setColour(const ColourValue& pColour)
{
mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour);
mColour = pColour;
Ogre::MaterialPtr m = static_cast<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)
@ -89,178 +143,13 @@ SceneNode* BillboardObject::getNode()
return mNode;
}
void BillboardObject::init(const String& textureName,
const float initialSize,
const Vector3& position,
SceneNode* rootNode)
{
SceneManager* sceneMgr = rootNode->getCreator();
Vector3 finalPosition = position.normalisedCopy() * 1000.f;
static unsigned int bodyCount=0;
/// \todo These billboards are not 100% correct, might want to revisit them later
mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1);
mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize);
mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON);
mBBSet->setCommonDirection( -position.normalisedCopy() );
mBBSet->setVisibilityFlags(RV_Sky);
mNode = rootNode->createChildSceneNode();
mNode->setPosition(finalPosition);
mNode->attachObject(mBBSet);
mBBSet->createBillboard(0,0,0);
mBBSet->setCastShadows(false);
mMaterial = MaterialManager::getSingleton().create("BillboardMaterial"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
mMaterial->removeAllTechniques();
Pass* p = mMaterial->createTechnique()->createPass();
p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
p->setDepthCheckEnabled(false);
p->setDepthWriteEnabled(false);
p->setSelfIllumination(1.0,1.0,1.0);
p->setDiffuse(0.0,0.0,0.0,1.0);
p->setAmbient(0.0,0.0,0.0);
p->setPolygonModeOverrideable(false);
p->createTextureUnitState(textureName);
mBBSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount));
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
HighLevelGpuProgramPtr vshader;
if (mgr.resourceExists("BBO_VP"))
vshader = mgr.getByName("BBO_VP");
else
vshader = mgr.createProgram("BBO_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM);
vshader->setParameter("profiles", "vs_2_x arbvp1");
vshader->setParameter("entry_point", "main_vp");
StringUtil::StrStreamType outStream;
outStream <<
"void main_vp( \n"
" float4 position : POSITION, \n"
" in float2 uv : TEXCOORD0, \n"
" out float2 oUV : TEXCOORD0, \n"
" out float4 oPosition : POSITION, \n"
" uniform float4x4 worldViewProj \n"
") \n"
"{ \n"
" oUV = uv; \n"
" oPosition = mul( worldViewProj, position ); \n"
"}";
vshader->setSource(outStream.str());
vshader->load();
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
mMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
HighLevelGpuProgramPtr fshader;
if (mgr.resourceExists("BBO_FP"))
fshader = mgr.getByName("BBO_FP");
else
fshader = mgr.createProgram("BBO_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM);
fshader->setParameter("profiles", "ps_2_x arbfp1");
fshader->setParameter("entry_point", "main_fp");
StringUtil::StrStreamType outStream2;
outStream2 <<
"void main_fp( \n"
" in float2 uv : TEXCOORD0, \n"
" out float4 oColor : COLOR, \n";
if (RenderingManager::useMRT()) outStream2 <<
" out float4 oColor1 : COLOR1, \n";
outStream2 <<
" uniform sampler2D texture : TEXUNIT0, \n"
" uniform float4 diffuse, \n"
" uniform float4 emissive \n"
") \n"
"{ \n"
" float4 tex = tex2D(texture, uv); \n"
" oColor = float4(emissive.xyz,1) * tex * float4(1,1,1,diffuse.a); \n";
if (RenderingManager::useMRT()) outStream2 <<
" oColor1 = float4(1, 0, 0, 1); \n";
outStream2 <<
"}";
fshader->setSource(outStream2.str());
fshader->load();
fshader->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
mMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName());
bodyCount++;
}
Moon::Moon( const String& textureName,
const float initialSize,
const Vector3& position,
SceneNode* rootNode)
SceneNode* rootNode,
const std::string& material)
: BillboardObject(textureName, initialSize, position, rootNode, material)
{
init(textureName, initialSize, position, rootNode);
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
HighLevelGpuProgramPtr vshader;
if (mgr.resourceExists("Moon_VP"))
vshader = mgr.getByName("Moon_VP");
else
vshader = mgr.createProgram("Moon_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM);
vshader->setParameter("profiles", "vs_2_x arbvp1");
vshader->setParameter("entry_point", "main_vp");
StringUtil::StrStreamType outStream;
outStream <<
"void main_vp( \n"
" float4 position : POSITION, \n"
" in float2 uv : TEXCOORD0, \n"
" out float2 oUV : TEXCOORD0, \n"
" out float4 oPosition : POSITION, \n"
" uniform float4x4 worldViewProj \n"
") \n"
"{ \n"
" oUV = uv; \n"
" oPosition = mul( worldViewProj, position ); \n"
"}";
vshader->setSource(outStream.str());
vshader->load();
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
mMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
HighLevelGpuProgramPtr fshader;
if (mgr.resourceExists("Moon_FP"))
fshader = mgr.getByName("Moon_FP");
else
fshader = mgr.createProgram("Moon_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM);
fshader->setParameter("profiles", "ps_2_x arbfp1");
fshader->setParameter("entry_point", "main_fp");
StringUtil::StrStreamType outStream2;
outStream2 <<
"void main_fp( \n"
" in float2 uv : TEXCOORD0, \n"
" out float4 oColor : COLOR, \n";
if (RenderingManager::useMRT()) outStream2 <<
" out float4 oColor1 : COLOR1, \n";
outStream2 <<
" uniform sampler2D texture : TEXUNIT0, \n"
" uniform float4 skyColour, \n"
" uniform float4 diffuse, \n"
" uniform float4 emissive \n"
") \n"
"{ \n"
" float4 tex = tex2D(texture, uv); \n"
" oColor = float4(emissive.xyz,1) * tex; \n";
if (RenderingManager::useMRT()) outStream2 <<
" oColor1 = float4(1, 0, 0, 1); \n";
outStream2 <<
// use a circle for the alpha (compute UV distance to center)
// looks a bit bad because its not filtered on the edges,
// but it's cheaper than a seperate alpha texture.
" float sqrUVdist = pow(uv.x-0.5,2) + pow(uv.y-0.5, 2); \n"
" oColor.a = diffuse.a * (sqrUVdist >= 0.24 ? 0 : 1); \n"
" oColor.rgb += (1-tex.a) * oColor.a * skyColour.rgb; \n"//fill dark side of moon with skycolour
" oColor.rgb += (1-diffuse.a) * skyColour.rgb; \n"//fade bump
"}";
fshader->setSource(outStream2.str());
fshader->load();
fshader->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
mMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName());
setVisibility(1.0);
mPhase = Moon::Phase_Full;
@ -271,11 +160,6 @@ void Moon::setType(const Moon::Type& type)
mType = type;
}
void Moon::setSkyColour(const Ogre::ColourValue& colour)
{
mMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("skyColour", colour);
}
void Moon::setPhase(const Moon::Phase& phase)
{
// Colour texture
@ -295,7 +179,10 @@ void Moon::setPhase(const Moon::Phase& phase)
textureName += ".dds";
mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(textureName);
if (mType == Moon::Type_Secunda)
sh::Factory::getInstance ().setTextureAlias ("secunda_texture", textureName);
else
sh::Factory::getInstance ().setTextureAlias ("masser_texture", textureName);
mPhase = phase;
}
@ -344,25 +231,12 @@ void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
else if (i>= 33 && i <= 48) alpha = 64; // second bottom-most row
else alpha = 255;
}
// NB we would have to swap R and B depending on rendersystem specific VertexElementType, but doesn't matter since they are both 1
uint8 tmpR = static_cast<uint8>(255);
uint8 tmpG = static_cast<uint8>(255);
uint8 tmpB = static_cast<uint8>(255);
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
*((uint32*)currentVertex) = tmpR | (tmpG << 8) | (tmpB << 16) | (tmpA << 24);
@ -387,8 +261,6 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
, mSceneMgr(NULL)
, mAtmosphereDay(NULL)
, mAtmosphereNight(NULL)
, mCloudMaterial()
, mAtmosphereMaterial()
, mCloudFragmentShader()
, mClouds()
, mNextClouds()
@ -396,8 +268,6 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
, mCloudOpacity(0.0f)
, mCloudSpeed(0.0f)
, mStarsOpacity(0.0f)
, mThunderOverlay(NULL)
, mThunderTextureUnit(NULL)
, mRemainingTransitionTime(0.0f)
, mGlareFade(0.0f)
, mGlare(0.0f)
@ -406,6 +276,8 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
, mMasserEnabled(true)
, mSecundaEnabled(true)
, mCreated(false)
, mCloudAnimationTimer(0.f)
, mMoonRed(false)
{
mSceneMgr = pMwRoot->getCreator();
mRootNode = mCamera->getParentSceneNode()->createChildSceneNode();
@ -415,45 +287,42 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
void SkyManager::create()
{
/// \todo preload all the textures and meshes that are used for sky rendering
sh::Factory::getInstance().setSharedParameter ("cloudBlendFactor",
sh::makeProperty<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
MaterialPtr material = MaterialManager::getSingleton().create( "ThunderMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
Pass* pass = material->getTechnique(0)->getPass(0);
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
mThunderTextureUnit = pass->createTextureUnitState();
mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f));
mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f);
OverlayManager& ovm = OverlayManager::getSingleton();
mThunderOverlay = ovm.create( "ThunderOverlay" );
OverlayContainer* overlay_panel;
overlay_panel = (OverlayContainer*)ovm.createOverlayElement("Panel", "ThunderPanel");
overlay_panel->_setPosition(0, 0);
overlay_panel->_setDimensions(1, 1);
overlay_panel->setMaterialName( "ThunderMaterial" );
overlay_panel->show();
mThunderOverlay->add2D(overlay_panel);
mThunderOverlay->hide();
mSecunda = new Moon("textures\\tx_secunda_full.dds", 0.5, Vector3(-0.4, 0.4, 0.5), mRootNode);
mLightning = mSceneMgr->createLight();
mLightning->setType (Ogre::Light::LT_DIRECTIONAL);
mLightning->setDirection (Ogre::Vector3(0.3, -0.7, 0.3));
mLightning->setVisible (false);
mLightning->setDiffuseColour (ColourValue(3,3,3));
mSecunda = new Moon("secunda_texture", 0.5, Vector3(-0.4, 0.4, 0.5), mRootNode, "openmw_moon");
mSecunda->setType(Moon::Type_Secunda);
mSecunda->setRenderQueue(RQG_SkiesEarly+4);
mMasser = new Moon("textures\\tx_masser_full.dds", 0.75, Vector3(-0.4, 0.4, 0.5), mRootNode);
mMasser = new Moon("masser_texture", 0.75, Vector3(-0.4, 0.4, 0.5), mRootNode, "openmw_moon");
mMasser->setRenderQueue(RQG_SkiesEarly+3);
mMasser->setType(Moon::Type_Masser);
mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 0.4), mRootNode);
mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 0.4), mRootNode, "openmw_sun");
mSun->setRenderQueue(RQG_SkiesEarly+4);
mSunGlare = new BillboardObject("textures\\tx_sun_flash_grey_05.dds", 3, Vector3(0.4, 0.4, 0.4), mRootNode);
mSunGlare = new BillboardObject("textures\\tx_sun_flash_grey_05.dds", 3, Vector3(0.4, 0.4, 0.4), mRootNode, "openmw_sun");
mSunGlare->setRenderQueue(RQG_SkiesLate);
mSunGlare->setVisibilityFlags(RV_Glare);
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
mSunGlare->setVisibilityFlags(RV_NoReflection);
// Stars
/// \todo sky_night_02.nif (available in Bloodmoon)
MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif");
Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif");
night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1);
@ -463,73 +332,17 @@ void SkyManager::create()
mAtmosphereNight = mRootNode->createChildSceneNode();
mAtmosphereNight->attachObject(night1_ent);
// Stars vertex shader
HighLevelGpuProgramPtr stars_vp = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_VERTEX_PROGRAM);
stars_vp->setParameter("profiles", "vs_2_x arbvp1");
stars_vp->setParameter("entry_point", "main_vp");
StringUtil::StrStreamType outStream4;
outStream4 <<
"void main_vp( \n"
" float4 position : POSITION, \n"
" in float2 uv : TEXCOORD0, \n"
" out float2 oUV : TEXCOORD0, \n"
" out float oFade : TEXCOORD1, \n"
" out float4 oPosition : POSITION, \n"
" uniform float4x4 worldViewProj \n"
") \n"
"{ \n"
" oUV = uv; \n"
" oFade = (position.z > 50) ? 1.f : 0.f; \n"
" oPosition = mul( worldViewProj, position ); \n"
"}";
stars_vp->setSource(outStream4.str());
stars_vp->load();
stars_vp->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
// Stars fragment shader
HighLevelGpuProgramPtr stars_fp = mgr.createProgram("Stars_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_FRAGMENT_PROGRAM);
stars_fp->setParameter("profiles", "ps_2_x arbfp1");
stars_fp->setParameter("entry_point", "main_fp");
StringUtil::StrStreamType outStream5;
outStream5 <<
"void main_fp( \n"
" in float2 uv : TEXCOORD0, \n"
" out float4 oColor : COLOR, \n";
if (RenderingManager::useMRT()) outStream5 <<
" out float4 oColor1 : COLOR1, \n";
outStream5 <<
" in float fade : TEXCOORD1, \n"
" uniform sampler2D texture : TEXUNIT0, \n"
" uniform float opacity, \n"
" uniform float4 diffuse, \n"
" uniform float4 emissive \n"
") \n"
"{ \n"
" oColor = tex2D(texture, uv) * float4(emissive.xyz, 1) * float4(1,1,1,fade*diffuse.a); \n";
if (RenderingManager::useMRT()) outStream5 <<
" oColor1 = float4(1, 0, 0, 1); \n";
outStream5 <<
"}";
stars_fp->setSource(outStream5.str());
stars_fp->load();
stars_fp->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
stars_fp->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
for (unsigned int i=0; i<night1_ent->getNumSubEntities(); ++i)
{
MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial();
mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0);
mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0);
mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
mp->getTechnique(0)->getPass(0)->setVertexProgram(stars_vp->getName());
mp->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName());
mp->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false);
mStarsMaterials[i] = mp;
std::string matName = "openmw_stars_" + boost::lexical_cast<std::string>(i);
sh::MaterialInstance* m = sh::Factory::getInstance ().createMaterialInstance (matName, "openmw_stars");
std::string textureName = sh::retrieveValue<sh::StringValue>(
sh::Factory::getInstance().getMaterialInstance(night1_ent->getSubEntity (i)->getMaterialName ())->getProperty("diffuseMap"), NULL).get();
m->setProperty ("texture", sh::makeProperty<sh::StringValue>(new sh::StringValue(textureName)));
night1_ent->getSubEntity(i)->setMaterialName (matName);
}
// Atmosphere (day)
@ -543,62 +356,7 @@ void SkyManager::create()
atmosphere_ent->setVisibilityFlags(RV_Sky);
mAtmosphereDay = mRootNode->createChildSceneNode();
mAtmosphereDay->attachObject(atmosphere_ent);
mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial();
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false);
// Atmosphere shader
HighLevelGpuProgramPtr vshader = mgr.createProgram("Atmosphere_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_VERTEX_PROGRAM);
vshader->setParameter("profiles", "vs_2_x arbvp1");
vshader->setParameter("entry_point", "main_vp");
StringUtil::StrStreamType outStream;
outStream <<
"void main_vp( \n"
" float4 position : POSITION, \n"
" in float4 color : COLOR, \n"
" out float4 oPosition : POSITION, \n"
" out float4 oVertexColor : TEXCOORD0, \n"
" uniform float4x4 worldViewProj \n"
") \n"
"{ \n"
" oPosition = mul( worldViewProj, position ); \n"
" oVertexColor = color; \n"
"}";
vshader->setSource(outStream.str());
vshader->load();
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
HighLevelGpuProgramPtr fshader = mgr.createProgram("Atmosphere_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_FRAGMENT_PROGRAM);
fshader->setParameter("profiles", "ps_2_x arbfp1");
fshader->setParameter("entry_point", "main_fp");
StringUtil::StrStreamType _outStream;
_outStream <<
"void main_fp( \n"
" in float4 iVertexColor : TEXCOORD0, \n"
" out float4 oColor : COLOR, \n";
if (RenderingManager::useMRT()) _outStream <<
" out float4 oColor1 : COLOR1, \n";
_outStream <<
" uniform float4 emissive \n"
") \n"
"{ \n"
" oColor = iVertexColor * emissive; \n";
if (RenderingManager::useMRT()) _outStream <<
" oColor1 = float4(1, 0, 0, 1); \n";
_outStream <<
"}";
fshader->setSource(_outStream.str());
fshader->load();
fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName());
atmosphere_ent->getSubEntity (0)->setMaterialName ("openmw_atmosphere");
// Clouds
NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif");
@ -607,94 +365,11 @@ void SkyManager::create()
clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5);
SceneNode* clouds_node = mRootNode->createChildSceneNode();
clouds_node->attachObject(clouds_ent);
mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial();
mCloudMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false);
clouds_ent->getSubEntity(0)->setMaterialName ("openmw_clouds");
clouds_ent->setCastShadows(false);
// Clouds vertex shader
HighLevelGpuProgramPtr vshader2 = mgr.createProgram("Clouds_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_VERTEX_PROGRAM);
vshader2->setParameter("profiles", "vs_2_x arbvp1");
vshader2->setParameter("entry_point", "main_vp");
StringUtil::StrStreamType outStream3;
outStream3 <<
"void main_vp( \n"
" float4 position : POSITION, \n"
" in float4 color : COLOR, \n"
" out float4 oColor : TEXCOORD1, \n"
" in float2 uv : TEXCOORD0, \n"
" out float2 oUV : TEXCOORD0, \n"
" out float4 oPosition : POSITION, \n"
" uniform float4x4 worldViewProj \n"
") \n"
"{ \n"
" oUV = uv; \n"
" oColor = color; \n"
" oPosition = mul( worldViewProj, position ); \n"
"}";
vshader2->setSource(outStream3.str());
vshader2->load();
vshader2->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
mCloudMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader2->getName());
// Clouds fragment shader
mCloudFragmentShader = mgr.createProgram("Clouds_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_FRAGMENT_PROGRAM);
mCloudFragmentShader->setParameter("profiles", "ps_2_x arbfp1");
mCloudFragmentShader->setParameter("entry_point", "main_fp");
StringUtil::StrStreamType outStream2;
outStream2 <<
"void main_fp( \n"
" in float2 uv : TEXCOORD0, \n"
" in float4 color : TEXCOORD1, \n"
" out float4 oColor : COLOR, \n";
if (RenderingManager::useMRT()) outStream2 <<
" out float4 oColor1 : COLOR1, \n";
outStream2 <<
" uniform sampler2D texture : TEXUNIT0, \n"
" uniform sampler2D secondTexture : TEXUNIT1, \n"
" uniform float transitionFactor, \n"
" uniform float time, \n"
" uniform float speed, \n"
" uniform float opacity, \n"
" uniform float4 emissive \n"
") \n"
"{ \n"
" uv += float2(0,1) * time * speed * 0.003; \n" // Scroll in y direction
" float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n"
" oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n";
if (RenderingManager::useMRT()) outStream2 <<
" oColor1 = float4(1, 0, 0, 1); \n";
outStream2 <<
"}";
mCloudFragmentShader->setSource(outStream2.str());
mCloudFragmentShader->load();
mCloudFragmentShader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
mCloudMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(mCloudFragmentShader->getName());
setCloudsOpacity(0.75);
ModVertexAlpha(clouds_ent, 1);
// I'm not sure if the materials are being used by any other objects
// Make a unique "modifiable" copy of the materials to be sure
mCloudMaterial = mCloudMaterial->clone("Clouds");
clouds_ent->getSubEntity(0)->setMaterial(mCloudMaterial);
mAtmosphereMaterial = mAtmosphereMaterial->clone("Atmosphere");
atmosphere_ent->getSubEntity(0)->setMaterial(mAtmosphereMaterial);
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 0.0);
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0);
mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
mCloudMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
mCloudMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("textures\\tx_sky_cloudy.dds");
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("");
mCreated = true;
}
@ -723,24 +398,28 @@ void SkyManager::update(float duration)
if (!mEnabled) return;
// UV Scroll the clouds
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", MWBase::Environment::get().getWorld()->getTimeScaleFactor()/30.f);
mCloudAnimationTimer += duration * mCloudSpeed * (MWBase::Environment::get().getWorld()->getTimeScaleFactor()/30.f);
sh::Factory::getInstance().setSharedParameter ("cloudAnimationTimer",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(mCloudAnimationTimer)));
/// \todo improve this
mMasser->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)
{
// take 1/5 sec for fading the glare effect from invisible to full
// take 1/10 sec for fading the glare effect from invisible to full
if (mGlareFade > mGlare)
{
mGlareFade -= duration*5;
mGlareFade -= duration*10;
if (mGlareFade < mGlare) mGlareFade = mGlare;
}
else if (mGlareFade < mGlare)
{
mGlareFade += duration*5;
mGlareFade += duration*10;
if (mGlareFade > mGlare) mGlareFade = mGlare;
}
@ -782,42 +461,37 @@ void SkyManager::disable()
void SkyManager::setMoonColour (bool red)
{
if (!mCreated) return;
mSecunda->setColour( red ? ColourValue(1.0, 0.0784, 0.0784)
: ColourValue(1.0, 1.0, 1.0));
}
void SkyManager::setCloudsOpacity(float opacity)
{
if (!mCreated) return;
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(opacity));
mMoonRed = red;
}
void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
{
if (!mCreated) return;
if (mClouds != weather.mCloudTexture)
{
mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("textures\\"+weather.mCloudTexture);
sh::Factory::getInstance().setTextureAlias ("cloud_texture_1", "textures\\"+weather.mCloudTexture);
mClouds = weather.mCloudTexture;
}
if (mNextClouds != weather.mNextCloudTexture)
{
mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName("textures\\"+weather.mNextCloudTexture);
sh::Factory::getInstance().setTextureAlias ("cloud_texture_2", "textures\\"+weather.mNextCloudTexture);
mNextClouds = weather.mNextCloudTexture;
}
if (mCloudBlendFactor != weather.mCloudBlendFactor)
{
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("transitionFactor", Real(weather.mCloudBlendFactor));
mCloudBlendFactor = weather.mCloudBlendFactor;
sh::Factory::getInstance().setSharedParameter ("cloudBlendFactor",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(weather.mCloudBlendFactor)));
}
if (mCloudOpacity != weather.mCloudOpacity)
{
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(weather.mCloudOpacity));
mCloudOpacity = weather.mCloudOpacity;
sh::Factory::getInstance().setSharedParameter ("cloudOpacity",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(weather.mCloudOpacity)));
}
if (mCloudColour != weather.mSunColor)
@ -826,23 +500,20 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
weather.mSunColor.g*0.7 + weather.mAmbientColor.g*0.7,
weather.mSunColor.b*0.7 + weather.mAmbientColor.b*0.7);
mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(clr);
sh::Factory::getInstance().setSharedParameter ("cloudColour",
sh::makeProperty<sh::Vector3>(new sh::Vector3(clr.r, clr.g, clr.b)));
mCloudColour = weather.mSunColor;
}
if (mSkyColour != weather.mSkyColor)
{
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(weather.mSkyColor);
mMasser->setSkyColour(weather.mSkyColor);
mSecunda->setSkyColour(weather.mSkyColor);
mSkyColour = weather.mSkyColor;
sh::Factory::getInstance().setSharedParameter ("atmosphereColour", sh::makeProperty<sh::Vector4>(new sh::Vector4(
weather.mSkyColor.r, weather.mSkyColor.g, weather.mSkyColor.b, weather.mSkyColor.a)));
}
if (mCloudSpeed != weather.mCloudSpeed)
{
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("speed", Real(weather.mCloudSpeed));
mCloudSpeed = weather.mCloudSpeed;
}
mCloudSpeed = weather.mCloudSpeed;
if (weather.mNight && mStarsOpacity != weather.mNightFade)
{
@ -851,12 +522,15 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
else
{
mAtmosphereNight->setVisible(true);
for (int i=0; i<7; ++i)
mStarsMaterials[i]->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, weather.mNightFade);
sh::Factory::getInstance().setSharedParameter ("nightFade",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(weather.mNightFade)));
mStarsOpacity = weather.mNightFade;
}
}
float strength;
float timeofday_angle = std::abs(mSunGlare->getPosition().z/mSunGlare->getPosition().length());
if (timeofday_angle <= 0.44)
@ -897,6 +571,10 @@ void SkyManager::setSunDirection(const Vector3& direction)
if (!mCreated) return;
mSun->setPosition(direction);
mSunGlare->setPosition(direction);
float height = direction.z;
float fade = ( height > 0.5) ? 1.0 : height * 2;
sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty<sh::Vector2>(new sh::Vector2(fade, height)));
}
void SkyManager::setMasserDirection(const Vector3& direction)
@ -931,16 +609,22 @@ void SkyManager::secundaDisable()
mSecundaEnabled = false;
}
void SkyManager::setThunder(const float factor)
void SkyManager::setLightningStrength(const float factor)
{
if (!mCreated) return;
if (factor > 0.f)
{
mThunderOverlay->show();
mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, factor*0.6);
mLightning->setDiffuseColour (ColourValue(2*factor, 2*factor, 2*factor));
mLightning->setVisible(true);
}
else
mThunderOverlay->hide();
mLightning->setVisible(false);
}
void SkyManager::setLightningDirection(const Ogre::Vector3& dir)
{
if (!mCreated) return;
mLightning->setDirection (dir);
}
void SkyManager::setMasserFade(const float fade)
@ -986,3 +670,10 @@ void SkyManager::scaleSky(float scale)
{
mRootNode->setScale(scale, scale, scale);
}
void SkyManager::setGlareEnabled (bool enabled)
{
if (!mCreated)
return;
mSunGlare->setVisible (mSunEnabled && enabled);
}

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

@ -28,22 +28,22 @@ namespace MWRender
mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend)
{
mTerrainGlobals = OGRE_NEW TerrainGlobalOptions();
TerrainMaterialGeneratorPtr matGen;
TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB();
TerrainMaterial* matGenP = new TerrainMaterial();
matGen.bind(matGenP);
mTerrainGlobals->setDefaultMaterialGenerator(matGen);
TerrainMaterialGenerator::Profile* const activeProfile =
mTerrainGlobals->getDefaultMaterialGenerator()
->getActiveProfile();
mActiveProfile = static_cast<TerrainMaterialGeneratorB::SM2Profile*>(activeProfile);
mActiveProfile = static_cast<TerrainMaterial::Profile*>(activeProfile);
//The pixel error should be as high as possible without it being noticed
//as it governs how fast mesh quality decreases.
mTerrainGlobals->setMaxPixelError(8);
mTerrainGlobals->setLayerBlendMapSize(32);
mTerrainGlobals->setDefaultGlobalColourMapSize(65);
//10 (default) didn't seem to be quite enough
mTerrainGlobals->setSkirtSize(128);
@ -52,26 +52,6 @@ namespace MWRender
//this seemed the distance where it wasn't too noticeable
mTerrainGlobals->setCompositeMapDistance(mWorldSize*2);
mActiveProfile->setLightmapEnabled(false);
mActiveProfile->setLayerSpecularMappingEnabled(false);
mActiveProfile->setLayerNormalMappingEnabled(false);
mActiveProfile->setLayerParallaxMappingEnabled(false);
bool shadows = Settings::Manager::getBool("enabled", "Shadows");
mActiveProfile->setReceiveDynamicShadowsEnabled(shadows);
mActiveProfile->setReceiveDynamicShadowsDepth(shadows);
if (Settings::Manager::getBool("split", "Shadows"))
mActiveProfile->setReceiveDynamicShadowsPSSM(mRendering->getShadows()->getPSSMSetup());
else
mActiveProfile->setReceiveDynamicShadowsPSSM(0);
mActiveProfile->setShadowFar(mRendering->getShadows()->getShadowFar());
mActiveProfile->setShadowFadeStart(mRendering->getShadows()->getFadeStart());
//composite maps lead to a drastic increase in loading time so are
//disabled
mActiveProfile->setCompositeMapEnabled(false);
mTerrainGroup.setOrigin(Vector3(mWorldSize/2,
0,
-mWorldSize/2));
@ -178,23 +158,20 @@ namespace MWRender
terrain->setVisibilityFlags(RV_Terrain);
terrain->setRenderQueueGroup(RQG_Main);
// disable or enable global colour map (depends on available vertex colours)
if ( land->landData->usingColours )
{
// disable or enable global colour map (depends on available vertex colours)
mActiveProfile->setGlobalColourMapEnabled(true);
TexturePtr vertex = getVertexColours(land,
cellX, cellY,
x*(mLandSize-1),
y*(mLandSize-1),
mLandSize);
//this is a hack to get around the fact that Ogre seems to
//corrupt the global colour map leading to rendering errors
MaterialPtr mat = terrain->getMaterial();
mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() );
//mat = terrain->_getCompositeMapMaterial();
//mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() );
mActiveProfile->setGlobalColourMapEnabled(true);
mActiveProfile->setGlobalColourMap (terrain, vertex->getName());
}
else
mActiveProfile->setGlobalColourMapEnabled (false);
}
}
}

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

File diff suppressed because it is too large Load Diff

@ -26,246 +26,59 @@ THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#ifndef __Ogre_TerrainMaterialGeneratorB_H__
#define __Ogre_TerrainMaterialGeneratorB_H__
#ifndef MWRENDER_TERRAINMATERIAL_H
#define MWRENDER_TERRAINMATERIAL_H
#include "OgreTerrainPrerequisites.h"
#include "OgreTerrainMaterialGenerator.h"
#include "OgreGpuProgramParams.h"
namespace Ogre
namespace sh
{
class PSSMShadowCameraSetup;
/** \addtogroup Optional Components
* @{
*/
/** \addtogroup Terrain
* Some details on the terrain component
* @{
*/
/** A TerrainMaterialGenerator which can cope with normal mapped, specular mapped
terrain.
@note Requires the Cg plugin to render correctly
*/
class TerrainMaterialGeneratorB : public TerrainMaterialGenerator
{
public:
TerrainMaterialGeneratorB();
~TerrainMaterialGeneratorB();
/** Shader model 2 profile target.
*/
class SM2Profile : public TerrainMaterialGenerator::Profile
{
public:
SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc);
~SM2Profile();
bool isVertexCompressionSupported() const {return false;}
MaterialPtr generate(const Terrain* terrain);
MaterialPtr generateForCompositeMap(const Terrain* terrain);
uint8 getMaxLayers(const Terrain* terrain) const;
void updateParams(const MaterialPtr& mat, const Terrain* terrain);
void updateParamsForCompositeMap(const MaterialPtr& mat, const Terrain* terrain);
void requestOptions(Terrain* terrain);
void setShadowFar(float far);
void setShadowFadeStart(float fadestart);
/** Whether to support normal mapping per layer in the shader (default true).
*/
bool isLayerNormalMappingEnabled() const { return mLayerNormalMappingEnabled; }
/** Whether to support normal mapping per layer in the shader (default true).
*/
void setLayerNormalMappingEnabled(bool enabled);
/** Whether to support parallax mapping per layer in the shader (default true).
*/
bool isLayerParallaxMappingEnabled() const { return mLayerParallaxMappingEnabled; }
/** Whether to support parallax mapping per layer in the shader (default true).
*/
void setLayerParallaxMappingEnabled(bool enabled);
/** Whether to support specular mapping per layer in the shader (default true).
*/
bool isLayerSpecularMappingEnabled() const { return mLayerSpecularMappingEnabled; }
/** Whether to support specular mapping per layer in the shader (default true).
*/
void setLayerSpecularMappingEnabled(bool enabled);
/** Whether to support a global colour map over the terrain in the shader,
if it's present (default true).
*/
bool isGlobalColourMapEnabled() const { return mGlobalColourMapEnabled; }
/** Whether to support a global colour map over the terrain in the shader,
if it's present (default true).
*/
void setGlobalColourMapEnabled(bool enabled);
/** Whether to support a light map over the terrain in the shader,
if it's present (default true).
*/
bool isLightmapEnabled() const { return mLightmapEnabled; }
/** Whether to support a light map over the terrain in the shader,
if it's present (default true).
*/
void setLightmapEnabled(bool enabled);
/** Whether to use the composite map to provide a lower LOD technique
in the distance (default true).
*/
bool isCompositeMapEnabled() const { return mCompositeMapEnabled; }
/** Whether to use the composite map to provide a lower LOD technique
in the distance (default true).
*/
void setCompositeMapEnabled(bool enabled);
/** Whether to support dynamic texture shadows received from other
objects, on the terrain (default true).
*/
bool getReceiveDynamicShadowsEnabled() const { return mReceiveDynamicShadows; }
/** Whether to support dynamic texture shadows received from other
objects, on the terrain (default true).
*/
void setReceiveDynamicShadowsEnabled(bool enabled);
/** Whether to use PSSM support dynamic texture shadows, and if so the
settings to use (default 0).
*/
void setReceiveDynamicShadowsPSSM(PSSMShadowCameraSetup* pssmSettings);
/** Whether to use PSSM support dynamic texture shadows, and if so the
settings to use (default 0).
*/
PSSMShadowCameraSetup* getReceiveDynamicShadowsPSSM() const { return mPSSM; }
/** Whether to use depth shadows (default false).
*/
void setReceiveDynamicShadowsDepth(bool enabled);
/** Whether to use depth shadows (default false).
*/
bool getReceiveDynamicShadowsDepth() const { return mDepthShadows; }
/** Whether to use shadows on low LOD material rendering (when using composite map) (default false).
*/
void setReceiveDynamicShadowsLowLod(bool enabled);
/** Whether to use shadows on low LOD material rendering (when using composite map) (default false).
*/
bool getReceiveDynamicShadowsLowLod() const { return mLowLodShadows; }
int getNumberOfLightsSupported() const;
/// Internal
bool _isSM3Available() const { return mSM3Available; }
protected:
enum TechniqueType
{
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
class ShaderHelper : public TerrainAlloc
{
public:
ShaderHelper() : mShadowSamplerStartHi(0), mShadowSamplerStartLo(0) {}
virtual ~ShaderHelper() {}
virtual HighLevelGpuProgramPtr generateVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
virtual HighLevelGpuProgramPtr generateFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
virtual void updateParams(const SM2Profile* prof, const MaterialPtr& mat, const Terrain* terrain, bool compositeMap);
protected:
virtual String getVertexProgramName(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
virtual String getFragmentProgramName(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
virtual HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) = 0;
virtual HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) = 0;
virtual void generateVertexProgramSource(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
virtual void generateFragmentProgramSource(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
virtual void generateVpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0;
virtual void generateFpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0;
virtual void generateVpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) = 0;
virtual void generateFpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) = 0;
virtual void generateVpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0;
virtual void generateFpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0;
virtual void defaultVpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog);
virtual void defaultFpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog);
virtual void updateVpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params);
virtual void updateFpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params);
static String getChannel(uint idx);
size_t mShadowSamplerStartHi;
size_t mShadowSamplerStartLo;
class MaterialInstance;
}
};
namespace MWRender
{
/// 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 TerrainMaterial : public Ogre::TerrainMaterialGenerator
{
public:
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);
};
class Profile : public Ogre::TerrainMaterialGenerator::Profile
{
public:
Profile(Ogre::TerrainMaterialGenerator* parent, const Ogre::String& name, const Ogre::String& desc);
virtual ~Profile();
/// 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) {}
};
virtual bool isVertexCompressionSupported() const { return false; }
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;
virtual Ogre::MaterialPtr generate(const Ogre::Terrain* terrain);
bool isShadowingEnabled(TechniqueType tt, const Terrain* terrain) const;
virtual Ogre::MaterialPtr generateForCompositeMap(const Ogre::Terrain* terrain);
};
virtual Ogre::uint8 getMaxLayers(const Ogre::Terrain* terrain) const;
virtual void updateParams(const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain);
virtual void updateParamsForCompositeMap(const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain);
virtual void requestOptions(Ogre::Terrain* terrain);
};
void setGlobalColourMapEnabled(bool enabled);
void setGlobalColourMap (Ogre::Terrain* terrain, const std::string& name);
private:
sh::MaterialInstance* mMaterial;
bool mGlobalColourMap;
/** @} */
/** @} */
};
TerrainMaterial();
};
}
#endif

@ -8,11 +8,20 @@
#include <OgreCompositorInstance.h>
#include <OgreCompositorChain.h>
#include <OgreRoot.h>
#include <OgreOverlayManager.h>
#include <OgreOverlayContainer.h>
#include <OgreOverlayElement.h>
#include "sky.hpp"
#include "renderingmanager.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;
namespace MWRender
@ -22,10 +31,18 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
mCamera (camera), mSceneManager (camera->getSceneManager()),
mIsUnderwater(false), mVisibilityFlags(0),
mReflectionTarget(0), mActive(1), mToggled(1),
mReflectionRenderActive(false), mRendering(rend)
mReflectionRenderActive(false), mRendering(rend),
mOldFarClip(0), mOldFarClip2(0),
mWaterTimer(0.f)
{
mSky = rend->getSkyManager();
sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty<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;
mIsUnderwater = false;
@ -40,7 +57,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
mWater->setCastShadows(false);
mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
mWaterNode->setPosition(0, mTop, 0);
mReflectionCamera = mSceneManager->createCamera("ReflectionCamera");
@ -53,27 +69,36 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
applyRTT();
applyVisibilityMask();
createMaterial();
mWater->setMaterial(mMaterial);
mUnderwaterEffect = Settings::Manager::getBool("underwater effect", "Water");
Ogre::Entity* underwaterDome = mSceneManager->createEntity ("underwater_dome.mesh");
underwaterDome->setRenderQueueGroup (RQG_UnderWater);
mUnderwaterDome = mSceneManager->getRootSceneNode ()->createChildSceneNode ();
mUnderwaterDome->attachObject (underwaterDome);
mUnderwaterDome->setScale(10000,10000,10000);
mUnderwaterDome->setVisible(false);
underwaterDome->setMaterialName("Underwater_Dome");
mSceneManager->addRenderQueueListener(this);
assignTextures();
setHeight(mTop);
sh::MaterialInstance* m = sh::Factory::getInstance ().getMaterialInstance ("Water");
m->setListener (this);
// ----------------------------------------------------------------------------------------------
// ---------------------------------- reflection debug overlay ----------------------------------
// ----------------------------------------------------------------------------------------------
/*
/*
if (Settings::Manager::getBool("shader", "Water"))
{
OverlayManager& mgr = OverlayManager::getSingleton();
Overlay* overlay;
// destroy if already exists
if (overlay = mgr.getByName("ReflectionDebugOverlay"))
if ((overlay = mgr.getByName("ReflectionDebugOverlay")))
mgr.destroy(overlay);
overlay = mgr.create("ReflectionDebugOverlay");
@ -85,18 +110,17 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName());
t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(mReflectionTexture->getName());
OverlayContainer* debugPanel;
// destroy container if exists
try
{
if (debugPanel =
if ((debugPanel =
static_cast<OverlayContainer*>(
mgr.getOverlayElement("Ogre/ReflectionDebugTexPanel"
)))
))))
mgr.destroyOverlayElement(debugPanel);
}
catch (Ogre::Exception&) {}
@ -110,13 +134,15 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
overlay->add2D(debugPanel);
overlay->show();
}
*/
*/
}
void Water::setActive(bool active)
{
mActive = active;
updateVisible();
sh::Factory::getInstance ().setSharedParameter ("waterEnabled", sh::makeProperty<sh::FloatValue> (new sh::FloatValue(active ? 1.0 : 0.0)));
}
Water::~Water()
@ -144,8 +170,14 @@ void Water::changeCell(const ESM::Cell* cell)
void Water::setHeight(const float height)
{
mTop = height;
mWaterPlane = Plane(Vector3::UNIT_Y, height);
// small error due to reflection texture size & reflection distortion
mErrorPlane = Plane(Vector3::UNIT_Y, height - 5);
mWaterNode->setPosition(0, height, 0);
sh::Factory::getInstance ().setSharedParameter ("waterLevel", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(height)));
}
void Water::toggle()
@ -158,36 +190,16 @@ void Water::checkUnderwater(float y)
{
if (!mActive)
{
mRendering->getCompositors()->setCompositorEnabled(mCompositorName, false);
return;
}
if ((mIsUnderwater && y > mTop) || !mWater->isVisible() || mCamera->getPolygonMode() != Ogre::PM_SOLID)
{
mRendering->getCompositors()->setCompositorEnabled(mCompositorName, false);
// tell the shader we are not underwater
Ogre::Pass* pass = mMaterial->getTechnique(0)->getPass(0);
if (pass->hasFragmentProgram() && pass->getFragmentProgramParameters()->_findNamedConstantDefinition("isUnderwater", false))
pass->getFragmentProgramParameters()->setNamedConstant("isUnderwater", Real(0));
mWater->setRenderQueueGroup(RQG_Water);
mIsUnderwater = false;
}
if (!mIsUnderwater && y < mTop && mWater->isVisible() && mCamera->getPolygonMode() == Ogre::PM_SOLID)
{
if (mUnderwaterEffect)
mRendering->getCompositors()->setCompositorEnabled(mCompositorName, true);
// tell the shader we are underwater
Ogre::Pass* pass = mMaterial->getTechnique(0)->getPass(0);
if (pass->hasFragmentProgram() && pass->getFragmentProgramParameters()->_findNamedConstantDefinition("isUnderwater", false))
pass->getFragmentProgramParameters()->setNamedConstant("isUnderwater", Real(1));
mWater->setRenderQueueGroup(RQG_UnderWater);
mIsUnderwater = true;
}
@ -211,12 +223,11 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt)
mReflectionCamera->setFOVy(mCamera->getFOVy());
mReflectionRenderActive = true;
/// \todo For some reason this camera is delayed for 1 frame, which causes ugly sky reflection behaviour..
/// to circumvent this we just scale the sky up, so it's not that noticable
/// \todo the reflection render (and probably all renderingmanager-updates) lag behind 1 camera frame for some reason
Vector3 pos = mCamera->getRealPosition();
pos.y = mTop*2 - pos.y;
mSky->setSkyPosition(pos);
mSky->scaleSky(mCamera->getFarClipDistance() / 5000.f);
mSky->scaleSky(mCamera->getFarClipDistance() / 50.f);
mReflectionCamera->enableReflection(mWaterPlane);
}
}
@ -233,48 +244,18 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt)
}
}
void Water::createMaterial()
{
if (mReflectionTarget == 0)
{
mMaterial = MaterialManager::getSingleton().getByName("Water_Fallback");
}
else
{
mMaterial = MaterialManager::getSingleton().getByName("Water");
mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(mReflectionTexture);
}
// these have to be set in code
std::string textureNames[32];
for (int i=0; i<32; ++i)
{
textureNames[i] = "textures\\water\\water" + StringConverter::toString(i, 2, '0') + ".dds";
}
Ogre::Technique* tech;
if (mReflectionTarget == 0)
tech = mMaterial->getTechnique(0);
else
tech = mMaterial->getTechnique(1);
tech->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2);
}
void Water::assignTextures()
{
if (Settings::Manager::getBool("shader", "Water"))
{
CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mRendering->getViewport())->getCompositor("gbuffer");
TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0);
TextureUnitState* tus = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState("refractionMap");
if (tus != 0)
tus->setTexture(colorTexture);
sh::Factory::getInstance ().setTextureAlias ("WaterRefraction", colorTexture->getName());
TexturePtr depthTexture = compositor->getTextureInstance("mrt_output", 1);
tus = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState("depthMap");
if (tus != 0)
tus->setTexture(depthTexture);
sh::Factory::getInstance ().setTextureAlias ("SceneDepth", depthTexture->getName());
}
}
@ -288,7 +269,7 @@ void Water::updateVisible()
{
mWater->setVisible(mToggled && mActive);
if (mReflectionTarget)
mReflectionTarget->setActive(mToggled && mActive && !mIsUnderwater);
mReflectionTarget->setActive(mToggled && mActive);
}
void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation)
@ -296,22 +277,46 @@ void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &in
// We don't want the sky to get clipped by custom near clip plane (the water plane)
if (queueGroupId < 20 && mReflectionRenderActive)
{
mOldFarClip = mReflectionCamera->getFarClipDistance ();
mReflectionCamera->disableCustomNearClipPlane();
mReflectionCamera->setFarClipDistance (1000000000);
Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS());
}
else if (queueGroupId == RQG_UnderWater)
{/*
mOldFarClip2 = mCamera->getFarClipDistance ();
mCamera->setFarClipDistance (1000000000);
Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS());
*/}
}
void Water::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation)
{
if (queueGroupId < 20 && mReflectionRenderActive)
{
mReflectionCamera->enableCustomNearClipPlane(mWaterPlane);
mReflectionCamera->setFarClipDistance (mOldFarClip);
if (!mIsUnderwater)
mReflectionCamera->enableCustomNearClipPlane(mErrorPlane);
Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS());
}
if (queueGroupId == RQG_UnderWater)
{
/*
mCamera->setFarClipDistance (mOldFarClip2);
Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS());
*/}
}
void Water::update()
void Water::update(float dt)
{
Ogre::Vector3 pos = mCamera->getDerivedPosition ();
pos.y = -mWaterPlane.d;
mUnderwaterDome->setPosition (pos);
mWaterTimer += dt / 30.0 * MWBase::Environment::get().getWorld()->getTimeScaleFactor();
sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty<sh::FloatValue>(new sh::FloatValue(mWaterTimer)));
mRendering->getSkyManager ()->setGlareEnabled (!mIsUnderwater);
}
void Water::applyRTT()
@ -336,14 +341,14 @@ void Water::applyRTT()
vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f));
vp->setShadowsEnabled(false);
// use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain)
//vp->setMaterialScheme("Fallback");
vp->setMaterialScheme("water_reflection");
rtt->addListener(this);
rtt->setActive(true);
mReflectionTarget = rtt;
}
mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT";
sh::Factory::getInstance ().setTextureAlias ("WaterReflection", mReflectionTexture->getName());
}
}
void Water::applyVisibilityMask()
@ -386,7 +391,6 @@ void Water::processChangedSettings(const Settings::CategorySettingVector& settin
{
applyRTT();
applyVisibilityMask();
createMaterial();
mWater->setMaterial(mMaterial);
assignTextures();
}
@ -394,4 +398,29 @@ void Water::processChangedSettings(const Settings::CategorySettingVector& settin
applyVisibilityMask();
}
void Water::requestedConfiguration (sh::MaterialInstance* m, const std::string& configuration)
{
}
void Water::createdConfiguration (sh::MaterialInstance* m, const std::string& configuration)
{
if (configuration == "local_map" || !Settings::Manager::getBool("shader", "Water"))
{
// for simple water, set animated texture names
// these have to be set in code
std::string textureNames[32];
for (int i=0; i<32; ++i)
{
textureNames[i] = "textures\\water\\water" + StringConverter::toString(i, 2, '0') + ".dds";
}
Ogre::Technique* t = static_cast<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

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

@ -181,16 +181,15 @@ namespace MWWorld
playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90;
Ogre::Quaternion quat = yawNode->getOrientation();
Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y);
Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y);
pm_ref.rightmove = -iter->second.x;
pm_ref.forwardmove = -iter->second.y;
pm_ref.upmove = iter->second.z;
pm_ref.rightmove = -iter->second.x;
pm_ref.forwardmove = -iter->second.y;
pm_ref.upmove = iter->second.z;
}
}

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

@ -22,3 +22,10 @@ endforeach (f)
endforeach (u)
source_group ("components\\${dir}" FILES ${files})
endmacro (add_component_dir)
macro (copy_all_files source_dir destination_dir files)
foreach (f ${files})
get_filename_component(filename ${f} NAME)
configure_file(${source_dir}/${f} ${destination_dir}/${filename} COPYONLY)
endforeach (f)
endmacro (copy_all_files)

@ -15,7 +15,6 @@ namespace Files
{
static const char* const openmwCfgFile = "openmw.cfg";
static const char* const pluginsCfgFile = "plugins.cfg";
const char* const mwToken = "?mw?";
const char* const localToken = "?local?";
@ -29,17 +28,6 @@ ConfigurationManager::ConfigurationManager()
boost::filesystem::create_directories(mFixedPath.getUserPath());
mPluginsCfgPath = mFixedPath.getLocalPath() / pluginsCfgFile;
if (!boost::filesystem::is_regular_file(mPluginsCfgPath))
{
mPluginsCfgPath = mFixedPath.getGlobalPath() / pluginsCfgFile;
if (!boost::filesystem::is_regular_file(mPluginsCfgPath))
{
std::cerr << "Failed to find " << pluginsCfgFile << " file!" << std::endl;
mPluginsCfgPath.clear();
}
}
mLogPath = mFixedPath.getUserPath();
}
@ -164,11 +152,6 @@ const boost::filesystem::path& ConfigurationManager::getInstallPath() const
return mFixedPath.getInstallPath();
}
const boost::filesystem::path& ConfigurationManager::getPluginsConfigPath() const
{
return mPluginsCfgPath;
}
const boost::filesystem::path& ConfigurationManager::getLogPath() const
{
return mLogPath;

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

@ -33,6 +33,11 @@
#include <OgreSubMesh.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/nifoverrides/nifoverrides.hpp>
@ -207,139 +212,82 @@ void NIFLoader::createMaterial(const Ogre::String &name,
const Ogre::Vector3 &emissive,
float glossiness, float alpha,
int alphaFlags, float alphaTest,
const Ogre::String &texName)
const Ogre::String &texName, bool vertexColor)
{
Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(name, resourceGroup);
if (texName.empty())
return;
//Hardware Skinning code, textures may be the wrong color if enabled
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)));
/* if(!mSkel.isNull()){
material->removeAllTechniques();
instance->setProperty ("diffuse", sh::makeProperty<sh::Vector4> (
new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha)));
Ogre::Technique* tech = material->createTechnique();
//tech->setSchemeName("blahblah");
Pass* pass = tech->createPass();
pass->setVertexProgram("Ogre/BasicVertexPrograms/AmbientOneTexture");*/
instance->setProperty ("specular", sh::makeProperty<sh::Vector4> (
new sh::Vector4(specular.x, specular.y, specular.z, glossiness)));
instance->setProperty ("emissive", sh::makeProperty<sh::Vector3> (
new sh::Vector3(emissive.x, emissive.y, emissive.z)));
// This assigns the texture to this material. If the texture name is
// a file name, and this file exists (in a resource directory), it
// will automatically be loaded when needed. If not (such as for
// internal NIF textures that we might support later), we should
// already have inserted a manual loader for the texture.
instance->setProperty ("diffuseMap", sh::makeProperty(texName));
if (vertexColor)
instance->setProperty ("has_vertex_colour", sh::makeProperty<sh::BooleanValue>(new sh::BooleanValue(true)));
if (!texName.empty())
// Add transparency if NiAlphaProperty was present
if (alphaFlags != -1)
{
Ogre::Pass *pass = material->getTechnique(0)->getPass(0);
/*TextureUnitState *txt =*/
pass->createTextureUnitState(texName);
pass->setVertexColourTracking(Ogre::TVC_DIFFUSE);
// As of yet UNTESTED code from Chris:
/*pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC);
pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL);
pass->setDepthCheckEnabled(true);
// Add transparency if NiAlphaProperty was present
if (alphaFlags != -1)
// The 237 alpha flags are by far the most common. Check
// NiAlphaProperty in nif/property.h if you need to decode
// other values. 237 basically means normal transparencly.
if (alphaFlags == 237)
{
std::cout << "Alpha flags set!" << endl;
if ((alphaFlags&1))
NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName);
if (result.first)
{
pass->setDepthWriteEnabled(false);
pass->setSceneBlending(getBlendFactor((alphaFlags>>1)&0xf),
getBlendFactor((alphaFlags>>5)&0xf));
instance->setProperty("alpha_rejection",
sh::makeProperty<sh::StringValue>(new sh::StringValue("greater_equal " + boost::lexical_cast<std::string>(result.second))));
}
else
pass->setDepthWriteEnabled(true);
if ((alphaFlags>>9)&1)
pass->setAlphaRejectSettings(getTestMode((alphaFlags>>10)&0x7),
alphaTest);
pass->setTransparentSortingEnabled(!((alphaFlags>>13)&1));
}
else
pass->setDepthWriteEnabled(true); */
// Add transparency if NiAlphaProperty was present
if (alphaFlags != -1)
{
// The 237 alpha flags are by far the most common. Check
// NiAlphaProperty in nif/property.h if you need to decode
// other values. 237 basically means normal transparencly.
if (alphaFlags == 237)
{
NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName);
if (result.first)
{
pass->setAlphaRejectFunction(Ogre::CMPF_GREATER_EQUAL);
pass->setAlphaRejectValue(result.second);
}
else
{
// Enable transparency
pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
//pass->setDepthCheckEnabled(false);
pass->setDepthWriteEnabled(false);
//std::cout << "alpha 237; material: " << name << " texName: " << texName << std::endl;
}
// Enable transparency
instance->setProperty("scene_blend", sh::makeProperty<sh::StringValue>(new sh::StringValue("alpha_blend")));
instance->setProperty("depth_write", sh::makeProperty<sh::StringValue>(new sh::StringValue("off")));
}
else
warn("Unhandled alpha setting for texture " + texName);
}
else
{
material->getTechnique(0)->setShadowCasterMaterial("depth_shadow_caster_noalpha");
}
warn("Unhandled alpha setting for texture " + texName);
}
else
instance->getMaterial ()->setShadowCasterMaterial ("openmw_shadowcaster_noalpha");
if (Settings::Manager::getBool("enabled", "Shadows"))
{
bool split = Settings::Manager::getBool("split", "Shadows");
const int numsplits = 3;
for (int i = 0; i < (split ? numsplits : 1); ++i)
{
Ogre::TextureUnitState* tu = material->getTechnique(0)->getPass(0)->createTextureUnitState();
tu->setName("shadowMap" + Ogre::StringConverter::toString(i));
tu->setContentType(Ogre::TextureUnitState::CONTENT_SHADOW);
tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_BORDER);
tu->setTextureBorderColour(Ogre::ColourValue::White);
}
}
// As of yet UNTESTED code from Chris:
/*pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC);
pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL);
pass->setDepthCheckEnabled(true);
if (Settings::Manager::getBool("shaders", "Objects"))
// Add transparency if NiAlphaProperty was present
if (alphaFlags != -1)
{
material->getTechnique(0)->getPass(0)->setVertexProgram("main_vp");
material->getTechnique(0)->getPass(0)->setFragmentProgram("main_fp");
std::cout << "Alpha flags set!" << endl;
if ((alphaFlags&1))
{
pass->setDepthWriteEnabled(false);
pass->setSceneBlending(getBlendFactor((alphaFlags>>1)&0xf),
getBlendFactor((alphaFlags>>5)&0xf));
}
else
pass->setDepthWriteEnabled(true);
material->getTechnique(0)->getPass(0)->setFog(true); // force-disable fixed function fog, it is calculated in shader
}
if ((alphaFlags>>9)&1)
pass->setAlphaRejectSettings(getTestMode((alphaFlags>>10)&0x7),
alphaTest);
// 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
pass->setTransparentSortingEnabled(!((alphaFlags>>13)&1));
}
// Add material bells and whistles
material->setAmbient(ambient[0], ambient[1], ambient[2]);
material->setDiffuse(diffuse[0], diffuse[1], diffuse[2], alpha);
material->setSpecular(specular[0], specular[1], specular[2], alpha);
material->setSelfIllumination(emissive[0], emissive[1], emissive[2]);
material->setShininess(glossiness);
else
pass->setDepthWriteEnabled(true); */
}
// Takes a name and adds a unique part to it. This is just used to
@ -642,6 +590,8 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
NiTexturingProperty *t = NULL;
NiMaterialProperty *m = NULL;
NiAlphaProperty *a = NULL;
// can't make any sense of these values, so ignoring them for now
//NiVertexColorProperty *v = NULL;
// Scan the property list for material information
PropertyList &list = shape->props;
@ -659,6 +609,8 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
m = static_cast<NiMaterialProperty*>(pr);
else if (pr->recType == RC_NiAlphaProperty)
a = static_cast<NiAlphaProperty*>(pr);
//else if (pr->recType == RC_NiVertexColorProperty)
//v = static_cast<NiVertexColorProperty*>(pr);
}
// Texture
@ -727,7 +679,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
{
//std::cout << "new";
createMaterial(material, d->ambient, d->diffuse, d->specular, d->emissive,
d->glossiness, d->alpha, alphaFlags, alphaTest, texName);
d->glossiness, d->alpha, alphaFlags, alphaTest, texName, shape->data->colors.size() != 0);
MaterialMap.insert(std::make_pair(texName,material));
}
}
@ -737,7 +689,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
// material for it.
const Ogre::Vector3 zero(0.0f), one(1.0f);
createMaterial(material, one, one, zero, zero, 0.0f, 1.0f,
alphaFlags, alphaTest, texName);
alphaFlags, alphaTest, texName, shape->data->colors.size() != 0);
}
}
} // End of material block, if(!hidden) ...

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

1
extern/shiny vendored

@ -0,0 +1 @@
Subproject commit 41245d1361bc0242e5d2c2313caffb711207e5fc

@ -1,16 +1,50 @@
project(resources)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/caustic_0.png "${OpenMW_BINARY_DIR}/resources/water/caustic_0.png" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/underwater.cg "${OpenMW_BINARY_DIR}/resources/water/underwater.cg" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/perlinvolume.dds "${OpenMW_BINARY_DIR}/resources/water/perlinvolume.dds" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.compositor "${OpenMW_BINARY_DIR}/resources/water/water.compositor" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.material "${OpenMW_BINARY_DIR}/resources/water/water.material" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/WaterNormal2.tga "${OpenMW_BINARY_DIR}/resources/water/WaterNormal2.tga" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.cg "${OpenMW_BINARY_DIR}/resources/water/water.cg" COPYONLY)
set(WATER_FILES
underwater_dome.mesh
water_nm.png
)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.cg "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.cg" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.material "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.material" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.compositor "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.compositor" COPYONLY)
set(GBUFFER_FILES
gbuffer.compositor
)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/shadows/depthshadowcaster.material "${OpenMW_BINARY_DIR}/resources/shadows/depthshadowcaster.material" COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/shadows/depthshadowcaster.cg "${OpenMW_BINARY_DIR}/resources/shadows/depthshadowcaster.cg" COPYONLY)
set(MATERIAL_FILES
atmosphere.shader
atmosphere.shaderset
clouds.shader
clouds.shaderset
core.h
moon.shader
moon.shaderset
objects.mat
objects.shader
objects.shaderset
openmw.configuration
quad2.shader
quad.mat
quad.shader
quad.shaderset
shadowcaster.mat
shadowcaster.shader
shadowcaster.shaderset
shadows.h
sky.mat
stars.shader
stars.shaderset
sun.shader
sun.shaderset
terrain.shader
terrain.shaderset
underwater.h
water.mat
water.shader
water.shaderset
)
copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/water "${OpenMW_BINARY_DIR}/resources/water/" "${WATER_FILES}")
copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer "${OpenMW_BINARY_DIR}/resources/gbuffer/" "${GBUFFER_FILES}")
copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/materials "${OpenMW_BINARY_DIR}/resources/materials/" "${MATERIAL_FILES}")

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

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

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

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

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

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

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

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

@ -0,0 +1,52 @@
#include "core.h"
#define MRT @shGlobalSettingBool(mrt_output)
#ifdef SH_VERTEX_SHADER
SH_BEGIN_PROGRAM
shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix)
shVertexInput(float2, uv0)
shOutput(float2, UV)
SH_START_PROGRAM
{
shOutputPosition = shMatrixMult(wvp, shInputPosition);
UV = uv0;
}
#else
SH_BEGIN_PROGRAM
shSampler2D(diffuseMap)
shInput(float2, UV)
#if MRT
shDeclareMrtOutput(1)
#endif
shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour)
shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour)
shUniform(float4, atmosphereColour) @shSharedParameter(atmosphereColour)
SH_START_PROGRAM
{
float4 tex = shSample(diffuseMap, UV);
shOutputColour(0) = float4(materialEmissive.xyz, 1) * tex;
// use a circle for the alpha (compute UV distance to center)
// looks a bit bad because it's not filtered on the edges,
// but cheaper than a seperate alpha texture.
float sqrUVdist = pow(UV.x-0.5,2) + pow(UV.y-0.5, 2);
shOutputColour(0).a = materialDiffuse.a * (sqrUVdist >= 0.24 ? 0 : 1);
shOutputColour(0).rgb += (1-tex.a) * shOutputColour(0).a * atmosphereColour.rgb; //fill dark side of moon with atmosphereColour
shOutputColour(0).rgb += (1-materialDiffuse.a) * atmosphereColour.rgb; //fade bump
#if MRT
shOutputColour(1) = float4(1,1,1,1);
#endif
}
#endif

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -0,0 +1,103 @@
material openmw_moon
{
allow_fixed_function false
pass
{
vertex_program moon_vertex
fragment_program moon_fragment
polygon_mode_overrideable off
depth_write off
depth_check off
scene_blend alpha_blend
texture_unit diffuseMap
{
texture_alias $texture
}
}
}
material openmw_clouds
{
allow_fixed_function false
pass
{
vertex_program clouds_vertex
fragment_program clouds_fragment
polygon_mode_overrideable off
scene_blend alpha_blend
depth_write off
// second diffuse map is used for weather transitions
texture_unit diffuseMap1
{
texture_alias cloud_texture_1
}
texture_unit diffuseMap2
{
texture_alias cloud_texture_2
}
}
}
material openmw_atmosphere
{
allow_fixed_function false
pass
{
vertex_program atmosphere_vertex
fragment_program atmosphere_fragment
polygon_mode_overrideable off
scene_blend alpha_blend
depth_write off
}
}
material openmw_stars
{
allow_fixed_function false
pass
{
vertex_program stars_vertex
fragment_program stars_fragment
polygon_mode_overrideable off
depth_check off
depth_write off
scene_blend alpha_blend
texture_unit diffuseMap
{
direct_texture $texture
}
}
}
// used for both sun and sun glare
material openmw_sun
{
allow_fixed_function false
pass
{
vertex_program sun_vertex
fragment_program sun_fragment
polygon_mode_overrideable off
depth_check off
depth_write off
scene_blend alpha_blend
texture_unit diffuseMap
{
direct_texture $texture
}
}
}

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

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

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

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

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

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

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

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

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

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

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

@ -1,7 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<Property key="ButtonAutoWidth" value="true"/>
@ -100,6 +103,12 @@
</Widget>
<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">
<Property key="Caption" value="Show frames per second"/>
</Widget>
@ -179,6 +188,55 @@
<Widget type="Button" skin="MW_Button" position="4 56 34 24" align="Left Top" name="ReflectTerrainButton"/>
</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>

@ -322,6 +322,80 @@
</Child>
</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">
<Property key="FontName" value = "Default" />
<Property key="TextAlign" value = "ALIGN_CENTER" />

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

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

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

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

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

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

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

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

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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

@ -9,7 +9,10 @@
#include "OgreTexture.h"
#include "OgreHardwarePixelBuffer.h"
#include <boost/filesystem.hpp>
#include <cassert>
#include <cstdlib>
#include <stdexcept>
using namespace Ogre;
@ -70,7 +73,6 @@ float OgreRenderer::getFPS()
}
void OgreRenderer::configure(const std::string &logPath,
const std::string &pluginCfg,
const std::string& renderSystem,
bool _logging)
{
@ -86,13 +88,41 @@ void OgreRenderer::configure(const std::string &logPath,
// Disable logging
log->setDebugOutputEnabled(false);
#if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) || defined(ENABLE_PLUGIN_CgProgramManager) || defined(ENABLE_PLUGIN_OctreeSceneManager) || defined(ENABLE_PLUGIN_ParticleFX)
mRoot = new Root("", "", "");
#if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) || defined(ENABLE_PLUGIN_CgProgramManager) || defined(ENABLE_PLUGIN_OctreeSceneManager) || defined(ENABLE_PLUGIN_ParticleFX)
loadPlugins();
#else
mRoot = new Root(pluginCfg, "", "");
#endif
std::string pluginDir;
const char* pluginEnv = getenv("OPENMW_OGRE_PLUGIN_DIR");
if (pluginEnv)
pluginDir = pluginEnv;
else
{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
pluginDir = ".\\";
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
pluginDir = OGRE_PLUGIN_DIR;
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
pluginDir = OGRE_PLUGIN_DIR_REL;
#endif
}
std::string glPlugin = std::string(pluginDir) + "/RenderSystem_GL" + OGRE_PLUGIN_DEBUG_SUFFIX;
if (boost::filesystem::exists(glPlugin + ".so") || boost::filesystem::exists(glPlugin + ".dll"))
mRoot->loadPlugin (glPlugin);
std::string dxPlugin = std::string(pluginDir) + "/RenderSystem_Direct3D9" + OGRE_PLUGIN_DEBUG_SUFFIX;
if (boost::filesystem::exists(dxPlugin + ".so") || boost::filesystem::exists(dxPlugin + ".dll"))
mRoot->loadPlugin (dxPlugin);
std::string cgPlugin = std::string(pluginDir) + "/Plugin_CgProgramManager" + OGRE_PLUGIN_DEBUG_SUFFIX;
if (boost::filesystem::exists(cgPlugin + ".so") || boost::filesystem::exists(cgPlugin + ".dll"))
mRoot->loadPlugin (cgPlugin);
RenderSystem* rs = mRoot->getRenderSystemByName(renderSystem);
if (rs == 0)
throw std::runtime_error ("RenderSystem with name " + renderSystem + " not found, make sure the plugins are loaded");

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

Loading…
Cancel
Save