mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-22 16:53:54 +00:00
Merge remote branch 'zini/master' into sound
This commit is contained in:
commit
0b5b2e9260
73 changed files with 1585 additions and 570 deletions
|
@ -346,7 +346,10 @@ if(WIN32)
|
||||||
FILE(GLOB files "${OpenMW_BINARY_DIR}/Release/*.*")
|
FILE(GLOB files "${OpenMW_BINARY_DIR}/Release/*.*")
|
||||||
INSTALL(FILES ${files} DESTINATION ".")
|
INSTALL(FILES ${files} DESTINATION ".")
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg")
|
||||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/readme.txt" DESTINATION ".")
|
INSTALL(FILES
|
||||||
|
"${OpenMW_SOURCE_DIR}/readme.txt"
|
||||||
|
"${OpenMW_BINARY_DIR}/settings-default.cfg"
|
||||||
|
DESTINATION ".")
|
||||||
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
|
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
|
||||||
|
|
||||||
SET(CPACK_GENERATOR "NSIS")
|
SET(CPACK_GENERATOR "NSIS")
|
||||||
|
@ -356,8 +359,12 @@ if(WIN32)
|
||||||
SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})
|
SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})
|
||||||
SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO})
|
SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO})
|
||||||
SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
|
SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
|
||||||
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW;esmtool;Esmtool;omwlauncher;OpenMW Launcher")
|
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW;omwlauncher;OpenMW Launcher")
|
||||||
set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Readme.lnk' '\$INSTDIR\\\\readme.txt'")
|
SET(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Readme.lnk' '\$INSTDIR\\\\readme.txt'")
|
||||||
|
SET(CPACK_NSIS_DELETE_ICONS_EXTRA "
|
||||||
|
!insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
|
||||||
|
Delete \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Readme.lnk\\\"
|
||||||
|
")
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/readme.txt")
|
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/readme.txt")
|
||||||
SET(CPACK_RESOURCE_FILE_LICENSE "${OpenMW_SOURCE_DIR}/GPL3.txt")
|
SET(CPACK_RESOURCE_FILE_LICENSE "${OpenMW_SOURCE_DIR}/GPL3.txt")
|
||||||
SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
||||||
|
|
|
@ -55,7 +55,7 @@ add_openmw_dir (mwclass
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwmechanics
|
add_openmw_dir (mwmechanics
|
||||||
mechanicsmanager stat creaturestats magiceffects movement actors
|
mechanicsmanager stat creaturestats magiceffects movement actors drawstate
|
||||||
)
|
)
|
||||||
|
|
||||||
# Main executable
|
# Main executable
|
||||||
|
|
|
@ -361,6 +361,7 @@ void OMW::Engine::go()
|
||||||
|
|
||||||
addResourcesDirectory(mResDir / "mygui");
|
addResourcesDirectory(mResDir / "mygui");
|
||||||
addResourcesDirectory(mResDir / "water");
|
addResourcesDirectory(mResDir / "water");
|
||||||
|
addResourcesDirectory(mResDir / "gbuffer");
|
||||||
|
|
||||||
// Create the window
|
// Create the window
|
||||||
mOgre->createWindow("OpenMW");
|
mOgre->createWindow("OpenMW");
|
||||||
|
|
|
@ -70,6 +70,14 @@ namespace MWClass
|
||||||
return ref->base->script;
|
return ref->base->script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Apparatus::getValue (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Apparatus>();
|
||||||
|
|
||||||
|
return ref->base->data.value;
|
||||||
|
}
|
||||||
|
|
||||||
void Apparatus::registerSelf()
|
void Apparatus::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Apparatus);
|
boost::shared_ptr<Class> instance (new Apparatus);
|
||||||
|
|
|
@ -25,6 +25,9 @@ namespace MWClass
|
||||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
|
virtual int getValue (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const;
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
|
@ -160,6 +160,14 @@ namespace MWClass
|
||||||
return ESM::Skill::HeavyArmor;
|
return ESM::Skill::HeavyArmor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Armor::getValue (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Armor>();
|
||||||
|
|
||||||
|
return ref->base->data.value;
|
||||||
|
}
|
||||||
|
|
||||||
void Armor::registerSelf()
|
void Armor::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Armor);
|
boost::shared_ptr<Class> instance (new Armor);
|
||||||
|
|
|
@ -40,6 +40,9 @@ namespace MWClass
|
||||||
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
|
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
|
||||||
/// no such skill.
|
/// no such skill.
|
||||||
|
|
||||||
|
virtual int getValue (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
|
|
@ -72,6 +72,14 @@ namespace MWClass
|
||||||
return ref->base->script;
|
return ref->base->script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Book::getValue (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Book>();
|
||||||
|
|
||||||
|
return ref->base->data.value;
|
||||||
|
}
|
||||||
|
|
||||||
void Book::registerSelf()
|
void Book::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Book);
|
boost::shared_ptr<Class> instance (new Book);
|
||||||
|
|
|
@ -25,6 +25,9 @@ namespace MWClass
|
||||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
|
virtual int getValue (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
|
|
@ -123,6 +123,14 @@ namespace MWClass
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Clothing::getValue (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Clothing>();
|
||||||
|
|
||||||
|
return ref->base->data.value;
|
||||||
|
}
|
||||||
|
|
||||||
void Clothing::registerSelf()
|
void Clothing::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Clothing);
|
boost::shared_ptr<Class> instance (new Clothing);
|
||||||
|
|
|
@ -34,6 +34,9 @@ namespace MWClass
|
||||||
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
|
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
|
||||||
/// no such skill.
|
/// no such skill.
|
||||||
|
|
||||||
|
virtual int getValue (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
|
|
@ -68,6 +68,14 @@ namespace MWClass
|
||||||
return ref->base->script;
|
return ref->base->script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Ingredient::getValue (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Ingredient>();
|
||||||
|
|
||||||
|
return ref->base->data.value;
|
||||||
|
}
|
||||||
|
|
||||||
void Ingredient::registerSelf()
|
void Ingredient::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Ingredient);
|
boost::shared_ptr<Class> instance (new Ingredient);
|
||||||
|
|
|
@ -25,6 +25,9 @@ namespace MWClass
|
||||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
|
virtual int getValue (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
|
|
@ -110,6 +110,14 @@ namespace MWClass
|
||||||
return std::make_pair (slots, false);
|
return std::make_pair (slots, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Light::getValue (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Light>();
|
||||||
|
|
||||||
|
return ref->base->data.value;
|
||||||
|
}
|
||||||
|
|
||||||
void Light::registerSelf()
|
void Light::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Light);
|
boost::shared_ptr<Class> instance (new Light);
|
||||||
|
|
|
@ -34,6 +34,9 @@ namespace MWClass
|
||||||
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
||||||
/// stay stacked when equipped?
|
/// stay stacked when equipped?
|
||||||
|
|
||||||
|
virtual int getValue (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
|
|
@ -81,6 +81,14 @@ namespace MWClass
|
||||||
return std::make_pair (slots, false);
|
return std::make_pair (slots, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Lockpick::getValue (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Tool>();
|
||||||
|
|
||||||
|
return ref->base->data.value;
|
||||||
|
}
|
||||||
|
|
||||||
void Lockpick::registerSelf()
|
void Lockpick::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Lockpick);
|
boost::shared_ptr<Class> instance (new Lockpick);
|
||||||
|
|
|
@ -29,6 +29,9 @@ namespace MWClass
|
||||||
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
||||||
/// stay stacked when equipped?
|
/// stay stacked when equipped?
|
||||||
|
|
||||||
|
virtual int getValue (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
|
|
@ -70,6 +70,14 @@ namespace MWClass
|
||||||
return ref->base->script;
|
return ref->base->script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Miscellaneous::getValue (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Miscellaneous>();
|
||||||
|
|
||||||
|
return ref->base->data.value;
|
||||||
|
}
|
||||||
|
|
||||||
void Miscellaneous::registerSelf()
|
void Miscellaneous::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Miscellaneous);
|
boost::shared_ptr<Class> instance (new Miscellaneous);
|
||||||
|
|
|
@ -25,6 +25,9 @@ namespace MWClass
|
||||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
|
virtual int getValue (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
|
|
@ -70,6 +70,14 @@ namespace MWClass
|
||||||
return ref->base->script;
|
return ref->base->script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Potion::getValue (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Potion>();
|
||||||
|
|
||||||
|
return ref->base->data.value;
|
||||||
|
}
|
||||||
|
|
||||||
void Potion::registerSelf()
|
void Potion::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Potion);
|
boost::shared_ptr<Class> instance (new Potion);
|
||||||
|
|
|
@ -25,6 +25,9 @@ namespace MWClass
|
||||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
|
virtual int getValue (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
|
|
@ -80,6 +80,14 @@ namespace MWClass
|
||||||
return std::make_pair (slots, false);
|
return std::make_pair (slots, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Probe::getValue (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Probe>();
|
||||||
|
|
||||||
|
return ref->base->data.value;
|
||||||
|
}
|
||||||
|
|
||||||
void Probe::registerSelf()
|
void Probe::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Probe);
|
boost::shared_ptr<Class> instance (new Probe);
|
||||||
|
|
|
@ -29,6 +29,9 @@ namespace MWClass
|
||||||
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
///< \return first: Return IDs of the slot this object can be equipped in; second: can object
|
||||||
/// stay stacked when equipped?
|
/// stay stacked when equipped?
|
||||||
|
|
||||||
|
virtual int getValue (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
|
|
@ -70,6 +70,14 @@ namespace MWClass
|
||||||
return ref->base->script;
|
return ref->base->script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Repair::getValue (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Repair>();
|
||||||
|
|
||||||
|
return ref->base->data.value;
|
||||||
|
}
|
||||||
|
|
||||||
void Repair::registerSelf()
|
void Repair::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Repair);
|
boost::shared_ptr<Class> instance (new Repair);
|
||||||
|
|
|
@ -25,6 +25,9 @@ namespace MWClass
|
||||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return name of the script attached to ptr
|
///< Return name of the script attached to ptr
|
||||||
|
|
||||||
|
virtual int getValue (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
|
|
@ -139,6 +139,14 @@ namespace MWClass
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Weapon::getValue (const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Weapon>();
|
||||||
|
|
||||||
|
return ref->base->data.value;
|
||||||
|
}
|
||||||
|
|
||||||
void Weapon::registerSelf()
|
void Weapon::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Weapon);
|
boost::shared_ptr<Class> instance (new Weapon);
|
||||||
|
|
|
@ -40,6 +40,9 @@ namespace MWClass
|
||||||
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
|
/// Return the index of the skill this item corresponds to when equiopped or -1, if there is
|
||||||
/// no such skill.
|
/// no such skill.
|
||||||
|
|
||||||
|
virtual int getValue (const MWWorld::Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
virtual std::string getUpSoundId (const MWWorld::Ptr& ptr, const MWWorld::Environment& environment) const;
|
||||||
|
|
|
@ -65,6 +65,8 @@ namespace MWInput
|
||||||
A_QuickLoad,
|
A_QuickLoad,
|
||||||
A_QuickMenu,
|
A_QuickMenu,
|
||||||
A_GameMenu,
|
A_GameMenu,
|
||||||
|
A_ToggleWeapon,
|
||||||
|
A_ToggleSpell,
|
||||||
|
|
||||||
A_LAST // Marker for the last item
|
A_LAST // Marker for the last item
|
||||||
};
|
};
|
||||||
|
@ -86,6 +88,38 @@ namespace MWInput
|
||||||
|
|
||||||
/* InputImpl Methods */
|
/* InputImpl Methods */
|
||||||
|
|
||||||
|
void toggleSpell()
|
||||||
|
{
|
||||||
|
DrawState state = player.getDrawState();
|
||||||
|
if(state == DrawState_Weapon || state == DrawState_Nothing)
|
||||||
|
{
|
||||||
|
player.setDrawState(DrawState_Spell);
|
||||||
|
std::cout << "Player has now readied his hands for spellcasting!\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player.setDrawState(DrawState_Nothing);
|
||||||
|
std::cout << "Player does not have any kind of attack ready now.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleWeapon()
|
||||||
|
{
|
||||||
|
DrawState state = player.getDrawState();
|
||||||
|
if(state == DrawState_Spell || state == DrawState_Nothing)
|
||||||
|
{
|
||||||
|
player.setDrawState(DrawState_Weapon);
|
||||||
|
std::cout << "Player is now drawing his weapon.\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player.setDrawState(DrawState_Nothing);
|
||||||
|
std::cout << "Player does not have any kind of attack ready now.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void screenshot()
|
void screenshot()
|
||||||
{
|
{
|
||||||
mEngine.screenshot();
|
mEngine.screenshot();
|
||||||
|
@ -197,7 +231,10 @@ namespace MWInput
|
||||||
"Auto Move");
|
"Auto Move");
|
||||||
disp->funcs.bind(A_ToggleWalk, boost::bind(&InputImpl::toggleWalking, this),
|
disp->funcs.bind(A_ToggleWalk, boost::bind(&InputImpl::toggleWalking, this),
|
||||||
"Toggle Walk/Run");
|
"Toggle Walk/Run");
|
||||||
|
disp->funcs.bind(A_ToggleWeapon,boost::bind(&InputImpl::toggleWeapon,this),
|
||||||
|
"Draw Weapon");
|
||||||
|
disp->funcs.bind(A_ToggleSpell,boost::bind(&InputImpl::toggleSpell,this),
|
||||||
|
"Ready hands");
|
||||||
// Add the exit listener
|
// Add the exit listener
|
||||||
ogre.getRoot()->addFrameListener(&exit);
|
ogre.getRoot()->addFrameListener(&exit);
|
||||||
|
|
||||||
|
@ -242,6 +279,8 @@ namespace MWInput
|
||||||
disp->bind(A_AutoMove, KC_Z);
|
disp->bind(A_AutoMove, KC_Z);
|
||||||
disp->bind(A_ToggleSneak, KC_X);
|
disp->bind(A_ToggleSneak, KC_X);
|
||||||
disp->bind(A_ToggleWalk, KC_C);
|
disp->bind(A_ToggleWalk, KC_C);
|
||||||
|
disp->bind(A_ToggleWeapon,KC_F);
|
||||||
|
disp->bind(A_ToggleSpell,KC_R);
|
||||||
|
|
||||||
// Key bindings for polled keys
|
// Key bindings for polled keys
|
||||||
// NOTE: These keys are constantly being polled. Only add keys that must be checked each frame.
|
// NOTE: These keys are constantly being polled. Only add keys that must be checked each frame.
|
||||||
|
|
|
@ -17,9 +17,9 @@ namespace MWMechanics
|
||||||
|
|
||||||
void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused)
|
void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused)
|
||||||
{
|
{
|
||||||
if (!paused)
|
if (!paused && ptr.getRefData().getHandle()!="player")
|
||||||
MWWorld::Class::get (ptr).getInventoryStore (ptr).autoEquip (
|
MWWorld::Class::get (ptr).getInventoryStore (ptr).autoEquip (
|
||||||
MWWorld::Class::get (ptr).getNpcStats (ptr));
|
MWWorld::Class::get (ptr).getNpcStats (ptr), mEnvironment);
|
||||||
}
|
}
|
||||||
|
|
||||||
Actors::Actors (MWWorld::Environment& environment) : mEnvironment (environment), mDuration (0) {}
|
Actors::Actors (MWWorld::Environment& environment) : mEnvironment (environment), mDuration (0) {}
|
||||||
|
|
11
apps/openmw/mwmechanics/drawstate.hpp
Normal file
11
apps/openmw/mwmechanics/drawstate.hpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef GAME_MWMECHANICS_DRAWSTATE_H
|
||||||
|
#define GAME_MWMECHANICS_DRAWSTATE_H
|
||||||
|
|
||||||
|
enum DrawState
|
||||||
|
{
|
||||||
|
DrawState_Weapon = 0,
|
||||||
|
DrawState_Spell = 1,
|
||||||
|
DrawState_Nothing = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -4,13 +4,13 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "stat.hpp"
|
#include "stat.hpp"
|
||||||
|
#include "drawstate.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
/// \brief Additional stats for NPCs
|
/// \brief Additional stats for NPCs
|
||||||
///
|
///
|
||||||
/// For non-NPC-specific stats, see the CreatureStats struct.
|
/// For non-NPC-specific stats, see the CreatureStats struct.
|
||||||
|
|
||||||
struct NpcStats
|
struct NpcStats
|
||||||
{
|
{
|
||||||
// NPCs other than the player can only have one faction. But for the sake of consistency
|
// NPCs other than the player can only have one faction. But for the sake of consistency
|
||||||
|
@ -24,9 +24,10 @@ namespace MWMechanics
|
||||||
bool mRun;
|
bool mRun;
|
||||||
bool mSneak;
|
bool mSneak;
|
||||||
bool mCombat;
|
bool mCombat;
|
||||||
|
DrawState mDrawState;
|
||||||
|
|
||||||
NpcStats() : mForceRun (false), mForceSneak (false), mRun (false), mSneak (false),
|
NpcStats() : mForceRun (false), mForceSneak (false), mRun (false), mSneak (false),
|
||||||
mCombat (false) {}
|
mCombat (false) , mDrawState(DrawState_Nothing) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "creatureanimation.hpp"
|
#include "creatureanimation.hpp"
|
||||||
|
#include "renderconst.hpp"
|
||||||
|
|
||||||
#include "../mwworld/world.hpp"
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
|
@ -20,6 +21,28 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environme
|
||||||
std::string meshNumbered = mesh + getUniqueID(mesh) + ">|";
|
std::string meshNumbered = mesh + getUniqueID(mesh) + ">|";
|
||||||
NifOgre::NIFLoader::load(meshNumbered);
|
NifOgre::NIFLoader::load(meshNumbered);
|
||||||
base = mRend.getScene()->createEntity(meshNumbered);
|
base = mRend.getScene()->createEntity(meshNumbered);
|
||||||
|
base->setVisibilityFlags(RV_Actors);
|
||||||
|
|
||||||
|
bool transparent = false;
|
||||||
|
for (unsigned int i=0; i<base->getNumSubEntities(); ++i)
|
||||||
|
{
|
||||||
|
Ogre::MaterialPtr mat = base->getSubEntity(i)->getMaterial();
|
||||||
|
Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator();
|
||||||
|
while (techIt.hasMoreElements())
|
||||||
|
{
|
||||||
|
Ogre::Technique* tech = techIt.getNext();
|
||||||
|
Ogre::Technique::PassIterator passIt = tech->getPassIterator();
|
||||||
|
while (passIt.hasMoreElements())
|
||||||
|
{
|
||||||
|
Ogre::Pass* pass = passIt.getNext();
|
||||||
|
|
||||||
|
if (pass->getDepthWriteEnabled() == false)
|
||||||
|
transparent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||||
|
|
||||||
std::string meshZero = mesh + "0000>|";
|
std::string meshZero = mesh + "0000>|";
|
||||||
|
|
||||||
if((transformations = (NIFLoader::getSingletonPtr())->getAnim(meshZero))){
|
if((transformations = (NIFLoader::getSingletonPtr())->getAnim(meshZero))){
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/world.hpp"
|
#include "../mwworld/world.hpp"
|
||||||
#include "../mwgui/window_manager.hpp"
|
#include "../mwgui/window_manager.hpp"
|
||||||
|
#include "renderconst.hpp"
|
||||||
|
|
||||||
#include <OgreOverlayManager.h>
|
#include <OgreOverlayManager.h>
|
||||||
#include <OgreMaterialManager.h>
|
#include <OgreMaterialManager.h>
|
||||||
|
@ -223,7 +224,8 @@ void LocalMap::render(const float x, const float y,
|
||||||
vp->setOverlaysEnabled(false);
|
vp->setOverlaysEnabled(false);
|
||||||
vp->setShadowsEnabled(false);
|
vp->setShadowsEnabled(false);
|
||||||
vp->setBackgroundColour(ColourValue(0, 0, 0));
|
vp->setBackgroundColour(ColourValue(0, 0, 0));
|
||||||
//vp->setVisibilityMask( ... );
|
vp->setVisibilityMask(RV_Map);
|
||||||
|
vp->setMaterialScheme("Map");
|
||||||
|
|
||||||
rtt->update();
|
rtt->update();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "npcanimation.hpp"
|
#include "npcanimation.hpp"
|
||||||
#include "../mwworld/world.hpp"
|
#include "../mwworld/world.hpp"
|
||||||
|
#include "renderconst.hpp"
|
||||||
|
|
||||||
|
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
|
@ -65,6 +66,27 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O
|
||||||
NifOgre::NIFLoader::load(smodel);
|
NifOgre::NIFLoader::load(smodel);
|
||||||
|
|
||||||
base = mRend.getScene()->createEntity(smodel);
|
base = mRend.getScene()->createEntity(smodel);
|
||||||
|
base->setVisibilityFlags(RV_Actors);
|
||||||
|
bool transparent = false;
|
||||||
|
for (unsigned int i=0; i<base->getNumSubEntities(); ++i)
|
||||||
|
{
|
||||||
|
Ogre::MaterialPtr mat = base->getSubEntity(i)->getMaterial();
|
||||||
|
Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator();
|
||||||
|
while (techIt.hasMoreElements())
|
||||||
|
{
|
||||||
|
Ogre::Technique* tech = techIt.getNext();
|
||||||
|
Ogre::Technique::PassIterator passIt = tech->getPassIterator();
|
||||||
|
while (passIt.hasMoreElements())
|
||||||
|
{
|
||||||
|
Ogre::Pass* pass = passIt.getNext();
|
||||||
|
|
||||||
|
if (pass->getDepthWriteEnabled() == false)
|
||||||
|
transparent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||||
|
|
||||||
base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones
|
base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones
|
||||||
//stay in the same place when we skipanim, or open a gui window
|
//stay in the same place when we skipanim, or open a gui window
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
#include "renderconst.hpp"
|
||||||
|
|
||||||
using namespace MWRender;
|
using namespace MWRender;
|
||||||
|
|
||||||
|
@ -112,17 +113,49 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
||||||
bounds.scale(insert->getScale());
|
bounds.scale(insert->getScale());
|
||||||
mBounds[ptr.getCell()].merge(bounds);
|
mBounds[ptr.getCell()].merge(bounds);
|
||||||
|
|
||||||
|
bool transparent = false;
|
||||||
|
for (unsigned int i=0; i<ent->getNumSubEntities(); ++i)
|
||||||
|
{
|
||||||
|
Ogre::MaterialPtr mat = ent->getSubEntity(i)->getMaterial();
|
||||||
|
Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator();
|
||||||
|
while (techIt.hasMoreElements())
|
||||||
|
{
|
||||||
|
Ogre::Technique* tech = techIt.getNext();
|
||||||
|
Ogre::Technique::PassIterator passIt = tech->getPassIterator();
|
||||||
|
while (passIt.hasMoreElements())
|
||||||
|
{
|
||||||
|
Ogre::Pass* pass = passIt.getNext();
|
||||||
|
|
||||||
|
if (pass->getDepthWriteEnabled() == false)
|
||||||
|
transparent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects"))
|
if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects"))
|
||||||
{
|
{
|
||||||
insert->attachObject(ent);
|
insert->attachObject(ent);
|
||||||
|
|
||||||
ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); /// \todo config value
|
ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0);
|
||||||
|
ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc);
|
||||||
|
ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Ogre::StaticGeometry* sg = 0;
|
Ogre::StaticGeometry* sg = 0;
|
||||||
|
|
||||||
if (small)
|
/* if (transparent)
|
||||||
|
{
|
||||||
|
if( mStaticGeometryAlpha.find(ptr.getCell()) == mStaticGeometryAlpha.end())
|
||||||
|
{
|
||||||
|
uniqueID = uniqueID +1;
|
||||||
|
sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID));
|
||||||
|
mStaticGeometryAlpha[ptr.getCell()] = sg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sg = mStaticGeometryAlpha[ptr.getCell()];
|
||||||
|
}
|
||||||
|
else*/ if (small)
|
||||||
{
|
{
|
||||||
if( mStaticGeometrySmall.find(ptr.getCell()) == mStaticGeometrySmall.end())
|
if( mStaticGeometrySmall.find(ptr.getCell()) == mStaticGeometrySmall.end())
|
||||||
{
|
{
|
||||||
|
@ -130,7 +163,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
||||||
sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID));
|
sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID));
|
||||||
mStaticGeometrySmall[ptr.getCell()] = sg;
|
mStaticGeometrySmall[ptr.getCell()] = sg;
|
||||||
|
|
||||||
sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance")); /// \todo config value
|
sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sg = mStaticGeometrySmall[ptr.getCell()];
|
sg = mStaticGeometrySmall[ptr.getCell()];
|
||||||
|
@ -158,6 +191,10 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
||||||
|
|
||||||
sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale());
|
sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale());
|
||||||
|
|
||||||
|
sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics);
|
||||||
|
|
||||||
|
sg->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||||
|
|
||||||
mRenderer.getScene()->destroyEntity(ent);
|
mRenderer.getScene()->destroyEntity(ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,6 +288,13 @@ void Objects::removeCell(MWWorld::Ptr::CellStore* store)
|
||||||
mRenderer.getScene()->destroyStaticGeometry (sg);
|
mRenderer.getScene()->destroyStaticGeometry (sg);
|
||||||
sg = 0;
|
sg = 0;
|
||||||
}
|
}
|
||||||
|
/*if(mStaticGeometryAlpha.find(store) != mStaticGeometryAlpha.end())
|
||||||
|
{
|
||||||
|
Ogre::StaticGeometry* sg = mStaticGeometryAlpha[store];
|
||||||
|
mStaticGeometryAlpha.erase(store);
|
||||||
|
mRenderer.getScene()->destroyStaticGeometry (sg);
|
||||||
|
sg = 0;
|
||||||
|
}*/
|
||||||
|
|
||||||
if(mBounds.find(store) != mBounds.end())
|
if(mBounds.find(store) != mBounds.end())
|
||||||
mBounds.erase(store);
|
mBounds.erase(store);
|
||||||
|
@ -268,6 +312,11 @@ void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell)
|
||||||
Ogre::StaticGeometry* sg = mStaticGeometrySmall[&cell];
|
Ogre::StaticGeometry* sg = mStaticGeometrySmall[&cell];
|
||||||
sg->build();
|
sg->build();
|
||||||
}
|
}
|
||||||
|
/*if(mStaticGeometryAlpha.find(&cell) != mStaticGeometryAlpha.end())
|
||||||
|
{
|
||||||
|
Ogre::StaticGeometry* sg = mStaticGeometryAlpha[&cell];
|
||||||
|
sg->build();
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell)
|
Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell)
|
||||||
|
|
|
@ -15,6 +15,7 @@ class Objects{
|
||||||
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
|
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
|
||||||
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry;
|
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry;
|
||||||
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometrySmall;
|
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometrySmall;
|
||||||
|
//std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometryAlpha;
|
||||||
std::map<MWWorld::Ptr::CellStore *, Ogre::AxisAlignedBox> mBounds;
|
std::map<MWWorld::Ptr::CellStore *, Ogre::AxisAlignedBox> mBounds;
|
||||||
std::vector<std::string> mLights;
|
std::vector<std::string> mLights;
|
||||||
Ogre::SceneNode* mMwRoot;
|
Ogre::SceneNode* mMwRoot;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "occlusionquery.hpp"
|
#include "occlusionquery.hpp"
|
||||||
|
#include "renderconst.hpp"
|
||||||
|
|
||||||
#include <OgreRenderSystem.h>
|
#include <OgreRenderSystem.h>
|
||||||
#include <OgreRoot.h>
|
#include <OgreRoot.h>
|
||||||
|
@ -40,9 +41,6 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This means that everything up to RENDER_QUEUE_MAIN can occlude the objects that are tested
|
|
||||||
const int queue = RENDER_QUEUE_MAIN+1;
|
|
||||||
|
|
||||||
MaterialPtr matBase = MaterialManager::getSingleton().getByName("BaseWhiteNoLighting");
|
MaterialPtr matBase = MaterialManager::getSingleton().getByName("BaseWhiteNoLighting");
|
||||||
MaterialPtr matQueryArea = matBase->clone("QueryTotalPixels");
|
MaterialPtr matQueryArea = matBase->clone("QueryTotalPixels");
|
||||||
matQueryArea->setDepthWriteEnabled(false);
|
matQueryArea->setDepthWriteEnabled(false);
|
||||||
|
@ -65,14 +63,14 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
||||||
mBBQueryTotal->setDefaultDimensions(150, 150);
|
mBBQueryTotal->setDefaultDimensions(150, 150);
|
||||||
mBBQueryTotal->createBillboard(Vector3::ZERO);
|
mBBQueryTotal->createBillboard(Vector3::ZERO);
|
||||||
mBBQueryTotal->setMaterialName("QueryTotalPixels");
|
mBBQueryTotal->setMaterialName("QueryTotalPixels");
|
||||||
mBBQueryTotal->setRenderQueueGroup(queue+1);
|
mBBQueryTotal->setRenderQueueGroup(RQG_OcclusionQuery+1);
|
||||||
mBBNodeReal->attachObject(mBBQueryTotal);
|
mBBNodeReal->attachObject(mBBQueryTotal);
|
||||||
|
|
||||||
mBBQueryVisible = mRendering->getScene()->createBillboardSet(1);
|
mBBQueryVisible = mRendering->getScene()->createBillboardSet(1);
|
||||||
mBBQueryVisible->setDefaultDimensions(150, 150);
|
mBBQueryVisible->setDefaultDimensions(150, 150);
|
||||||
mBBQueryVisible->createBillboard(Vector3::ZERO);
|
mBBQueryVisible->createBillboard(Vector3::ZERO);
|
||||||
mBBQueryVisible->setMaterialName("QueryVisiblePixels");
|
mBBQueryVisible->setMaterialName("QueryVisiblePixels");
|
||||||
mBBQueryVisible->setRenderQueueGroup(queue+1);
|
mBBQueryVisible->setRenderQueueGroup(RQG_OcclusionQuery+1);
|
||||||
mBBNodeReal->attachObject(mBBQueryVisible);
|
mBBNodeReal->attachObject(mBBQueryVisible);
|
||||||
|
|
||||||
mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1);
|
mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1);
|
||||||
|
@ -80,7 +78,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
||||||
mBBQuerySingleObject->setDefaultDimensions(0.003, 0.003);
|
mBBQuerySingleObject->setDefaultDimensions(0.003, 0.003);
|
||||||
mBBQuerySingleObject->createBillboard(Vector3::ZERO);
|
mBBQuerySingleObject->createBillboard(Vector3::ZERO);
|
||||||
mBBQuerySingleObject->setMaterialName("QueryVisiblePixels");
|
mBBQuerySingleObject->setMaterialName("QueryVisiblePixels");
|
||||||
mBBQuerySingleObject->setRenderQueueGroup(queue);
|
mBBQuerySingleObject->setRenderQueueGroup(RQG_OcclusionQuery);
|
||||||
mObjectNode->attachObject(mBBQuerySingleObject);
|
mObjectNode->attachObject(mBBQuerySingleObject);
|
||||||
|
|
||||||
mRendering->getScene()->addRenderObjectListener(this);
|
mRendering->getScene()->addRenderObjectListener(this);
|
||||||
|
@ -153,7 +151,7 @@ void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocati
|
||||||
* this can happen for example if the object that is tested is outside of the view frustum
|
* this can happen for example if the object that is tested is outside of the view frustum
|
||||||
* to prevent this, check if the queries have been performed after everything has been rendered and if not, start them manually
|
* to prevent this, check if the queries have been performed after everything has been rendered and if not, start them manually
|
||||||
*/
|
*/
|
||||||
if (queueGroupId == RENDER_QUEUE_SKIES_LATE)
|
if (queueGroupId == RQG_SkiesLate)
|
||||||
{
|
{
|
||||||
if (mWasVisible == false && mDoQuery)
|
if (mWasVisible == false && mDoQuery)
|
||||||
{
|
{
|
||||||
|
|
62
apps/openmw/mwrender/renderconst.hpp
Normal file
62
apps/openmw/mwrender/renderconst.hpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#ifndef GAME_RENDER_CONST_H
|
||||||
|
#define GAME_RENDER_CONST_H
|
||||||
|
|
||||||
|
#include <OgreRenderQueue.h>
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
|
||||||
|
// Render queue groups
|
||||||
|
enum RenderQueueGroups
|
||||||
|
{
|
||||||
|
// Sky early (atmosphere, clouds, moons)
|
||||||
|
RQG_SkiesEarly = Ogre::RENDER_QUEUE_SKIES_EARLY,
|
||||||
|
|
||||||
|
RQG_Main = Ogre::RENDER_QUEUE_MAIN,
|
||||||
|
|
||||||
|
RQG_Water = Ogre::RENDER_QUEUE_7+1,
|
||||||
|
|
||||||
|
RQG_Alpha = Ogre::RENDER_QUEUE_MAIN,
|
||||||
|
|
||||||
|
RQG_UnderWater = Ogre::RENDER_QUEUE_7+1,
|
||||||
|
|
||||||
|
RQG_OcclusionQuery = Ogre::RENDER_QUEUE_8,
|
||||||
|
|
||||||
|
// Sky late (sun & sun flare)
|
||||||
|
RQG_SkiesLate = Ogre::RENDER_QUEUE_SKIES_LATE
|
||||||
|
};
|
||||||
|
|
||||||
|
// Visibility flags
|
||||||
|
enum VisibilityFlags
|
||||||
|
{
|
||||||
|
// Terrain
|
||||||
|
RV_Terrain = 1,
|
||||||
|
|
||||||
|
// Statics (e.g. trees, houses)
|
||||||
|
RV_Statics = 2,
|
||||||
|
|
||||||
|
// Small statics
|
||||||
|
RV_StaticsSmall = 4,
|
||||||
|
|
||||||
|
// Water
|
||||||
|
RV_Water = 8,
|
||||||
|
|
||||||
|
// Actors (player, npcs, creatures)
|
||||||
|
RV_Actors = 16,
|
||||||
|
|
||||||
|
// Misc objects (containers, dynamic objects)
|
||||||
|
RV_Misc = 32,
|
||||||
|
|
||||||
|
RV_Sky = 64,
|
||||||
|
|
||||||
|
// Sun glare (not visible in reflection)
|
||||||
|
RV_Glare = 128,
|
||||||
|
|
||||||
|
RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water,
|
||||||
|
|
||||||
|
/// \todo markers (normally hidden)
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -27,6 +27,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
||||||
mTerrainManager = new TerrainManager(mRendering.getScene(),
|
mTerrainManager = new TerrainManager(mRendering.getScene(),
|
||||||
environment);
|
environment);
|
||||||
|
|
||||||
|
mWater = 0;
|
||||||
|
|
||||||
//The fog type must be set before any terrain objects are created as if the
|
//The fog type must be set before any terrain objects are created as if the
|
||||||
//fog type is set to FOG_NONE then the initially created terrain won't have any fog
|
//fog type is set to FOG_NONE then the initially created terrain won't have any fog
|
||||||
configureFog(1, ColourValue(1,1,1));
|
configureFog(1, ColourValue(1,1,1));
|
||||||
|
@ -39,14 +41,34 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
||||||
std::string filter = Settings::Manager::getString("texture filtering", "General");
|
std::string filter = Settings::Manager::getString("texture filtering", "General");
|
||||||
if (filter == "anisotropic") tfo = TFO_ANISOTROPIC;
|
if (filter == "anisotropic") tfo = TFO_ANISOTROPIC;
|
||||||
else if (filter == "trilinear") tfo = TFO_TRILINEAR;
|
else if (filter == "trilinear") tfo = TFO_TRILINEAR;
|
||||||
else /* if (filter == "bilinear") */ tfo = TFO_BILINEAR;
|
else if (filter == "bilinear") tfo = TFO_BILINEAR;
|
||||||
|
else if (filter == "none") tfo = TFO_NONE;
|
||||||
|
|
||||||
MaterialManager::getSingleton().setDefaultTextureFiltering(tfo);
|
MaterialManager::getSingleton().setDefaultTextureFiltering(tfo);
|
||||||
MaterialManager::getSingleton().setDefaultAnisotropy(Settings::Manager::getInt("anisotropy", "General"));
|
MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 );
|
||||||
|
|
||||||
// Load resources
|
// Load resources
|
||||||
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
|
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
|
||||||
|
|
||||||
|
// disable unsupported effects
|
||||||
|
const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
|
||||||
|
if (caps->getNumMultiRenderTargets() < 2)
|
||||||
|
Settings::Manager::setBool("shader", "Water", false);
|
||||||
|
|
||||||
|
// note that the order is important here
|
||||||
|
if (useMRT())
|
||||||
|
{
|
||||||
|
CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "gbuffer");
|
||||||
|
CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbuffer", true);
|
||||||
|
CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "Underwater");
|
||||||
|
CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "gbufferFinalizer");
|
||||||
|
CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbufferFinalizer", true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CompositorManager::getSingleton().addCompositor(mRendering.getViewport(), "UnderwaterNoMRT");
|
||||||
|
}
|
||||||
|
|
||||||
// Turn the entire scene (represented by the 'root' node) -90
|
// Turn the entire scene (represented by the 'root' node) -90
|
||||||
// degrees around the x axis. This makes Z go upwards, and Y go into
|
// degrees around the x axis. This makes Z go upwards, and Y go into
|
||||||
// the screen (when x is to the right.) This is the orientation that
|
// the screen (when x is to the right.) This is the orientation that
|
||||||
|
@ -69,8 +91,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
||||||
|
|
||||||
mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode());
|
mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode());
|
||||||
|
|
||||||
mWater = 0;
|
|
||||||
|
|
||||||
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
|
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
|
||||||
mSun = 0;
|
mSun = 0;
|
||||||
|
|
||||||
|
@ -122,8 +142,7 @@ void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store)
|
||||||
void RenderingManager::removeWater ()
|
void RenderingManager::removeWater ()
|
||||||
{
|
{
|
||||||
if(mWater){
|
if(mWater){
|
||||||
delete mWater;
|
mWater->setActive(false);
|
||||||
mWater = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +158,7 @@ void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store)
|
||||||
mDebugging->cellAdded(store);
|
mDebugging->cellAdded(store);
|
||||||
if (store->cell->isExterior())
|
if (store->cell->isExterior())
|
||||||
mTerrainManager->cellAdded(store);
|
mTerrainManager->cellAdded(store);
|
||||||
|
waterAdded(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::addObject (const MWWorld::Ptr& ptr){
|
void RenderingManager::addObject (const MWWorld::Ptr& ptr){
|
||||||
|
@ -195,11 +215,10 @@ void RenderingManager::update (float duration){
|
||||||
void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){
|
void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){
|
||||||
if(store->cell->data.flags & store->cell->HasWater){
|
if(store->cell->data.flags & store->cell->HasWater){
|
||||||
if(mWater == 0)
|
if(mWater == 0)
|
||||||
mWater = new MWRender::Water(mRendering.getCamera(), store->cell);
|
mWater = new MWRender::Water(mRendering.getCamera(), mSkyManager, store->cell);
|
||||||
else
|
else
|
||||||
mWater->changeCell(store->cell);
|
mWater->changeCell(store->cell);
|
||||||
//else
|
mWater->setActive(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
removeWater();
|
removeWater();
|
||||||
|
@ -263,11 +282,25 @@ bool RenderingManager::toggleRenderMode(int mode)
|
||||||
{
|
{
|
||||||
if (mRendering.getCamera()->getPolygonMode() == PM_SOLID)
|
if (mRendering.getCamera()->getPolygonMode() == PM_SOLID)
|
||||||
{
|
{
|
||||||
|
// disable compositors
|
||||||
|
if (useMRT())
|
||||||
|
{
|
||||||
|
CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbuffer", false);
|
||||||
|
CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbufferFinalizer", false);
|
||||||
|
}
|
||||||
|
|
||||||
mRendering.getCamera()->setPolygonMode(PM_WIREFRAME);
|
mRendering.getCamera()->setPolygonMode(PM_WIREFRAME);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// re-enable compositors
|
||||||
|
if (useMRT())
|
||||||
|
{
|
||||||
|
CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbuffer", true);
|
||||||
|
CompositorManager::getSingleton().setCompositorEnabled(mRendering.getViewport(), "gbufferFinalizer", true);
|
||||||
|
}
|
||||||
|
|
||||||
mRendering.getCamera()->setPolygonMode(PM_SOLID);
|
mRendering.getCamera()->setPolygonMode(PM_SOLID);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -293,6 +326,12 @@ void RenderingManager::configureFog(const float density, const Ogre::ColourValue
|
||||||
|
|
||||||
mRendering.getCamera()->setFarClipDistance ( max / density );
|
mRendering.getCamera()->setFarClipDistance ( max / density );
|
||||||
mRendering.getViewport()->setBackgroundColour (colour);
|
mRendering.getViewport()->setBackgroundColour (colour);
|
||||||
|
|
||||||
|
CompositorInstance* inst = CompositorManager::getSingleton().getCompositorChain(mRendering.getViewport())->getCompositor("gbuffer");
|
||||||
|
if (inst != 0)
|
||||||
|
inst->getCompositor()->getTechnique(0)->getTargetPass(0)->getPass(0)->setClearColour(colour);
|
||||||
|
if (mWater)
|
||||||
|
mWater->setViewportBackground(colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -352,8 +391,10 @@ void RenderingManager::toggleLight()
|
||||||
|
|
||||||
setAmbientMode();
|
setAmbientMode();
|
||||||
}
|
}
|
||||||
void RenderingManager::checkUnderwater(){
|
void RenderingManager::checkUnderwater()
|
||||||
if(mWater){
|
{
|
||||||
|
if(mWater)
|
||||||
|
{
|
||||||
mWater->checkUnderwater( mRendering.getCamera()->getRealPosition().y );
|
mWater->checkUnderwater( mRendering.getCamera()->getRealPosition().y );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -372,6 +413,7 @@ void RenderingManager::skipAnimation (const MWWorld::Ptr& ptr)
|
||||||
void RenderingManager::setSunColour(const Ogre::ColourValue& colour)
|
void RenderingManager::setSunColour(const Ogre::ColourValue& colour)
|
||||||
{
|
{
|
||||||
mSun->setDiffuseColour(colour);
|
mSun->setDiffuseColour(colour);
|
||||||
|
mSun->setSpecularColour(colour);
|
||||||
mTerrainManager->setDiffuse(colour);
|
mTerrainManager->setDiffuse(colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,4 +470,9 @@ void RenderingManager::enableLights()
|
||||||
mObjects.enableLights();
|
mObjects.enableLights();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool RenderingManager::useMRT()
|
||||||
|
{
|
||||||
|
return Settings::Manager::getBool("shader", "Water");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -31,11 +31,8 @@
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
class Camera;
|
|
||||||
class Viewport;
|
|
||||||
class SceneManager;
|
class SceneManager;
|
||||||
class SceneNode;
|
class SceneNode;
|
||||||
class RaySceneQuery;
|
|
||||||
class Quaternion;
|
class Quaternion;
|
||||||
class Vector3;
|
class Vector3;
|
||||||
}
|
}
|
||||||
|
@ -84,6 +81,8 @@ class RenderingManager: private RenderingInterface {
|
||||||
|
|
||||||
void removeWater();
|
void removeWater();
|
||||||
|
|
||||||
|
static const bool useMRT();
|
||||||
|
|
||||||
void preCellChange (MWWorld::Ptr::CellStore* store);
|
void preCellChange (MWWorld::Ptr::CellStore* store);
|
||||||
///< this event is fired immediately before changing cell
|
///< this event is fired immediately before changing cell
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
|
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/world.hpp"
|
#include "../mwworld/world.hpp"
|
||||||
#include "occlusionquery.hpp"
|
#include "renderconst.hpp"
|
||||||
|
#include "renderingmanager.hpp"
|
||||||
|
|
||||||
using namespace MWRender;
|
using namespace MWRender;
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
|
@ -60,6 +61,11 @@ Vector3 BillboardObject::getPosition() const
|
||||||
return Vector3(p.x, -p.z, p.y);
|
return Vector3(p.x, -p.z, p.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BillboardObject::setVisibilityFlags(int flags)
|
||||||
|
{
|
||||||
|
mBBSet->setVisibilityFlags(flags);
|
||||||
|
}
|
||||||
|
|
||||||
void BillboardObject::setColour(const ColourValue& pColour)
|
void BillboardObject::setColour(const ColourValue& pColour)
|
||||||
{
|
{
|
||||||
mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour);
|
mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour);
|
||||||
|
@ -89,9 +95,9 @@ void BillboardObject::init(const String& textureName,
|
||||||
/// \todo These billboards are not 100% correct, might want to revisit them later
|
/// \todo These billboards are not 100% correct, might want to revisit them later
|
||||||
mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1);
|
mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1);
|
||||||
mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize);
|
mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize);
|
||||||
mBBSet->setRenderQueueGroup(RENDER_QUEUE_MAIN+2);
|
|
||||||
mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON);
|
mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON);
|
||||||
mBBSet->setCommonDirection( -position.normalisedCopy() );
|
mBBSet->setCommonDirection( -position.normalisedCopy() );
|
||||||
|
mBBSet->setVisibilityFlags(RV_Sky);
|
||||||
mNode = rootNode->createChildSceneNode();
|
mNode = rootNode->createChildSceneNode();
|
||||||
mNode->setPosition(finalPosition);
|
mNode->setPosition(finalPosition);
|
||||||
mNode->attachObject(mBBSet);
|
mNode->attachObject(mBBSet);
|
||||||
|
@ -109,6 +115,65 @@ void BillboardObject::init(const String& textureName,
|
||||||
p->createTextureUnitState(textureName);
|
p->createTextureUnitState(textureName);
|
||||||
mBBSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount));
|
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++;
|
bodyCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +222,10 @@ Moon::Moon( const String& textureName,
|
||||||
outStream2 <<
|
outStream2 <<
|
||||||
"void main_fp( \n"
|
"void main_fp( \n"
|
||||||
" in float2 uv : TEXCOORD0, \n"
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
" out float4 oColor : COLOR, \n"
|
" out float4 oColor : COLOR, \n";
|
||||||
|
if (RenderingManager::useMRT()) outStream2 <<
|
||||||
|
" out float4 oColor1 : COLOR1, \n";
|
||||||
|
outStream2 <<
|
||||||
" uniform sampler2D texture : TEXUNIT0, \n"
|
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||||
" uniform float4 skyColour, \n"
|
" uniform float4 skyColour, \n"
|
||||||
" uniform float4 diffuse, \n"
|
" uniform float4 diffuse, \n"
|
||||||
|
@ -165,7 +233,10 @@ Moon::Moon( const String& textureName,
|
||||||
") \n"
|
") \n"
|
||||||
"{ \n"
|
"{ \n"
|
||||||
" float4 tex = tex2D(texture, uv); \n"
|
" float4 tex = tex2D(texture, uv); \n"
|
||||||
" oColor = float4(emissive.xyz,1) * tex; \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)
|
// use a circle for the alpha (compute UV distance to center)
|
||||||
// looks a bit bad because its not filtered on the edges,
|
// looks a bit bad because its not filtered on the edges,
|
||||||
// but it's cheaper than a seperate alpha texture.
|
// but it's cheaper than a seperate alpha texture.
|
||||||
|
@ -358,15 +429,17 @@ void SkyManager::create()
|
||||||
|
|
||||||
mSecunda = new Moon("textures\\tx_secunda_full.dds", 0.5, Vector3(-0.4, 0.4, 0.5), mRootNode);
|
mSecunda = new Moon("textures\\tx_secunda_full.dds", 0.5, Vector3(-0.4, 0.4, 0.5), mRootNode);
|
||||||
mSecunda->setType(Moon::Type_Secunda);
|
mSecunda->setType(Moon::Type_Secunda);
|
||||||
mSecunda->setRenderQueue(RENDER_QUEUE_SKIES_EARLY+4);
|
mSecunda->setRenderQueue(RQG_SkiesEarly+4);
|
||||||
|
|
||||||
mMasser = new Moon("textures\\tx_masser_full.dds", 0.75, Vector3(-0.4, 0.4, 0.5), mRootNode);
|
mMasser = new Moon("textures\\tx_masser_full.dds", 0.75, Vector3(-0.4, 0.4, 0.5), mRootNode);
|
||||||
mMasser->setRenderQueue(RENDER_QUEUE_SKIES_EARLY+3);
|
mMasser->setRenderQueue(RQG_SkiesEarly+3);
|
||||||
mMasser->setType(Moon::Type_Masser);
|
mMasser->setType(Moon::Type_Masser);
|
||||||
|
|
||||||
mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 0.4), mRootNode);
|
mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 0.4), mRootNode);
|
||||||
|
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);
|
||||||
mSunGlare->setRenderQueue(RENDER_QUEUE_SKIES_LATE);
|
mSunGlare->setRenderQueue(RQG_SkiesLate);
|
||||||
|
mSunGlare->setVisibilityFlags(RV_Glare);
|
||||||
|
|
||||||
|
|
||||||
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||||
|
@ -375,7 +448,8 @@ void SkyManager::create()
|
||||||
/// \todo sky_night_02.nif (available in Bloodmoon)
|
/// \todo sky_night_02.nif (available in Bloodmoon)
|
||||||
MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif");
|
MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif");
|
||||||
Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif");
|
Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif");
|
||||||
night1_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+1);
|
night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1);
|
||||||
|
night1_ent->setVisibilityFlags(RV_Sky);
|
||||||
|
|
||||||
mAtmosphereNight = mRootNode->createChildSceneNode();
|
mAtmosphereNight = mRootNode->createChildSceneNode();
|
||||||
mAtmosphereNight->attachObject(night1_ent);
|
mAtmosphereNight->attachObject(night1_ent);
|
||||||
|
@ -413,7 +487,10 @@ void SkyManager::create()
|
||||||
outStream5 <<
|
outStream5 <<
|
||||||
"void main_fp( \n"
|
"void main_fp( \n"
|
||||||
" in float2 uv : TEXCOORD0, \n"
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
" out float4 oColor : COLOR, \n"
|
" out float4 oColor : COLOR, \n";
|
||||||
|
if (RenderingManager::useMRT()) outStream5 <<
|
||||||
|
" out float4 oColor1 : COLOR1, \n";
|
||||||
|
outStream5 <<
|
||||||
" in float fade : TEXCOORD1, \n"
|
" in float fade : TEXCOORD1, \n"
|
||||||
" uniform sampler2D texture : TEXUNIT0, \n"
|
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||||
" uniform float opacity, \n"
|
" uniform float opacity, \n"
|
||||||
|
@ -421,7 +498,10 @@ void SkyManager::create()
|
||||||
" uniform float4 emissive \n"
|
" uniform float4 emissive \n"
|
||||||
") \n"
|
") \n"
|
||||||
"{ \n"
|
"{ \n"
|
||||||
" oColor = tex2D(texture, uv) * float4(emissive.xyz, 1) * float4(1,1,1,fade*diffuse.a); \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->setSource(outStream5.str());
|
||||||
stars_fp->load();
|
stars_fp->load();
|
||||||
|
@ -448,7 +528,8 @@ void SkyManager::create()
|
||||||
|
|
||||||
ModVertexAlpha(atmosphere_ent, 0);
|
ModVertexAlpha(atmosphere_ent, 0);
|
||||||
|
|
||||||
atmosphere_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY);
|
atmosphere_ent->setRenderQueueGroup(RQG_SkiesEarly);
|
||||||
|
atmosphere_ent->setVisibilityFlags(RV_Sky);
|
||||||
mAtmosphereDay = mRootNode->createChildSceneNode();
|
mAtmosphereDay = mRootNode->createChildSceneNode();
|
||||||
mAtmosphereDay->attachObject(atmosphere_ent);
|
mAtmosphereDay->attachObject(atmosphere_ent);
|
||||||
mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial();
|
mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial();
|
||||||
|
@ -466,26 +547,52 @@ void SkyManager::create()
|
||||||
" float4 position : POSITION, \n"
|
" float4 position : POSITION, \n"
|
||||||
" in float4 color : COLOR, \n"
|
" in float4 color : COLOR, \n"
|
||||||
" out float4 oPosition : POSITION, \n"
|
" out float4 oPosition : POSITION, \n"
|
||||||
" out float4 oColor : COLOR, \n"
|
" out float4 oVertexColor : TEXCOORD0, \n"
|
||||||
" uniform float4 emissive, \n"
|
|
||||||
" uniform float4x4 worldViewProj \n"
|
" uniform float4x4 worldViewProj \n"
|
||||||
") \n"
|
") \n"
|
||||||
"{ \n"
|
"{ \n"
|
||||||
" oPosition = mul( worldViewProj, position ); \n"
|
" oPosition = mul( worldViewProj, position ); \n"
|
||||||
" oColor = color * emissive; \n"
|
" oVertexColor = color; \n"
|
||||||
"}";
|
"}";
|
||||||
vshader->setSource(outStream.str());
|
vshader->setSource(outStream.str());
|
||||||
vshader->load();
|
vshader->load();
|
||||||
|
|
||||||
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||||
vshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
|
||||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
|
||||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setFragmentProgram("");
|
|
||||||
|
HighLevelGpuProgramPtr fshader = mgr.createProgram("Atmosphere_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
"cg", GPT_FRAGMENT_PROGRAM);
|
||||||
|
|
||||||
|
fshader->setParameter("profiles", "ps_2_x arbfp1");
|
||||||
|
fshader->setParameter("entry_point", "main_fp");
|
||||||
|
|
||||||
|
StringUtil::StrStreamType _outStream;
|
||||||
|
_outStream <<
|
||||||
|
"void main_fp( \n"
|
||||||
|
" in float4 iVertexColor : TEXCOORD0, \n"
|
||||||
|
" out float4 oColor : COLOR, \n";
|
||||||
|
if (RenderingManager::useMRT()) _outStream <<
|
||||||
|
" out float4 oColor1 : COLOR1, \n";
|
||||||
|
_outStream <<
|
||||||
|
" uniform float4 emissive \n"
|
||||||
|
") \n"
|
||||||
|
"{ \n"
|
||||||
|
" oColor = iVertexColor * emissive; \n";
|
||||||
|
if (RenderingManager::useMRT()) _outStream <<
|
||||||
|
" oColor1 = float4(1, 0, 0, 1); \n";
|
||||||
|
_outStream <<
|
||||||
|
"}";
|
||||||
|
fshader->setSource(_outStream.str());
|
||||||
|
fshader->load();
|
||||||
|
|
||||||
|
fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||||
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName());
|
||||||
|
|
||||||
// Clouds
|
// Clouds
|
||||||
NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif");
|
NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif");
|
||||||
Entity* clouds_ent = mSceneMgr->createEntity("meshes\\sky_clouds_01.nif");
|
Entity* clouds_ent = mSceneMgr->createEntity("meshes\\sky_clouds_01.nif");
|
||||||
clouds_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+5);
|
clouds_ent->setVisibilityFlags(RV_Sky);
|
||||||
|
clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5);
|
||||||
SceneNode* clouds_node = mRootNode->createChildSceneNode();
|
SceneNode* clouds_node = mRootNode->createChildSceneNode();
|
||||||
clouds_node->attachObject(clouds_ent);
|
clouds_node->attachObject(clouds_ent);
|
||||||
mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial();
|
mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial();
|
||||||
|
@ -525,8 +632,11 @@ void SkyManager::create()
|
||||||
outStream2 <<
|
outStream2 <<
|
||||||
"void main_fp( \n"
|
"void main_fp( \n"
|
||||||
" in float2 uv : TEXCOORD0, \n"
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
" out float4 oColor : COLOR, \n"
|
|
||||||
" in float4 color : TEXCOORD1, \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 texture : TEXUNIT0, \n"
|
||||||
" uniform sampler2D secondTexture : TEXUNIT1, \n"
|
" uniform sampler2D secondTexture : TEXUNIT1, \n"
|
||||||
" uniform float transitionFactor, \n"
|
" uniform float transitionFactor, \n"
|
||||||
|
@ -538,7 +648,10 @@ void SkyManager::create()
|
||||||
"{ \n"
|
"{ \n"
|
||||||
" uv += float2(0,1) * time * speed * 0.003; \n" // Scroll in y direction
|
" uv += float2(0,1) * time * speed * 0.003; \n" // Scroll in y direction
|
||||||
" float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n"
|
" float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n"
|
||||||
" oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \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->setSource(outStream2.str());
|
||||||
mCloudFragmentShader->load();
|
mCloudFragmentShader->load();
|
||||||
|
@ -734,7 +847,8 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
|
||||||
strength = 1.f;
|
strength = 1.f;
|
||||||
|
|
||||||
mSunGlare->setVisibility(weather.mGlareView * mGlareFade * strength);
|
mSunGlare->setVisibility(weather.mGlareView * mGlareFade * strength);
|
||||||
mSun->setVisibility(mGlareFade >= 0.5 ? weather.mGlareView * mGlareFade * strength : 0);
|
|
||||||
|
mSun->setVisibility(weather.mGlareView * strength);
|
||||||
|
|
||||||
mAtmosphereNight->setVisible(weather.mNight && mEnabled);
|
mAtmosphereNight->setVisible(weather.mNight && mEnabled);
|
||||||
}
|
}
|
||||||
|
@ -837,3 +951,18 @@ Ogre::SceneNode* SkyManager::getSunNode()
|
||||||
if (!mCreated) return 0;
|
if (!mCreated) return 0;
|
||||||
return mSun->getNode();
|
return mSun->getNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkyManager::setSkyPosition(const Ogre::Vector3& position)
|
||||||
|
{
|
||||||
|
mRootNode->_setDerivedPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::resetSkyPosition()
|
||||||
|
{
|
||||||
|
mRootNode->setPosition(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkyManager::scaleSky(float scale)
|
||||||
|
{
|
||||||
|
mRootNode->setScale(scale, scale, scale);
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace MWRender
|
||||||
void setPosition(const Ogre::Vector3& pPosition);
|
void setPosition(const Ogre::Vector3& pPosition);
|
||||||
void setVisible(const bool visible);
|
void setVisible(const bool visible);
|
||||||
void setRenderQueue(unsigned int id);
|
void setRenderQueue(unsigned int id);
|
||||||
|
void setVisibilityFlags(int flags);
|
||||||
void setSize(const float size);
|
void setSize(const float size);
|
||||||
Ogre::Vector3 getPosition() const;
|
Ogre::Vector3 getPosition() const;
|
||||||
|
|
||||||
|
@ -168,6 +169,10 @@ namespace MWRender
|
||||||
void setGlare(const float glare);
|
void setGlare(const float glare);
|
||||||
Ogre::Vector3 getRealSunPos();
|
Ogre::Vector3 getRealSunPos();
|
||||||
|
|
||||||
|
void setSkyPosition(const Ogre::Vector3& position);
|
||||||
|
void resetSkyPosition();
|
||||||
|
void scaleSky(float scale);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mCreated;
|
bool mCreated;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "terrainmaterial.hpp"
|
#include "terrainmaterial.hpp"
|
||||||
#include "terrain.hpp"
|
#include "terrain.hpp"
|
||||||
|
#include "renderconst.hpp"
|
||||||
|
|
||||||
|
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
|
@ -162,6 +163,8 @@ namespace MWRender
|
||||||
x * numTextures, y * numTextures,
|
x * numTextures, y * numTextures,
|
||||||
numTextures,
|
numTextures,
|
||||||
indexes);
|
indexes);
|
||||||
|
terrain->setVisibilityFlags(RV_Terrain);
|
||||||
|
terrain->setRenderQueueGroup(RQG_Main);
|
||||||
|
|
||||||
if ( land && land->landData->usingColours )
|
if ( land && land->landData->usingColours )
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,6 +37,7 @@ THE SOFTWARE.
|
||||||
#include "OgreShadowCameraSetupPSSM.h"
|
#include "OgreShadowCameraSetupPSSM.h"
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
#include "renderingmanager.hpp"
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
@ -558,6 +559,9 @@ namespace Ogre
|
||||||
//params->setNamedAutoConstant("lightSpecularColour"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, i);
|
//params->setNamedAutoConstant("lightSpecularColour"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MWRender::RenderingManager::useMRT())
|
||||||
|
params->setNamedAutoConstant("far", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
|
||||||
|
|
||||||
params->setNamedAutoConstant("eyePosObjSpace", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE);
|
params->setNamedAutoConstant("eyePosObjSpace", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE);
|
||||||
params->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
params->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
||||||
|
|
||||||
|
@ -753,11 +757,6 @@ namespace Ogre
|
||||||
ret->unload();
|
ret->unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(prof->isLayerNormalMappingEnabled() || prof->isLayerParallaxMappingEnabled())
|
|
||||||
ret->setParameter("profiles", "ps_3_0 ps_2_x fp40 arbfp1");
|
|
||||||
//else
|
|
||||||
//ret->setParameter("profiles", "ps_3_0 ps_2_0 fp30 arbfp1");
|
|
||||||
else // fp30 doesn't work (black terrain)
|
|
||||||
ret->setParameter("profiles", "ps_3_0 ps_2_x fp40 arbfp1");
|
ret->setParameter("profiles", "ps_3_0 ps_2_x fp40 arbfp1");
|
||||||
ret->setParameter("entry_point", "main_fp");
|
ret->setParameter("entry_point", "main_fp");
|
||||||
|
|
||||||
|
@ -917,7 +916,7 @@ namespace Ogre
|
||||||
|
|
||||||
|
|
||||||
outStream <<
|
outStream <<
|
||||||
"float4 main_fp(\n"
|
"void main_fp(\n"
|
||||||
"float4 position : TEXCOORD0,\n";
|
"float4 position : TEXCOORD0,\n";
|
||||||
|
|
||||||
uint texCoordSet = 1;
|
uint texCoordSet = 1;
|
||||||
|
@ -1034,8 +1033,15 @@ namespace Ogre
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MWRender::RenderingManager::useMRT()) outStream <<
|
||||||
|
" , out float4 oColor : COLOR \n"
|
||||||
|
" , out float4 oColor1 : COLOR1 \n"
|
||||||
|
" , uniform float far \n";
|
||||||
|
else outStream <<
|
||||||
|
" , out float4 oColor : COLOR \n";
|
||||||
|
|
||||||
outStream <<
|
outStream <<
|
||||||
") : COLOR\n"
|
")\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" float4 outputCol;\n"
|
" float4 outputCol;\n"
|
||||||
" float shadow = 1.0;\n"
|
" float shadow = 1.0;\n"
|
||||||
|
@ -1241,6 +1247,10 @@ namespace Ogre
|
||||||
" oPos = mul(viewProjMatrix, worldPos);\n"
|
" oPos = mul(viewProjMatrix, worldPos);\n"
|
||||||
" oUVMisc.xy = uv.xy;\n";
|
" oUVMisc.xy = uv.xy;\n";
|
||||||
|
|
||||||
|
outStream <<
|
||||||
|
" // pass cam depth\n"
|
||||||
|
" oUVMisc.z = oPos.z;\n";
|
||||||
|
|
||||||
bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP;
|
bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP;
|
||||||
if (fog)
|
if (fog)
|
||||||
{
|
{
|
||||||
|
@ -1337,7 +1347,12 @@ namespace Ogre
|
||||||
}
|
}
|
||||||
|
|
||||||
// Final return
|
// Final return
|
||||||
outStream << " return outputCol;\n"
|
outStream << " oColor = outputCol;\n";
|
||||||
|
|
||||||
|
if (MWRender::RenderingManager::useMRT()) outStream <<
|
||||||
|
" oColor1 = float4(uvMisc.z / far, 0, 0, 1); \n";
|
||||||
|
|
||||||
|
outStream
|
||||||
<< "}\n";
|
<< "}\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1511,14 +1526,6 @@ namespace Ogre
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (prof->getReceiveDynamicShadowsPSSM())
|
|
||||||
{
|
|
||||||
outStream <<
|
|
||||||
" // pass cam depth\n"
|
|
||||||
" oUVMisc.z = oPos.z;\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateFpDynamicShadowsParams(
|
void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateFpDynamicShadowsParams(
|
||||||
|
|
|
@ -1,29 +1,43 @@
|
||||||
#include "water.hpp"
|
#include "water.hpp"
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
#include "sky.hpp"
|
||||||
|
#include "renderingmanager.hpp"
|
||||||
|
|
||||||
|
using namespace Ogre;
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
Water::Water (Ogre::Camera *camera, const ESM::Cell* cell) :
|
Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
||||||
mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()),
|
mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()),
|
||||||
mIsUnderwater(false)
|
mIsUnderwater(false), mVisibilityFlags(0),
|
||||||
|
mReflectionTarget(0), mActive(1)
|
||||||
{
|
{
|
||||||
|
mSky = sky;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "Water", -1);
|
CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false);
|
||||||
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false);
|
|
||||||
} catch(...) {}
|
} catch(...) {}
|
||||||
|
|
||||||
mTop = cell->water;
|
mTop = cell->water;
|
||||||
|
|
||||||
mIsUnderwater = false;
|
mIsUnderwater = false;
|
||||||
|
|
||||||
mWaterPlane = Ogre::Plane(Ogre::Vector3::UNIT_Y, 0);
|
mWaterPlane = Plane(Vector3::UNIT_Y, 0);
|
||||||
|
|
||||||
Ogre::MeshManager::getSingleton().createPlane("water", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mWaterPlane, CELL_SIZE*5, CELL_SIZE * 5, 10, 10, true, 1, 3,5, Ogre::Vector3::UNIT_Z);
|
MeshManager::getSingleton().createPlane("water", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mWaterPlane, CELL_SIZE*5, CELL_SIZE * 5, 10, 10, true, 1, 3,3, Vector3::UNIT_Z);
|
||||||
|
|
||||||
mWater = mSceneManager->createEntity("water");
|
mWater = mSceneManager->createEntity("water");
|
||||||
|
mWater->setVisibilityFlags(RV_Water);
|
||||||
|
mWater->setRenderQueueGroup(RQG_Water);
|
||||||
|
|
||||||
mWater->setMaterialName("Examples/Water0");
|
mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water")
|
||||||
|
+ RV_Statics * Settings::Manager::getBool("reflect statics", "Water")
|
||||||
|
+ RV_StaticsSmall * Settings::Manager::getBool("reflect small statics", "Water")
|
||||||
|
+ RV_Actors * Settings::Manager::getBool("reflect actors", "Water")
|
||||||
|
+ RV_Misc * Settings::Manager::getBool("reflect misc", "Water")
|
||||||
|
+ RV_Sky;
|
||||||
|
|
||||||
mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
|
mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
|
||||||
mWaterNode->setPosition(0, mTop, 0);
|
mWaterNode->setPosition(0, mTop, 0);
|
||||||
|
@ -33,18 +47,51 @@ Water::Water (Ogre::Camera *camera, const ESM::Cell* cell) :
|
||||||
mWaterNode->setPosition(getSceneNodeCoordinates(cell->data.gridX, cell->data.gridY));
|
mWaterNode->setPosition(getSceneNodeCoordinates(cell->data.gridX, cell->data.gridY));
|
||||||
}
|
}
|
||||||
mWaterNode->attachObject(mWater);
|
mWaterNode->attachObject(mWater);
|
||||||
|
|
||||||
|
// Create rendertarget for reflection
|
||||||
|
int rttsize = Settings::Manager::getInt("rtt size", "Water");
|
||||||
|
|
||||||
|
if (Settings::Manager::getBool("shader", "Water"))
|
||||||
|
{
|
||||||
|
TexturePtr tex = TextureManager::getSingleton().createManual("WaterReflection",
|
||||||
|
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_R8G8B8, TU_RENDERTARGET);
|
||||||
|
|
||||||
|
RenderTarget* rtt = tex->getBuffer()->getRenderTarget();
|
||||||
|
Viewport* vp = rtt->addViewport(mCamera);
|
||||||
|
vp->setOverlaysEnabled(false);
|
||||||
|
vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f));
|
||||||
|
vp->setShadowsEnabled(false);
|
||||||
|
vp->setVisibilityMask( mVisibilityFlags );
|
||||||
|
rtt->addListener(this);
|
||||||
|
rtt->setActive(true);
|
||||||
|
|
||||||
|
mReflectionTarget = rtt;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT";
|
||||||
|
|
||||||
|
createMaterial();
|
||||||
|
mWater->setMaterial(mMaterial);
|
||||||
|
|
||||||
|
mUnderwaterEffect = Settings::Manager::getBool("underwater effect", "Water");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Water::setActive(bool active)
|
||||||
|
{
|
||||||
|
mActive = active;
|
||||||
|
if (mReflectionTarget) mReflectionTarget->setActive(active && !mIsUnderwater);
|
||||||
|
mWater->setVisible(active);
|
||||||
|
}
|
||||||
|
|
||||||
Water::~Water()
|
Water::~Water()
|
||||||
{
|
{
|
||||||
Ogre::MeshManager::getSingleton().remove("water");
|
MeshManager::getSingleton().remove("water");
|
||||||
|
|
||||||
mWaterNode->detachObject(mWater);
|
mWaterNode->detachObject(mWater);
|
||||||
mSceneManager->destroyEntity(mWater);
|
mSceneManager->destroyEntity(mWater);
|
||||||
mSceneManager->destroySceneNode(mWaterNode);
|
mSceneManager->destroySceneNode(mWaterNode);
|
||||||
|
|
||||||
Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport);
|
CompositorManager::getSingleton().removeCompositorChain(mViewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Water::changeCell(const ESM::Cell* cell)
|
void Water::changeCell(const ESM::Cell* cell)
|
||||||
|
@ -65,31 +112,122 @@ void Water::setHeight(const float height)
|
||||||
|
|
||||||
void Water::toggle()
|
void Water::toggle()
|
||||||
{
|
{
|
||||||
|
if (mActive)
|
||||||
mWater->setVisible(!mWater->getVisible());
|
mWater->setVisible(!mWater->getVisible());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Water::checkUnderwater(float y)
|
void Water::checkUnderwater(float y)
|
||||||
{
|
{
|
||||||
if ((mIsUnderwater && y > mTop) || !mWater->isVisible())
|
if (!mActive) return;
|
||||||
|
if ((mIsUnderwater && y > mTop) || !mWater->isVisible() || mCamera->getPolygonMode() != Ogre::PM_SOLID)
|
||||||
{
|
{
|
||||||
try {
|
CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false);
|
||||||
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false);
|
|
||||||
} catch(...) {}
|
// 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));
|
||||||
|
|
||||||
|
if (mReflectionTarget)
|
||||||
|
mReflectionTarget->setActive(mActive);
|
||||||
|
|
||||||
|
mWater->setRenderQueueGroup(RQG_Water);
|
||||||
|
|
||||||
mIsUnderwater = false;
|
mIsUnderwater = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mIsUnderwater && y < mTop && mWater->isVisible())
|
if (!mIsUnderwater && y < mTop && mWater->isVisible() && mCamera->getPolygonMode() == Ogre::PM_SOLID)
|
||||||
{
|
{
|
||||||
try {
|
if (mUnderwaterEffect)
|
||||||
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", true);
|
CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, true);
|
||||||
} catch(...) {}
|
|
||||||
|
// 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));
|
||||||
|
|
||||||
|
if (mReflectionTarget)
|
||||||
|
mReflectionTarget->setActive(false);
|
||||||
|
|
||||||
|
mWater->setRenderQueueGroup(RQG_UnderWater);
|
||||||
|
|
||||||
mIsUnderwater = true;
|
mIsUnderwater = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ogre::Vector3 Water::getSceneNodeCoordinates(int gridX, int gridY)
|
Vector3 Water::getSceneNodeCoordinates(int gridX, int gridY)
|
||||||
{
|
{
|
||||||
return Ogre::Vector3(gridX * CELL_SIZE + (CELL_SIZE / 2), mTop, -gridY * CELL_SIZE - (CELL_SIZE / 2));
|
return Vector3(gridX * CELL_SIZE + (CELL_SIZE / 2), mTop, -gridY * CELL_SIZE - (CELL_SIZE / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Water::preRenderTargetUpdate(const RenderTargetEvent& evt)
|
||||||
|
{
|
||||||
|
if (evt.source == mReflectionTarget)
|
||||||
|
{
|
||||||
|
mWater->setVisible(false);
|
||||||
|
|
||||||
|
// Some messy code to get the skybox to show up at all
|
||||||
|
// The problem here is that it gets clipped by the water plane
|
||||||
|
// Therefore scale it up a bit
|
||||||
|
Vector3 pos = mCamera->getRealPosition();
|
||||||
|
pos.y = mTop*2 - pos.y;
|
||||||
|
mSky->setSkyPosition(pos);
|
||||||
|
mSky->scaleSky(mCamera->getFarClipDistance() / 1000.f);
|
||||||
|
|
||||||
|
mCamera->enableCustomNearClipPlane(Plane(Vector3::UNIT_Y, mTop));
|
||||||
|
mCamera->enableReflection(Plane(Vector3::UNIT_Y, mTop));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Water::postRenderTargetUpdate(const RenderTargetEvent& evt)
|
||||||
|
{
|
||||||
|
mWater->setVisible(true);
|
||||||
|
|
||||||
|
if (evt.source == mReflectionTarget)
|
||||||
|
{
|
||||||
|
mSky->resetSkyPosition();
|
||||||
|
mSky->scaleSky(1);
|
||||||
|
mCamera->disableReflection();
|
||||||
|
mCamera->disableCustomNearClipPlane();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Water::createMaterial()
|
||||||
|
{
|
||||||
|
mMaterial = MaterialManager::getSingleton().getByName("Water");
|
||||||
|
|
||||||
|
// 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";
|
||||||
|
}
|
||||||
|
mMaterial->getTechnique(1)->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2);
|
||||||
|
|
||||||
|
// use technique without shaders if reflection is disabled
|
||||||
|
if (mReflectionTarget == 0)
|
||||||
|
mMaterial->removeTechnique(0);
|
||||||
|
|
||||||
|
if (Settings::Manager::getBool("shader", "Water"))
|
||||||
|
{
|
||||||
|
CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mViewport)->getCompositor("gbuffer");
|
||||||
|
|
||||||
|
TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0);
|
||||||
|
TextureUnitState* tus = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState("refractionMap");
|
||||||
|
if (tus != 0)
|
||||||
|
tus->setTexture(colorTexture);
|
||||||
|
|
||||||
|
TexturePtr depthTexture = compositor->getTextureInstance("mrt_output", 1);
|
||||||
|
tus = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState("depthMap");
|
||||||
|
if (tus != 0)
|
||||||
|
tus->setTexture(depthTexture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Water::setViewportBackground(const ColourValue& bg)
|
||||||
|
{
|
||||||
|
if (mReflectionTarget)
|
||||||
|
mReflectionTarget->getViewport(0)->setBackgroundColour(bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -4,10 +4,14 @@
|
||||||
#include <Ogre.h>
|
#include <Ogre.h>
|
||||||
#include <components/esm/loadcell.hpp>
|
#include <components/esm/loadcell.hpp>
|
||||||
|
|
||||||
|
#include "renderconst.hpp"
|
||||||
|
|
||||||
namespace MWRender {
|
namespace MWRender {
|
||||||
|
|
||||||
|
class SkyManager;
|
||||||
|
|
||||||
/// Water rendering
|
/// Water rendering
|
||||||
class Water : Ogre::RenderTargetListener, Ogre::Camera::Listener
|
class Water : public Ogre::RenderTargetListener
|
||||||
{
|
{
|
||||||
static const int CELL_SIZE = 8192;
|
static const int CELL_SIZE = 8192;
|
||||||
Ogre::Camera *mCamera;
|
Ogre::Camera *mCamera;
|
||||||
|
@ -19,16 +23,37 @@ namespace MWRender {
|
||||||
Ogre::Entity *mWater;
|
Ogre::Entity *mWater;
|
||||||
|
|
||||||
bool mIsUnderwater;
|
bool mIsUnderwater;
|
||||||
|
bool mActive;
|
||||||
int mTop;
|
int mTop;
|
||||||
|
|
||||||
Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY);
|
Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
|
||||||
|
void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
|
||||||
|
|
||||||
|
SkyManager* mSky;
|
||||||
|
|
||||||
|
std::string mCompositorName;
|
||||||
|
|
||||||
|
void createMaterial();
|
||||||
|
Ogre::MaterialPtr mMaterial;
|
||||||
|
|
||||||
|
Ogre::RenderTarget* mReflectionTarget;
|
||||||
|
|
||||||
|
bool mUnderwaterEffect;
|
||||||
|
int mVisibilityFlags;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Water (Ogre::Camera *camera, const ESM::Cell* cell);
|
Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell);
|
||||||
~Water();
|
~Water();
|
||||||
|
|
||||||
|
void setActive(bool active);
|
||||||
|
|
||||||
void toggle();
|
void toggle();
|
||||||
|
|
||||||
|
void setViewportBackground(const Ogre::ColourValue& bg);
|
||||||
|
|
||||||
void checkUnderwater(float y);
|
void checkUnderwater(float y);
|
||||||
void changeCell(const ESM::Cell* cell);
|
void changeCell(const ESM::Cell* cell);
|
||||||
void setHeight(const float height);
|
void setHeight(const float height);
|
||||||
|
|
|
@ -26,7 +26,9 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
void Class::insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const{
|
|
||||||
|
void Class::insertObject(const Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +139,11 @@ namespace MWWorld
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Class::getValue (const Ptr& ptr) const
|
||||||
|
{
|
||||||
|
throw std::logic_error ("value not supported by this class");
|
||||||
|
}
|
||||||
|
|
||||||
const Class& Class::get (const std::string& key)
|
const Class& Class::get (const std::string& key)
|
||||||
{
|
{
|
||||||
std::map<std::string, boost::shared_ptr<Class> >::const_iterator iter = sClasses.find (key);
|
std::map<std::string, boost::shared_ptr<Class> >::const_iterator iter = sClasses.find (key);
|
||||||
|
|
|
@ -155,6 +155,10 @@ namespace MWWorld
|
||||||
/// no such skill.
|
/// no such skill.
|
||||||
/// (default implementation: return -1)
|
/// (default implementation: return -1)
|
||||||
|
|
||||||
|
virtual int getValue (const Ptr& ptr) const;
|
||||||
|
///< Return trade value of the object. Throws an exception, if the object can't be traded.
|
||||||
|
/// (default implementation: throws an exception)
|
||||||
|
|
||||||
static const Class& get (const std::string& key);
|
static const Class& get (const std::string& key);
|
||||||
///< If there is no class for this \a key, an exception is thrown.
|
///< If there is no class for this \a key, an exception is thrown.
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
|
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
|
|
||||||
#include <iostream> /// \todo remove after rendering is implemented
|
#include <iostream> /// \todo remove after rendering is implemented
|
||||||
|
@ -94,29 +96,66 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSlot (int slot)
|
||||||
return mSlots[slot];
|
return mSlots[slot];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats)
|
void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats,
|
||||||
|
const Environment& environment)
|
||||||
{
|
{
|
||||||
TSlots slots;
|
TSlots slots;
|
||||||
initSlots (slots);
|
initSlots (slots);
|
||||||
|
|
||||||
for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter)
|
for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter)
|
||||||
{
|
{
|
||||||
|
Ptr test = *iter;
|
||||||
|
int testSkill = MWWorld::Class::get (test).getEquipmentSkill (test, environment);
|
||||||
|
|
||||||
std::pair<std::vector<int>, bool> itemsSlots =
|
std::pair<std::vector<int>, bool> itemsSlots =
|
||||||
MWWorld::Class::get (*iter).getEquipmentSlots (*iter);
|
MWWorld::Class::get (*iter).getEquipmentSlots (*iter);
|
||||||
|
|
||||||
for (std::vector<int>::const_iterator iter2 (itemsSlots.first.begin());
|
for (std::vector<int>::const_iterator iter2 (itemsSlots.first.begin());
|
||||||
iter2!=itemsSlots.first.end(); ++iter2)
|
iter2!=itemsSlots.first.end(); ++iter2)
|
||||||
{
|
{
|
||||||
/// \todo comapre item with item in slot
|
bool use = false;
|
||||||
|
|
||||||
if (slots.at (*iter2)==end())
|
if (slots.at (*iter2)==end())
|
||||||
|
use = true; // slot was empty before -> skill all further checks
|
||||||
|
else
|
||||||
{
|
{
|
||||||
|
Ptr old = *slots.at (*iter2);
|
||||||
|
|
||||||
|
if (!use)
|
||||||
|
{
|
||||||
|
// check skill
|
||||||
|
int oldSkill =
|
||||||
|
MWWorld::Class::get (old).getEquipmentSkill (old, environment);
|
||||||
|
|
||||||
|
if (testSkill!=-1 || oldSkill!=-1 || testSkill!=oldSkill)
|
||||||
|
{
|
||||||
|
if (stats.mSkill[oldSkill].getModified()>stats.mSkill[testSkill].getModified())
|
||||||
|
continue; // rejected, because old item better matched the NPC's skills.
|
||||||
|
|
||||||
|
if (stats.mSkill[oldSkill].getModified()<stats.mSkill[testSkill].getModified())
|
||||||
|
use = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!use)
|
||||||
|
{
|
||||||
|
// check value
|
||||||
|
if (MWWorld::Class::get (old).getValue (old)>=
|
||||||
|
MWWorld::Class::get (test).getValue (test))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
use = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// \todo unstack, if reqquired (itemsSlots.second)
|
/// \todo unstack, if reqquired (itemsSlots.second)
|
||||||
|
|
||||||
slots[*iter2] = iter;
|
slots[*iter2] = iter;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ namespace MWMechanics
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
class Environment;
|
||||||
|
|
||||||
///< \brief Variant of the ContainerStore for NPCs
|
///< \brief Variant of the ContainerStore for NPCs
|
||||||
class InventoryStore : public ContainerStore
|
class InventoryStore : public ContainerStore
|
||||||
{
|
{
|
||||||
|
@ -62,7 +64,7 @@ namespace MWWorld
|
||||||
|
|
||||||
ContainerStoreIterator getSlot (int slot);
|
ContainerStoreIterator getSlot (int slot);
|
||||||
|
|
||||||
void autoEquip (const MWMechanics::NpcStats& stats);
|
void autoEquip (const MWMechanics::NpcStats& stats, const Environment& environment);
|
||||||
///< Auto equip items according to stats and item value.
|
///< Auto equip items according to stats and item value.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../mwrender/player.hpp"
|
#include "../mwrender/player.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/movement.hpp"
|
#include "../mwmechanics/movement.hpp"
|
||||||
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
|
|
||||||
#include "world.hpp"
|
#include "world.hpp"
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
|
@ -48,6 +49,12 @@ namespace MWWorld
|
||||||
mClass = new_class;
|
mClass = new_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::setDrawState(const DrawState& value)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = getPlayer();
|
||||||
|
MWWorld::Class::get(ptr).getNpcStats(ptr).mDrawState = value;
|
||||||
|
}
|
||||||
|
|
||||||
void Player::setAutoMove (bool enable)
|
void Player::setAutoMove (bool enable)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = getPlayer();
|
MWWorld::Ptr ptr = getPlayer();
|
||||||
|
@ -89,4 +96,10 @@ namespace MWWorld
|
||||||
|
|
||||||
MWWorld::Class::get (ptr).setStance (ptr, MWWorld::Class::Run, !running);
|
MWWorld::Class::get (ptr).setStance (ptr, MWWorld::Class::Run, !running);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrawState Player::getDrawState()
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = getPlayer();
|
||||||
|
return MWWorld::Class::get(ptr).getNpcStats(ptr).mDrawState;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include "../mwworld/refdata.hpp"
|
#include "../mwworld/refdata.hpp"
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/drawstate.hpp"
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
class Player;
|
class Player;
|
||||||
|
@ -31,7 +33,6 @@ namespace MWWorld
|
||||||
ESM::Class *mClass;
|
ESM::Class *mClass;
|
||||||
bool mAutoMove;
|
bool mAutoMove;
|
||||||
int mForwardBackward;
|
int mForwardBackward;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Player(MWRender::Player *renderer, const ESM::NPC *player, MWWorld::World& world);
|
Player(MWRender::Player *renderer, const ESM::NPC *player, MWWorld::World& world);
|
||||||
|
@ -76,6 +77,8 @@ namespace MWWorld
|
||||||
|
|
||||||
void setClass (const ESM::Class& class_);
|
void setClass (const ESM::Class& class_);
|
||||||
|
|
||||||
|
void setDrawState(const DrawState& state);
|
||||||
|
|
||||||
std::string getName() const
|
std::string getName() const
|
||||||
{
|
{
|
||||||
return mName;
|
return mName;
|
||||||
|
@ -106,6 +109,8 @@ namespace MWWorld
|
||||||
return mAutoMove;
|
return mAutoMove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrawState getDrawState();
|
||||||
|
|
||||||
void setAutoMove (bool enable);
|
void setAutoMove (bool enable);
|
||||||
|
|
||||||
void setLeftRight (int value);
|
void setLeftRight (int value);
|
||||||
|
|
|
@ -204,7 +204,6 @@ namespace MWWorld
|
||||||
mWorld->adjustSky();
|
mWorld->adjustSky();
|
||||||
|
|
||||||
mCellChanged = true;
|
mCellChanged = true;
|
||||||
mRendering.waterAdded(mCurrentCell);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//We need the ogre renderer and a scene node.
|
//We need the ogre renderer and a scene node.
|
||||||
|
@ -257,8 +256,6 @@ namespace MWWorld
|
||||||
mWorld->adjustSky();
|
mWorld->adjustSky();
|
||||||
|
|
||||||
mCellChanged = true;
|
mCellChanged = true;
|
||||||
|
|
||||||
mRendering.waterAdded(cell);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::changeToExteriorCell (const ESM::Position& position)
|
void Scene::changeToExteriorCell (const ESM::Position& position)
|
||||||
|
|
|
@ -335,13 +335,15 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::E
|
||||||
void WeatherManager::setWeather(const String& weather, bool instant)
|
void WeatherManager::setWeather(const String& weather, bool instant)
|
||||||
{
|
{
|
||||||
if (weather == mCurrentWeather && mNextWeather == "")
|
if (weather == mCurrentWeather && mNextWeather == "")
|
||||||
|
{
|
||||||
|
mFirstUpdate = false;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (instant || mFirstUpdate)
|
if (instant || mFirstUpdate)
|
||||||
{
|
{
|
||||||
mNextWeather = "";
|
mNextWeather = "";
|
||||||
mCurrentWeather = weather;
|
mCurrentWeather = weather;
|
||||||
mFirstUpdate = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -355,6 +357,7 @@ void WeatherManager::setWeather(const String& weather, bool instant)
|
||||||
mNextWeather = weather;
|
mNextWeather = weather;
|
||||||
mRemainingTransitionTime = mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*3600;
|
mRemainingTransitionTime = mWeatherSettings[mCurrentWeather].mTransitionDelta*24.f*3600;
|
||||||
}
|
}
|
||||||
|
mFirstUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
WeatherResult WeatherManager::getResult(const String& weather)
|
WeatherResult WeatherManager::getResult(const String& weather)
|
||||||
|
@ -472,6 +475,7 @@ WeatherResult WeatherManager::transition(float factor)
|
||||||
result.mCloudSpeed = current.mCloudSpeed;
|
result.mCloudSpeed = current.mCloudSpeed;
|
||||||
result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity);
|
result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity);
|
||||||
result.mGlareView = lerp(current.mGlareView, other.mGlareView);
|
result.mGlareView = lerp(current.mGlareView, other.mGlareView);
|
||||||
|
result.mNightFade = lerp(current.mNightFade, other.mNightFade);
|
||||||
|
|
||||||
result.mNight = current.mNight;
|
result.mNight = current.mNight;
|
||||||
|
|
||||||
|
@ -520,23 +524,23 @@ void WeatherManager::update(float duration)
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
float random = ((rand()%100)/100.f) * total;
|
float random = ((rand()%100)/100.f) * total;
|
||||||
|
|
||||||
//if (random > snow+blight+ash+thunder+rain+overcast+foggy+cloudy+clear)
|
//if (random >= snow+blight+ash+thunder+rain+overcast+foggy+cloudy+clear)
|
||||||
// weather = "blizzard";
|
// weather = "blizzard";
|
||||||
//else if (random > blight+ash+thunder+rain+overcast+foggy+cloudy+clear)
|
//else if (random >= blight+ash+thunder+rain+overcast+foggy+cloudy+clear)
|
||||||
// weather = "snow";
|
// weather = "snow";
|
||||||
/*else*/ if (random > ash+thunder+rain+overcast+foggy+cloudy+clear)
|
/*else*/ if (random >= ash+thunder+rain+overcast+foggy+cloudy+clear)
|
||||||
weather = "blight";
|
weather = "blight";
|
||||||
else if (random > thunder+rain+overcast+foggy+cloudy+clear)
|
else if (random >= thunder+rain+overcast+foggy+cloudy+clear)
|
||||||
weather = "ashstorm";
|
weather = "ashstorm";
|
||||||
else if (random > rain+overcast+foggy+cloudy+clear)
|
else if (random >= rain+overcast+foggy+cloudy+clear)
|
||||||
weather = "thunderstorm";
|
weather = "thunderstorm";
|
||||||
else if (random > overcast+foggy+cloudy+clear)
|
else if (random >= overcast+foggy+cloudy+clear)
|
||||||
weather = "rain";
|
weather = "rain";
|
||||||
else if (random > foggy+cloudy+clear)
|
else if (random >= foggy+cloudy+clear)
|
||||||
weather = "overcast";
|
weather = "overcast";
|
||||||
else if (random > cloudy+clear)
|
else if (random >= cloudy+clear)
|
||||||
weather = "foggy";
|
weather = "foggy";
|
||||||
else if (random > clear)
|
else if (random >= clear)
|
||||||
weather = "cloudy";
|
weather = "cloudy";
|
||||||
else
|
else
|
||||||
weather = "clear";
|
weather = "clear";
|
||||||
|
@ -584,8 +588,8 @@ void WeatherManager::update(float duration)
|
||||||
int facing = (mHour > 13.f) ? 1 : -1;
|
int facing = (mHour > 13.f) ? 1 : -1;
|
||||||
|
|
||||||
Vector3 final(
|
Vector3 final(
|
||||||
(1-height)*facing,
|
-(1-height)*facing,
|
||||||
(1-height)*facing,
|
-(1-height)*facing,
|
||||||
height);
|
height);
|
||||||
mRendering->setSunDirection(final);
|
mRendering->setSunDirection(final);
|
||||||
|
|
||||||
|
|
|
@ -302,6 +302,8 @@ void NIFLoader::createMaterial(const String &name,
|
||||||
|
|
||||||
if (Settings::Manager::getBool("shaders", "Objects"))
|
if (Settings::Manager::getBool("shaders", "Objects"))
|
||||||
{
|
{
|
||||||
|
bool mrt = Settings::Manager::getBool("shader", "Water");
|
||||||
|
|
||||||
// Create shader for the material
|
// Create shader for the material
|
||||||
// vertex
|
// vertex
|
||||||
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||||
|
@ -324,9 +326,8 @@ void NIFLoader::createMaterial(const String &name,
|
||||||
" out float4 oPosition : POSITION, \n"
|
" out float4 oPosition : POSITION, \n"
|
||||||
" out float4 oPositionObjSpace : TEXCOORD1, \n"
|
" out float4 oPositionObjSpace : TEXCOORD1, \n"
|
||||||
" out float4 oNormal : TEXCOORD2, \n"
|
" out float4 oNormal : TEXCOORD2, \n"
|
||||||
" out float oFogValue : TEXCOORD3, \n"
|
" out float oDepth : TEXCOORD3, \n"
|
||||||
" out float4 oVertexColour : TEXCOORD4, \n"
|
" out float4 oVertexColour : TEXCOORD4, \n"
|
||||||
" uniform float4 fogParams, \n"
|
|
||||||
" uniform float4x4 worldViewProj \n"
|
" uniform float4x4 worldViewProj \n"
|
||||||
") \n"
|
") \n"
|
||||||
"{ \n"
|
"{ \n"
|
||||||
|
@ -334,13 +335,12 @@ void NIFLoader::createMaterial(const String &name,
|
||||||
" oUV = uv; \n"
|
" oUV = uv; \n"
|
||||||
" oNormal = normal; \n"
|
" oNormal = normal; \n"
|
||||||
" oPosition = mul( worldViewProj, position ); \n"
|
" oPosition = mul( worldViewProj, position ); \n"
|
||||||
" oFogValue = saturate((oPosition.z - fogParams.y) * fogParams.w); \n"
|
" oDepth = oPosition.z; \n"
|
||||||
" oPositionObjSpace = position; \n"
|
" oPositionObjSpace = position; \n"
|
||||||
"}";
|
"}";
|
||||||
vertex->setSource(outStream.str());
|
vertex->setSource(outStream.str());
|
||||||
vertex->load();
|
vertex->load();
|
||||||
vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||||
vertex->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vertex = mgr.getByName("main_vp");
|
vertex = mgr.getByName("main_vp");
|
||||||
|
@ -370,9 +370,14 @@ void NIFLoader::createMaterial(const String &name,
|
||||||
" uniform sampler2D texture : TEXUNIT0, \n"
|
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||||
" float4 positionObjSpace : TEXCOORD1, \n"
|
" float4 positionObjSpace : TEXCOORD1, \n"
|
||||||
" float4 normal : TEXCOORD2, \n"
|
" float4 normal : TEXCOORD2, \n"
|
||||||
" float fogValue : TEXCOORD3, \n"
|
" float iDepth : TEXCOORD3, \n"
|
||||||
" float4 vertexColour : TEXCOORD4, \n"
|
" float4 vertexColour : TEXCOORD4, \n"
|
||||||
" uniform float4 fogColour, \n";
|
" uniform float4 fogColour, \n"
|
||||||
|
" uniform float4 fogParams, \n";
|
||||||
|
|
||||||
|
if (mrt) outStream <<
|
||||||
|
" out float4 oColor1 : COLOR1, \n"
|
||||||
|
" uniform float far, \n";
|
||||||
|
|
||||||
for (int i=0; i<num_lights; ++i)
|
for (int i=0; i<num_lights; ++i)
|
||||||
{
|
{
|
||||||
|
@ -408,8 +413,14 @@ void NIFLoader::createMaterial(const String &name,
|
||||||
|
|
||||||
outStream <<
|
outStream <<
|
||||||
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
|
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
|
||||||
|
" float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); \n"
|
||||||
" oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour, fogValue); \n"
|
" oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour, fogValue); \n"
|
||||||
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n"
|
" 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->setSource(outStream.str());
|
||||||
fragment->load();
|
fragment->load();
|
||||||
|
@ -425,6 +436,9 @@ void NIFLoader::createMaterial(const String &name,
|
||||||
fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
|
fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
|
||||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
|
||||||
fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
|
||||||
|
if (mrt)
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("far", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fragment = mgr.getByName("main_fp");
|
fragment = mgr.getByName("main_fp");
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
project(resources)
|
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/caustic_0.png "${OpenMW_BINARY_DIR}/resources/water/caustic_0.png" COPYONLY)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/Example_Fresnel.cg "${OpenMW_BINARY_DIR}/resources/water/Example_Fresnel.cg" 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/Example_FresnelPS.asm "${OpenMW_BINARY_DIR}/resources/water/Example_FresnelPS.asm" COPYONLY)
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/GlassFP.cg "${OpenMW_BINARY_DIR}/resources/water/GlassFP.cg" COPYONLY)
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/GlassVP.cg "${OpenMW_BINARY_DIR}/resources/water/GlassVP.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/perlinvolume.dds "${OpenMW_BINARY_DIR}/resources/water/perlinvolume.dds" COPYONLY)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/Water02.jpg "${OpenMW_BINARY_DIR}/resources/water/Water02.jpg" 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.compositor "${OpenMW_BINARY_DIR}/resources/water/water.compositor" COPYONLY)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/waves2.dds "${OpenMW_BINARY_DIR}/resources/water/waves2.dds" 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/Examples-Water.material "${OpenMW_BINARY_DIR}/resources/water/Examples-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/WaterNormal1.tga "${OpenMW_BINARY_DIR}/resources/water/WaterNormal1.tga" COPYONLY)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.cg "${OpenMW_BINARY_DIR}/resources/water/water.cg" COPYONLY)
|
||||||
|
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.cg "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.cg" COPYONLY)
|
||||||
|
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)
|
||||||
|
|
18
files/gbuffer/gbuffer.cg
Normal file
18
files/gbuffer/gbuffer.cg
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
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;
|
||||||
|
}
|
95
files/gbuffer/gbuffer.compositor
Normal file
95
files/gbuffer/gbuffer.compositor
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
// Compositor that just controls output to the MRT textures
|
||||||
|
compositor gbuffer
|
||||||
|
{
|
||||||
|
technique
|
||||||
|
{
|
||||||
|
// MRT output. Currently this is a color texture plus a depth texture
|
||||||
|
texture mrt_output target_width target_height PF_FLOAT16_RGBA PF_FLOAT16_RGBA chain_scope depth_pool 2
|
||||||
|
|
||||||
|
target mrt_output
|
||||||
|
{
|
||||||
|
input none
|
||||||
|
pass clear
|
||||||
|
{
|
||||||
|
clear
|
||||||
|
{
|
||||||
|
// make sure to set this to the viewport background color from outside
|
||||||
|
colour_value 0 0 0 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pass render_scene
|
||||||
|
{
|
||||||
|
// Renders everything except water
|
||||||
|
first_render_queue 0
|
||||||
|
last_render_queue 70
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
target_output
|
||||||
|
{
|
||||||
|
input none
|
||||||
|
|
||||||
|
pass render_quad
|
||||||
|
{
|
||||||
|
material RenderScene
|
||||||
|
input 0 mrt_output 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finalizer compositor to render objects that we don't want in the MRT textures (ex. water)
|
||||||
|
// NB the water has to be rendered in a seperate compositor anyway, because it
|
||||||
|
// accesses the MRT textures which can't be done while they are still being rendered to.
|
||||||
|
compositor gbufferFinalizer
|
||||||
|
{
|
||||||
|
technique
|
||||||
|
{
|
||||||
|
texture no_mrt_output target_width target_height PF_R8G8B8A8 depth_pool 2 no_fsaa
|
||||||
|
texture previousscene target_width target_height PF_R8G8B8A8
|
||||||
|
|
||||||
|
target previousscene
|
||||||
|
{
|
||||||
|
input previous
|
||||||
|
}
|
||||||
|
target no_mrt_output
|
||||||
|
{
|
||||||
|
input none
|
||||||
|
shadows off
|
||||||
|
pass clear
|
||||||
|
{
|
||||||
|
clear
|
||||||
|
{
|
||||||
|
buffers colour
|
||||||
|
colour_value 0 0 0 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pass render_quad
|
||||||
|
{
|
||||||
|
material RenderSceneNoDepth
|
||||||
|
input 0 previousscene
|
||||||
|
}
|
||||||
|
pass render_scene
|
||||||
|
{
|
||||||
|
first_render_queue 71
|
||||||
|
last_render_queue 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target_output
|
||||||
|
{
|
||||||
|
input none
|
||||||
|
pass clear
|
||||||
|
{
|
||||||
|
clear
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pass render_quad
|
||||||
|
{
|
||||||
|
material RenderSceneNoDepth
|
||||||
|
input 0 no_mrt_output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
63
files/gbuffer/gbuffer.material
Normal file
63
files/gbuffer/gbuffer.material
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,12 @@
|
||||||
|
# WARNING: Editing this file might have no effect, as these
|
||||||
|
# settings are overwritten by your user settings file.
|
||||||
|
|
||||||
[General]
|
[General]
|
||||||
# Camera field of view
|
# Camera field of view
|
||||||
field of view = 55
|
field of view = 55
|
||||||
|
|
||||||
# Texture filtering mode. valid values:
|
# Texture filtering mode. valid values:
|
||||||
|
# none
|
||||||
# anisotropic
|
# anisotropic
|
||||||
# bilinear
|
# bilinear
|
||||||
# trilinear
|
# trilinear
|
||||||
|
@ -54,6 +58,26 @@ fog end factor = 1.0
|
||||||
# Max. number of lights that affect the terrain. Setting to 1 will only reflect sunlight
|
# Max. number of lights that affect the terrain. Setting to 1 will only reflect sunlight
|
||||||
num lights = 8
|
num lights = 8
|
||||||
|
|
||||||
|
[Water]
|
||||||
|
# Enable this to get fancy-looking water with reflections and refractions
|
||||||
|
# All the settings below have no effect if this is false
|
||||||
|
shader = true
|
||||||
|
|
||||||
|
rtt size = 512
|
||||||
|
|
||||||
|
reflect terrain = true
|
||||||
|
|
||||||
|
reflect statics = false
|
||||||
|
|
||||||
|
reflect small statics = false
|
||||||
|
|
||||||
|
reflect actors = true
|
||||||
|
|
||||||
|
reflect misc = false
|
||||||
|
|
||||||
|
# Enable underwater effect. It is not resource intensive, so only disable it if you have problems.
|
||||||
|
underwater effect = true
|
||||||
|
|
||||||
[Sound]
|
[Sound]
|
||||||
# Device name. Blank means default
|
# Device name. Blank means default
|
||||||
device =
|
device =
|
||||||
|
|
|
@ -1,116 +0,0 @@
|
||||||
// Vertex program for fresnel reflections / refractions
|
|
||||||
void main_vp(
|
|
||||||
float4 pos : POSITION,
|
|
||||||
float4 normal : NORMAL,
|
|
||||||
float2 tex : TEXCOORD0,
|
|
||||||
|
|
||||||
out float4 oPos : POSITION,
|
|
||||||
out float3 noiseCoord : TEXCOORD0,
|
|
||||||
out float4 projectionCoord : TEXCOORD1,
|
|
||||||
out float3 oEyeDir : TEXCOORD2,
|
|
||||||
out float3 oNormal : TEXCOORD3,
|
|
||||||
|
|
||||||
uniform float4x4 worldViewProjMatrix,
|
|
||||||
uniform float3 eyePosition, // object space
|
|
||||||
uniform float timeVal,
|
|
||||||
uniform float scale, // the amount to scale the noise texture by
|
|
||||||
uniform float scroll, // the amount by which to scroll the noise
|
|
||||||
uniform float noise // the noise perturb as a factor of the time
|
|
||||||
)
|
|
||||||
{
|
|
||||||
oPos = mul(worldViewProjMatrix, pos);
|
|
||||||
// Projective texture coordinates, adjust for mapping
|
|
||||||
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);
|
|
||||||
projectionCoord = mul(scalemat, oPos);
|
|
||||||
// Noise map coords
|
|
||||||
noiseCoord.xy = (tex + (timeVal * scroll)) * scale;
|
|
||||||
noiseCoord.z = noise * timeVal;
|
|
||||||
|
|
||||||
oEyeDir = normalize(pos.xyz - eyePosition);
|
|
||||||
oNormal = normal.rgb;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fragment program for distorting a texture using a 3D noise texture
|
|
||||||
void main_fp(
|
|
||||||
float3 noiseCoord : TEXCOORD0,
|
|
||||||
float4 projectionCoord : TEXCOORD1,
|
|
||||||
float3 eyeDir : TEXCOORD2,
|
|
||||||
float3 normal : TEXCOORD3,
|
|
||||||
|
|
||||||
out float4 col : COLOR,
|
|
||||||
|
|
||||||
uniform float4 tintColour,
|
|
||||||
uniform float noiseScale,
|
|
||||||
uniform float fresnelBias,
|
|
||||||
uniform float fresnelScale,
|
|
||||||
uniform float fresnelPower,
|
|
||||||
uniform sampler2D waterTex : register(s0),
|
|
||||||
uniform sampler2D noiseMap : register(s1),
|
|
||||||
uniform sampler2D reflectMap : register(s2),
|
|
||||||
uniform sampler2D refractMap : register(s3)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Do the tex projection manually so we can distort _after_
|
|
||||||
float2 final = projectionCoord.xy / projectionCoord.w;
|
|
||||||
|
|
||||||
// Noise
|
|
||||||
float3 noiseNormal = (tex2D(noiseMap, (noiseCoord.xy / 5)).rgb - 0.5).rbg * noiseScale;
|
|
||||||
final += noiseNormal.xz;
|
|
||||||
|
|
||||||
// Fresnel
|
|
||||||
//normal = normalize(normal + noiseNormal.xz);
|
|
||||||
float fresnel = fresnelBias + fresnelScale * pow(1 + dot(eyeDir, normal), fresnelPower);
|
|
||||||
|
|
||||||
// Reflection / refraction
|
|
||||||
float4 reflectionColour = tex2D(reflectMap, final);
|
|
||||||
float4 refractionColour = tex2D(refractMap, final) + tintColour;
|
|
||||||
|
|
||||||
// Final colour
|
|
||||||
col = lerp(refractionColour, reflectionColour, fresnel) * tex2D(waterTex, noiseNormal) / 3 ;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Old version to match ATI PS 1.3 implementation
|
|
||||||
void main_vp_old(
|
|
||||||
float4 pos : POSITION,
|
|
||||||
float4 normal : NORMAL,
|
|
||||||
float2 tex : TEXCOORD0,
|
|
||||||
|
|
||||||
out float4 oPos : POSITION,
|
|
||||||
out float fresnel : COLOR,
|
|
||||||
out float3 noiseCoord : TEXCOORD0,
|
|
||||||
out float4 projectionCoord : TEXCOORD1,
|
|
||||||
|
|
||||||
uniform float4x4 worldViewProjMatrix,
|
|
||||||
uniform float3 eyePosition, // object space
|
|
||||||
uniform float fresnelBias,
|
|
||||||
uniform float fresnelScale,
|
|
||||||
uniform float fresnelPower,
|
|
||||||
uniform float timeVal,
|
|
||||||
uniform float scale, // the amount to scale the noise texture by
|
|
||||||
uniform float scroll, // the amount by which to scroll the noise
|
|
||||||
uniform float noise // the noise perturb as a factor of the time
|
|
||||||
)
|
|
||||||
{
|
|
||||||
oPos = mul(worldViewProjMatrix, pos);
|
|
||||||
// Projective texture coordinates, adjust for mapping
|
|
||||||
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);
|
|
||||||
projectionCoord = mul(scalemat, oPos);
|
|
||||||
// Noise map coords
|
|
||||||
noiseCoord.xy = (tex + (timeVal * scroll)) * scale;
|
|
||||||
noiseCoord.z = noise * timeVal;
|
|
||||||
|
|
||||||
// calc fresnel factor (reflection coefficient)
|
|
||||||
float3 eyeDir = normalize(pos.xyz - eyePosition);
|
|
||||||
fresnel = fresnelBias + fresnelScale * pow(1 + dot(eyeDir, normal), fresnelPower);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
ps.1.4
|
|
||||||
// conversion from Cg generated ARB_fragment_program to ps.1.4 by NFZ
|
|
||||||
// command line args: -profile arbfp1 -entry main_fp
|
|
||||||
// program main_fp
|
|
||||||
// c0 : distortionRange
|
|
||||||
// c1 : tintColour
|
|
||||||
// testure 0 : noiseMap
|
|
||||||
// texture 1 : reflectMap
|
|
||||||
// texture 2 : refractMap
|
|
||||||
// v0.x : fresnel
|
|
||||||
// t0.xyz : noiseCoord
|
|
||||||
// t1.xyw : projectionCoord
|
|
||||||
|
|
||||||
def c2, 2, 1, 0, 0
|
|
||||||
|
|
||||||
// Cg: distort.x = tex3D(noiseMap, noiseCoord).x;
|
|
||||||
// arbfp1: TEX R0.x, fragment.texcoord[0], texture[0], 3D;
|
|
||||||
// sample noise map using noiseCoord in TEX unit 0
|
|
||||||
|
|
||||||
texld r0, t0.xyz
|
|
||||||
|
|
||||||
// get projected texture coordinates from TEX coord 1
|
|
||||||
// will be used in phase 2
|
|
||||||
|
|
||||||
texcrd r1.xy, t1_dw.xyw
|
|
||||||
mov r1.z, c2.y
|
|
||||||
|
|
||||||
// Cg: distort.y = tex3D(noiseMap, noiseCoord + yoffset).x;
|
|
||||||
// arbfp1: ADD R1.xyz, fragment.texcoord[0], c1;
|
|
||||||
// arbfp1: TEX R1.x, R1, texture[0], 3D;
|
|
||||||
// arbfp1: MOV R0.y, R1.x;
|
|
||||||
|
|
||||||
// Cg: distort = (distort * 2 - 1) * distortionRange;
|
|
||||||
// arbfp1: MAD R0.xy, R0, c0.x, -c0.y;
|
|
||||||
// arbfp1: MUL R0.xy, R0, u0.x;
|
|
||||||
// (distort * 2 - 1) same as 2*(distort -.5) so use _bx2
|
|
||||||
|
|
||||||
|
|
||||||
// Cg: final = projectionCoord.xy / projectionCoord.w;
|
|
||||||
// Cg: final += distort;
|
|
||||||
// arbfp1: RCP R0.w, fragment.texcoord[1].w;
|
|
||||||
// arbfp1: MAD R0.xy, fragment.texcoord[1], R0.w, R0;
|
|
||||||
// final = (distort * projectionCoord.w) + projectionCoord.xy
|
|
||||||
// for ps.1.4 have to re-arrange things a bit to perturb projected texture coordinates
|
|
||||||
|
|
||||||
mad r0.xyz, r0_bx2, c0.x, r1
|
|
||||||
|
|
||||||
phase
|
|
||||||
|
|
||||||
// do dependant texture reads
|
|
||||||
// Cg: reflectionColour = tex2D(reflectMap, final);
|
|
||||||
// arbfp1: TEX R0, R0, texture[1], 2D;
|
|
||||||
// sampe reflectMap using dependant read : texunit 1
|
|
||||||
|
|
||||||
texld r1, r0.xyz
|
|
||||||
|
|
||||||
// Cg: refractionColour = tex2D(refractMap, final) + tintColour;
|
|
||||||
// arbfp1: TEX R1, R0, texture[2], 2D;
|
|
||||||
// sample refractMap : texunit 2
|
|
||||||
|
|
||||||
texld r2, r0.xyz
|
|
||||||
|
|
||||||
// adding tintColour that is in global c1
|
|
||||||
// arbfp1: ADD R1, R1, u1;
|
|
||||||
|
|
||||||
add r2, r2, c1
|
|
||||||
|
|
||||||
// Cg: col = lerp(refractionColour, reflectionColour, fresnel);
|
|
||||||
// arbfp1: ADD R0, R0, -R1;
|
|
||||||
// arbfp1: MAD result.color, fragment.color.primary.x, R0, R1;
|
|
||||||
|
|
||||||
lrp r0, v0.x, r1, r2
|
|
|
@ -1,149 +0,0 @@
|
||||||
|
|
||||||
vertex_program Water/GlassVP cg
|
|
||||||
{
|
|
||||||
source GlassVP.cg
|
|
||||||
entry_point glass_vp
|
|
||||||
profiles vs_1_1 arbvp1
|
|
||||||
|
|
||||||
default_params
|
|
||||||
{
|
|
||||||
param_named_auto worldViewProj worldviewproj_matrix
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fragment_program Water/GlassFP cg
|
|
||||||
{
|
|
||||||
source GlassFP.cg
|
|
||||||
entry_point main_ps
|
|
||||||
profiles ps_2_0 arbfp1
|
|
||||||
}
|
|
||||||
|
|
||||||
material Water/Compositor
|
|
||||||
{
|
|
||||||
technique
|
|
||||||
{
|
|
||||||
pass
|
|
||||||
{
|
|
||||||
depth_check off
|
|
||||||
vertex_program_ref Water/GlassVP
|
|
||||||
{
|
|
||||||
param_named_auto timeVal time 0.25
|
|
||||||
param_named scale float 0.1
|
|
||||||
}
|
|
||||||
|
|
||||||
fragment_program_ref Water/GlassFP
|
|
||||||
{
|
|
||||||
param_named tintColour float4 0 0.35 0.35 1
|
|
||||||
}
|
|
||||||
|
|
||||||
texture_unit RT
|
|
||||||
{
|
|
||||||
tex_coord_set 0
|
|
||||||
tex_address_mode clamp
|
|
||||||
filtering linear linear linear
|
|
||||||
}
|
|
||||||
|
|
||||||
texture_unit
|
|
||||||
{
|
|
||||||
texture WaterNormal1.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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vertex_program Water/RefractReflectVP cg
|
|
||||||
{
|
|
||||||
source Example_Fresnel.cg
|
|
||||||
entry_point main_vp
|
|
||||||
profiles vs_1_1 arbvp1
|
|
||||||
}
|
|
||||||
vertex_program Water/RefractReflectVPold cg
|
|
||||||
{
|
|
||||||
source Example_Fresnel.cg
|
|
||||||
entry_point main_vp_old
|
|
||||||
profiles vs_1_1 arbvp1
|
|
||||||
}
|
|
||||||
|
|
||||||
fragment_program Water/RefractReflectFP cg
|
|
||||||
{
|
|
||||||
source Example_Fresnel.cg
|
|
||||||
entry_point main_fp
|
|
||||||
// sorry, ps_1_1 and fp20 can't do this
|
|
||||||
profiles ps_2_0 arbfp1
|
|
||||||
}
|
|
||||||
|
|
||||||
fragment_program Water/RefractReflectPS asm
|
|
||||||
{
|
|
||||||
source Example_FresnelPS.asm
|
|
||||||
// sorry, only for ps_1_4 :)
|
|
||||||
syntax ps_1_4
|
|
||||||
|
|
||||||
}
|
|
||||||
material Examples/Water0
|
|
||||||
{
|
|
||||||
|
|
||||||
technique
|
|
||||||
{
|
|
||||||
pass
|
|
||||||
{
|
|
||||||
//
|
|
||||||
|
|
||||||
depth_write off
|
|
||||||
vertex_program_ref Water/RefractReflectVP
|
|
||||||
{
|
|
||||||
param_named_auto worldViewProjMatrix worldviewproj_matrix
|
|
||||||
param_named_auto eyePosition camera_position_object_space
|
|
||||||
param_named_auto timeVal time 0.15
|
|
||||||
param_named scroll float 1
|
|
||||||
param_named scale float 1
|
|
||||||
param_named noise float 1
|
|
||||||
// scroll and noisePos will need updating per frame
|
|
||||||
}
|
|
||||||
fragment_program_ref Water/RefractReflectFP
|
|
||||||
{
|
|
||||||
param_named fresnelBias float -0.1
|
|
||||||
param_named fresnelScale float 0.8
|
|
||||||
param_named fresnelPower float 20
|
|
||||||
param_named tintColour float4 1 1 1 1
|
|
||||||
param_named noiseScale float 0.05
|
|
||||||
}
|
|
||||||
// Water
|
|
||||||
scene_blend alpha_blend
|
|
||||||
texture_unit
|
|
||||||
{
|
|
||||||
|
|
||||||
// Water texture
|
|
||||||
texture Water02.jpg
|
|
||||||
// min / mag filtering, no mip
|
|
||||||
filtering linear linear none
|
|
||||||
alpha_op_ex source1 src_manual src_current 0.9
|
|
||||||
|
|
||||||
}
|
|
||||||
// Noise
|
|
||||||
texture_unit
|
|
||||||
{
|
|
||||||
alpha_op_ex source1 src_manual src_current 0.9
|
|
||||||
// Perlin noise volume
|
|
||||||
texture waves2.dds
|
|
||||||
// min / mag filtering, no mip
|
|
||||||
filtering linear linear none
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
sampler RT : register(s0);
|
|
||||||
sampler NormalMap : register(s1);
|
|
||||||
sampler CausticMap : register(s2);
|
|
||||||
|
|
||||||
float4 main_ps(float2 iTexCoord : TEXCOORD0,
|
|
||||||
float3 noiseCoord : TEXCOORD1,
|
|
||||||
uniform float4 tintColour) : COLOR
|
|
||||||
{
|
|
||||||
float4 normal = tex2D(NormalMap, noiseCoord);
|
|
||||||
|
|
||||||
|
|
||||||
return tex2D(RT, iTexCoord + normal.xy * 0.05) +
|
|
||||||
(tex2D(CausticMap, noiseCoord) / 5) +
|
|
||||||
tintColour ;
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
void glass_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;
|
|
||||||
}
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 182 KiB |
Binary file not shown.
Before Width: | Height: | Size: 192 KiB |
BIN
files/water/WaterNormal2.tga
Normal file
BIN
files/water/WaterNormal2.tga
Normal file
Binary file not shown.
After Width: | Height: | Size: 192 KiB |
61
files/water/underwater.cg
Normal file
61
files/water/underwater.cg
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
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),
|
||||||
|
uniform float4 tintColour) : COLOR
|
||||||
|
{
|
||||||
|
float4 normal = tex2D(NormalMap, noiseCoord) * 2 - 1;
|
||||||
|
|
||||||
|
return tex2D(RT, iTexCoord + normal.xy * 0.015) +
|
||||||
|
(tex2D(CausticMap, noiseCoord) / 5) +
|
||||||
|
tintColour ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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),
|
||||||
|
uniform float4 tintColour) : 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) +
|
||||||
|
tintColour;
|
||||||
|
|
||||||
|
return lerp(color, float4(0, 0.65, 0.65, 1), depth);
|
||||||
|
}
|
121
files/water/water.cg
Normal file
121
files/water/water.cg
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
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 += isUnderwater * float3(0, 0.35, 0.35); // underwater tint color
|
||||||
|
oColor.xyz = lerp(oColor.xyz, float3(0, 0.65, 0.65), 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,4 +1,4 @@
|
||||||
compositor Water
|
compositor UnderwaterNoMRT
|
||||||
{
|
{
|
||||||
technique
|
technique
|
||||||
{
|
{
|
||||||
|
@ -13,9 +13,34 @@ compositor Water
|
||||||
|
|
||||||
pass render_quad
|
pass render_quad
|
||||||
{
|
{
|
||||||
material Water/Compositor
|
material Water/CompositorNoMRT
|
||||||
input 0 rt0
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
198
files/water/water.material
Normal file
198
files/water/water.material
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
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 Map
|
||||||
|
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
|
||||||
|
{
|
||||||
|
param_named tintColour float4 0 0.35 0.35 1
|
||||||
|
}
|
||||||
|
|
||||||
|
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 tintColour float4 0 0.35 0.35 1
|
||||||
|
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.
Loading…
Reference in a new issue