mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:23:52 +00:00
Merge branch 'master' into physicsaedra2
Conflicts: apps/openmw/mwworld/player.cpp
This commit is contained in:
commit
f2fae770d4
75 changed files with 3365 additions and 821 deletions
|
@ -97,6 +97,7 @@ set(OENGINE_OGRE
|
||||||
${LIBDIR}/openengine/ogre/renderer.cpp
|
${LIBDIR}/openengine/ogre/renderer.cpp
|
||||||
${LIBDIR}/openengine/ogre/mouselook.cpp
|
${LIBDIR}/openengine/ogre/mouselook.cpp
|
||||||
${LIBDIR}/openengine/ogre/fader.cpp
|
${LIBDIR}/openengine/ogre/fader.cpp
|
||||||
|
${LIBDIR}/openengine/ogre/imagerotate.cpp
|
||||||
)
|
)
|
||||||
set(OENGINE_GUI
|
set(OENGINE_GUI
|
||||||
${LIBDIR}/openengine/gui/events.cpp
|
${LIBDIR}/openengine/gui/events.cpp
|
||||||
|
@ -231,6 +232,9 @@ endif (APPLE)
|
||||||
configure_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg
|
configure_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg
|
||||||
"${OpenMW_BINARY_DIR}/settings-default.cfg")
|
"${OpenMW_BINARY_DIR}/settings-default.cfg")
|
||||||
|
|
||||||
|
configure_file(${OpenMW_SOURCE_DIR}/files/transparency-overrides.cfg
|
||||||
|
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg")
|
||||||
|
|
||||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
|
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
|
||||||
"${OpenMW_BINARY_DIR}/openmw.cfg")
|
"${OpenMW_BINARY_DIR}/openmw.cfg")
|
||||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
|
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
|
||||||
|
@ -312,6 +316,7 @@ if(DPKG_PROGRAM)
|
||||||
|
|
||||||
#Install global configuration files
|
#Install global configuration files
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||||
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "../etc/openmw/" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "../etc/openmw/" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
|
||||||
|
|
||||||
add_openmw_dir (mwrender
|
add_openmw_dir (mwrender
|
||||||
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
|
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
|
||||||
renderinginterface localmap occlusionquery terrain terrainmaterial water
|
renderinginterface localmap occlusionquery terrain terrainmaterial water shadows shaderhelper
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
|
@ -25,7 +25,7 @@ add_openmw_dir (mwinput
|
||||||
add_openmw_dir (mwgui
|
add_openmw_dir (mwgui
|
||||||
layouts text_input widgets race class birth review window_manager console dialogue
|
layouts text_input widgets race class birth review window_manager console dialogue
|
||||||
dialogue_history window_base stats_window messagebox journalwindow charactercreation
|
dialogue_history window_base stats_window messagebox journalwindow charactercreation
|
||||||
map_window window_pinnable_base
|
map_window window_pinnable_base cursorreplace
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwdialogue
|
add_openmw_dir (mwdialogue
|
||||||
|
@ -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 spells
|
||||||
)
|
)
|
||||||
|
|
||||||
# Main executable
|
# Main executable
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <components/files/fixedpath.hpp>
|
#include <components/files/fixedpath.hpp>
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
#include <components/nifoverrides/nifoverrides.hpp>
|
||||||
|
|
||||||
#include <components/nifbullet/bullet_nif_loader.hpp>
|
#include <components/nifbullet/bullet_nif_loader.hpp>
|
||||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||||
|
@ -28,6 +29,7 @@
|
||||||
#include "mwinput/inputmanager.hpp"
|
#include "mwinput/inputmanager.hpp"
|
||||||
|
|
||||||
#include "mwgui/window_manager.hpp"
|
#include "mwgui/window_manager.hpp"
|
||||||
|
#include "mwgui/cursorreplace.hpp"
|
||||||
|
|
||||||
#include "mwscript/scriptmanager.hpp"
|
#include "mwscript/scriptmanager.hpp"
|
||||||
#include "mwscript/compilercontext.hpp"
|
#include "mwscript/compilercontext.hpp"
|
||||||
|
@ -349,6 +351,13 @@ void OMW::Engine::go()
|
||||||
|
|
||||||
mFpsLevel = settings.getInt("fps", "HUD");
|
mFpsLevel = settings.getInt("fps", "HUD");
|
||||||
|
|
||||||
|
// load nif overrides
|
||||||
|
NifOverrides::Overrides nifOverrides;
|
||||||
|
if (boost::filesystem::exists(mCfgMgr.getLocalPath().string() + "/transparency-overrides.cfg"))
|
||||||
|
nifOverrides.loadTransparencyOverrides(mCfgMgr.getLocalPath().string() + "/transparency-overrides.cfg");
|
||||||
|
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"))
|
||||||
|
nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg");
|
||||||
|
|
||||||
mOgre->configure(!boost::filesystem::is_regular_file(mCfgMgr.getOgreConfigPath()),
|
mOgre->configure(!boost::filesystem::is_regular_file(mCfgMgr.getOgreConfigPath()),
|
||||||
mCfgMgr.getOgreConfigPath().string(),
|
mCfgMgr.getOgreConfigPath().string(),
|
||||||
mCfgMgr.getLogPath().string(),
|
mCfgMgr.getLogPath().string(),
|
||||||
|
@ -361,12 +370,17 @@ void OMW::Engine::go()
|
||||||
|
|
||||||
addResourcesDirectory(mResDir / "mygui");
|
addResourcesDirectory(mResDir / "mygui");
|
||||||
addResourcesDirectory(mResDir / "water");
|
addResourcesDirectory(mResDir / "water");
|
||||||
|
addResourcesDirectory(mResDir / "gbuffer");
|
||||||
|
addResourcesDirectory(mResDir / "shadows");
|
||||||
|
|
||||||
// Create the window
|
// Create the window
|
||||||
mOgre->createWindow("OpenMW");
|
mOgre->createWindow("OpenMW");
|
||||||
|
|
||||||
loadBSA();
|
loadBSA();
|
||||||
|
|
||||||
|
// cursor replacer (converts the cursor from the bsa so they can be used by mygui)
|
||||||
|
MWGui::CursorReplace replacer;
|
||||||
|
|
||||||
// Create the world
|
// Create the world
|
||||||
mEnvironment.mWorld = new MWWorld::World (*mOgre, mFileCollections, mMaster,
|
mEnvironment.mWorld = new MWWorld::World (*mOgre, mFileCollections, mMaster,
|
||||||
mResDir, mNewGame, mEnvironment, mEncoding, mFallbackMap);
|
mResDir, mNewGame, mEnvironment, mEncoding, mFallbackMap);
|
||||||
|
|
|
@ -61,6 +61,10 @@ namespace MWClass
|
||||||
for (int i=0; i<27; ++i)
|
for (int i=0; i<27; ++i)
|
||||||
data->mNpcStats.mSkill[i].setBase (ref->base->npdt52.skills[i]);
|
data->mNpcStats.mSkill[i].setBase (ref->base->npdt52.skills[i]);
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator iter (ref->base->spells.list.begin());
|
||||||
|
iter!=ref->base->spells.list.end(); ++iter)
|
||||||
|
data->mCreatureStats.mSpells.add (*iter);
|
||||||
|
|
||||||
// creature stats
|
// creature stats
|
||||||
data->mCreatureStats.mAttributes[0].set (ref->base->npdt52.strength);
|
data->mCreatureStats.mAttributes[0].set (ref->base->npdt52.strength);
|
||||||
data->mCreatureStats.mAttributes[1].set (ref->base->npdt52.intelligence);
|
data->mCreatureStats.mAttributes[1].set (ref->base->npdt52.intelligence);
|
||||||
|
|
16
apps/openmw/mwgui/cursorreplace.cpp
Normal file
16
apps/openmw/mwgui/cursorreplace.cpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include "cursorreplace.hpp"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <openengine/ogre/imagerotate.hpp>
|
||||||
|
|
||||||
|
#include <OgreResourceGroupManager.h>
|
||||||
|
#include <OgreRoot.h>
|
||||||
|
|
||||||
|
using namespace MWGui;
|
||||||
|
|
||||||
|
CursorReplace::CursorReplace()
|
||||||
|
{
|
||||||
|
OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_vresize.png", 90);
|
||||||
|
OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_dresize1.png", -45);
|
||||||
|
OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_dresize2.png", 45);
|
||||||
|
}
|
16
apps/openmw/mwgui/cursorreplace.hpp
Normal file
16
apps/openmw/mwgui/cursorreplace.hpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef GAME_CURSORREPLACE_H
|
||||||
|
#define GAME_CURSORREPLACE_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace MWGui
|
||||||
|
{
|
||||||
|
/// \brief MyGUI does not support rotating cursors, so we have to do it manually
|
||||||
|
class CursorReplace
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CursorReplace();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -66,6 +66,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
|
||||||
};
|
};
|
||||||
|
@ -87,6 +89,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();
|
||||||
|
@ -198,7 +232,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);
|
||||||
|
|
||||||
|
@ -243,6 +280,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.
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "stat.hpp"
|
#include "stat.hpp"
|
||||||
#include "magiceffects.hpp"
|
#include "magiceffects.hpp"
|
||||||
|
#include "spells.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
@ -14,7 +15,7 @@ namespace MWMechanics
|
||||||
Stat<int> mAttributes[8];
|
Stat<int> mAttributes[8];
|
||||||
DynamicStat<int> mDynamic[3]; // health, magicka, fatigue
|
DynamicStat<int> mDynamic[3]; // health, magicka, fatigue
|
||||||
int mLevel;
|
int mLevel;
|
||||||
std::set<std::string> mAbilities;
|
Spells mSpells;
|
||||||
MagicEffects mMagicEffects;
|
MagicEffects mMagicEffects;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
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
|
|
@ -23,7 +23,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
// reset
|
// reset
|
||||||
creatureStats.mLevel = player->npdt52.level;
|
creatureStats.mLevel = player->npdt52.level;
|
||||||
creatureStats.mAbilities.clear();
|
creatureStats.mSpells.clear();
|
||||||
creatureStats.mMagicEffects = MagicEffects();
|
creatureStats.mMagicEffects = MagicEffects();
|
||||||
|
|
||||||
for (int i=0; i<27; ++i)
|
for (int i=0; i<27; ++i)
|
||||||
|
@ -71,7 +71,7 @@ namespace MWMechanics
|
||||||
for (std::vector<std::string>::const_iterator iter (race->powers.list.begin());
|
for (std::vector<std::string>::const_iterator iter (race->powers.list.begin());
|
||||||
iter!=race->powers.list.end(); ++iter)
|
iter!=race->powers.list.end(); ++iter)
|
||||||
{
|
{
|
||||||
insertSpell (*iter, ptr);
|
creatureStats.mSpells.add (*iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ namespace MWMechanics
|
||||||
for (std::vector<std::string>::const_iterator iter (sign->powers.list.begin());
|
for (std::vector<std::string>::const_iterator iter (sign->powers.list.begin());
|
||||||
iter!=sign->powers.list.end(); ++iter)
|
iter!=sign->powers.list.end(); ++iter)
|
||||||
{
|
{
|
||||||
insertSpell (*iter, ptr);
|
creatureStats.mSpells.add (*iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,59 +159,14 @@ namespace MWMechanics
|
||||||
creatureStats.mDynamic[i].setCurrent (creatureStats.mDynamic[i].getModified());
|
creatureStats.mDynamic[i].setCurrent (creatureStats.mDynamic[i].getModified());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MechanicsManager::insertSpell (const std::string& id, MWWorld::Ptr& creature)
|
|
||||||
{
|
|
||||||
MWMechanics::CreatureStats& creatureStats =
|
|
||||||
MWWorld::Class::get (creature).getCreatureStats (creature);
|
|
||||||
|
|
||||||
const ESM::Spell *spell = mEnvironment.mWorld->getStore().spells.find (id);
|
|
||||||
|
|
||||||
switch (spell->data.type)
|
|
||||||
{
|
|
||||||
case ESM::Spell::ST_Ability:
|
|
||||||
|
|
||||||
if (creatureStats.mAbilities.find (id)==creatureStats.mAbilities.end())
|
|
||||||
{
|
|
||||||
creatureStats.mAbilities.insert (id);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
// TODO ST_SPELL, ST_Blight, ST_Disease, ST_Curse, ST_Power
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
std::cout
|
|
||||||
<< "adding unsupported spell type (" << spell->data.type
|
|
||||||
<< ") to creature: " << id << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MechanicsManager::adjustMagicEffects (MWWorld::Ptr& creature)
|
void MechanicsManager::adjustMagicEffects (MWWorld::Ptr& creature)
|
||||||
{
|
{
|
||||||
MWMechanics::CreatureStats& creatureStats =
|
MWMechanics::CreatureStats& creatureStats =
|
||||||
MWWorld::Class::get (creature).getCreatureStats (creature);
|
MWWorld::Class::get (creature).getCreatureStats (creature);
|
||||||
|
|
||||||
MagicEffects now;
|
MagicEffects now = creatureStats.mSpells.getMagicEffects (mEnvironment);
|
||||||
|
|
||||||
for (std::set<std::string>::const_iterator iter (creatureStats.mAbilities.begin());
|
/// \todo add effects from active spells and equipment
|
||||||
iter!=creatureStats.mAbilities.end(); ++iter)
|
|
||||||
{
|
|
||||||
const ESM::Spell *spell = mEnvironment.mWorld->getStore().spells.find (*iter);
|
|
||||||
|
|
||||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter = spell->effects.list.begin();
|
|
||||||
iter!=spell->effects.list.end(); ++iter)
|
|
||||||
{
|
|
||||||
if (iter->range==0) // self
|
|
||||||
{
|
|
||||||
EffectParam param;
|
|
||||||
param.mMagnitude = iter->magnMax; // TODO calculate magnitude
|
|
||||||
now.add (EffectKey (*iter), param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO add effects from other spell types, active spells and equipment
|
|
||||||
|
|
||||||
MagicEffects diff = MagicEffects::diff (creatureStats.mMagicEffects, now);
|
MagicEffects diff = MagicEffects::diff (creatureStats.mMagicEffects, now);
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,6 @@ namespace MWMechanics
|
||||||
///< build player according to stored class/race/birthsign information. Will
|
///< build player according to stored class/race/birthsign information. Will
|
||||||
/// default to the values of the ESM::NPC object, if no explicit information is given.
|
/// default to the values of the ESM::NPC object, if no explicit information is given.
|
||||||
|
|
||||||
void insertSpell (const std::string& id, MWWorld::Ptr& creature);
|
|
||||||
|
|
||||||
void adjustMagicEffects (MWWorld::Ptr& creature);
|
void adjustMagicEffects (MWWorld::Ptr& creature);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -2,14 +2,19 @@
|
||||||
#define GAME_MWMECHANICS_NPCSTATS_H
|
#define GAME_MWMECHANICS_NPCSTATS_H
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#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.
|
||||||
|
///
|
||||||
|
/// \note For technical reasons the spell list and the currently selected spell is also handled by
|
||||||
|
/// CreatureStats, even though they are actually NPC stats.
|
||||||
|
|
||||||
struct NpcStats
|
struct NpcStats
|
||||||
{
|
{
|
||||||
|
@ -24,9 +29,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) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
81
apps/openmw/mwmechanics/spells.cpp
Normal file
81
apps/openmw/mwmechanics/spells.cpp
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
|
||||||
|
#include "spells.hpp"
|
||||||
|
|
||||||
|
#include <components/esm/loadspel.hpp>
|
||||||
|
|
||||||
|
#include "../mwworld/environment.hpp"
|
||||||
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
|
#include "magiceffects.hpp"
|
||||||
|
|
||||||
|
namespace MWMechanics
|
||||||
|
{
|
||||||
|
void Spells::addSpell (const ESM::Spell *spell, MagicEffects& effects) const
|
||||||
|
{
|
||||||
|
for (std::vector<ESM::ENAMstruct>::const_iterator iter = spell->effects.list.begin();
|
||||||
|
iter!=spell->effects.list.end(); ++iter)
|
||||||
|
{
|
||||||
|
EffectParam param;
|
||||||
|
param.mMagnitude = iter->magnMax; /// \todo calculate magnitude
|
||||||
|
effects.add (EffectKey (*iter), param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spells::TIterator Spells::begin() const
|
||||||
|
{
|
||||||
|
return mSpells.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
Spells::TIterator Spells::end() const
|
||||||
|
{
|
||||||
|
return mSpells.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spells::add (const std::string& spellId)
|
||||||
|
{
|
||||||
|
if (std::find (mSpells.begin(), mSpells.end(), spellId)!=mSpells.end())
|
||||||
|
mSpells.push_back (spellId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spells::remove (const std::string& spellId)
|
||||||
|
{
|
||||||
|
TContainer::iterator iter = std::find (mSpells.begin(), mSpells.end(), spellId);
|
||||||
|
|
||||||
|
if (iter!=mSpells.end())
|
||||||
|
mSpells.erase (iter);
|
||||||
|
|
||||||
|
if (spellId==mSelectedSpell)
|
||||||
|
mSelectedSpell.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
MagicEffects Spells::getMagicEffects (const MWWorld::Environment& environment) const
|
||||||
|
{
|
||||||
|
MagicEffects effects;
|
||||||
|
|
||||||
|
for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter)
|
||||||
|
{
|
||||||
|
const ESM::Spell *spell = environment.mWorld->getStore().spells.find (*iter);
|
||||||
|
|
||||||
|
if (spell->data.type==ESM::Spell::ST_Ability || spell->data.type==ESM::Spell::ST_Blight ||
|
||||||
|
spell->data.type==ESM::Spell::ST_Disease || spell->data.type==ESM::Spell::ST_Curse)
|
||||||
|
addSpell (spell, effects);
|
||||||
|
}
|
||||||
|
|
||||||
|
return effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spells::clear()
|
||||||
|
{
|
||||||
|
mSpells.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spells::setSelectedSpell (const std::string& spellId)
|
||||||
|
{
|
||||||
|
mSelectedSpell = spellId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string Spells::getSelectedSpell() const
|
||||||
|
{
|
||||||
|
return mSelectedSpell;
|
||||||
|
}
|
||||||
|
}
|
66
apps/openmw/mwmechanics/spells.hpp
Normal file
66
apps/openmw/mwmechanics/spells.hpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef GAME_MWMECHANICS_SPELLS_H
|
||||||
|
#define GAME_MWMECHANICS_SPELLS_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
struct Spell;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
struct Environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWMechanics
|
||||||
|
{
|
||||||
|
class MagicEffects;
|
||||||
|
|
||||||
|
/// \brief Spell list
|
||||||
|
///
|
||||||
|
/// This class manages known spells as well as abilities, powers and permanent negative effects like
|
||||||
|
/// diseaes.
|
||||||
|
class Spells
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::vector<std::string> TContainer;
|
||||||
|
typedef TContainer::const_iterator TIterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector<std::string> mSpells;
|
||||||
|
std::string mSelectedSpell;
|
||||||
|
|
||||||
|
void addSpell (const ESM::Spell *, MagicEffects& effects) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TIterator begin() const;
|
||||||
|
|
||||||
|
TIterator end() const;
|
||||||
|
|
||||||
|
void add (const std::string& spell);
|
||||||
|
///< Adding a spell that is already listed in *this is a no-op.
|
||||||
|
|
||||||
|
void remove (const std::string& spell);
|
||||||
|
///< If the spell to be removed is the selected spell, the selected spell will be changed to
|
||||||
|
/// no spell (empty string).
|
||||||
|
|
||||||
|
MagicEffects getMagicEffects (const MWWorld::Environment& environment) const;
|
||||||
|
///< Return sum of magic effects resulting from abilities, blights, deseases and curses.
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
///< Remove all spells of al types.
|
||||||
|
|
||||||
|
void setSelectedSpell (const std::string& spellId);
|
||||||
|
///< This function does not verify, if the spell is available.
|
||||||
|
|
||||||
|
const std::string getSelectedSpell() const;
|
||||||
|
///< May return an empty string.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -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,10 @@ 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);
|
||||||
|
|
||||||
|
// use fallback techniques without shadows and without mrt
|
||||||
|
vp->setMaterialScheme("Fallback");
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
@ -114,17 +115,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())
|
||||||
{
|
{
|
||||||
|
@ -132,7 +165,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()];
|
||||||
|
@ -160,6 +193,12 @@ 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->setCastShadows(true);
|
||||||
|
|
||||||
|
sg->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||||
|
|
||||||
mRenderer.getScene()->destroyEntity(ent);
|
mRenderer.getScene()->destroyEntity(ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,6 +292,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);
|
||||||
|
@ -270,6 +316,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);
|
||||||
|
@ -62,25 +60,28 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
||||||
mBBNodeReal = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
|
mBBNodeReal = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
|
||||||
|
|
||||||
mBBQueryTotal = mRendering->getScene()->createBillboardSet(1);
|
mBBQueryTotal = mRendering->getScene()->createBillboardSet(1);
|
||||||
|
mBBQueryTotal->setCastShadows(false);
|
||||||
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->setCastShadows(false);
|
||||||
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);
|
||||||
/// \todo ideally this should occupy exactly 1 pixel on the screen
|
/// \todo ideally this should occupy exactly 1 pixel on the screen
|
||||||
|
mBBQuerySingleObject->setCastShadows(false);
|
||||||
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 +154,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
|
|
@ -14,6 +14,10 @@
|
||||||
#include <components/esm/loadstat.hpp>
|
#include <components/esm/loadstat.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
#include "shadows.hpp"
|
||||||
|
#include "shaderhelper.hpp"
|
||||||
|
#include "localmap.hpp"
|
||||||
|
#include "water.hpp"
|
||||||
|
|
||||||
using namespace MWRender;
|
using namespace MWRender;
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
|
@ -21,11 +25,11 @@ using namespace Ogre;
|
||||||
namespace MWRender {
|
namespace MWRender {
|
||||||
|
|
||||||
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment)
|
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment)
|
||||||
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0)
|
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mSunEnabled(0)
|
||||||
{
|
{
|
||||||
mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5);
|
mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5);
|
||||||
mTerrainManager = new TerrainManager(mRendering.getScene(),
|
|
||||||
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
|
||||||
|
@ -39,14 +43,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
|
||||||
|
@ -64,13 +88,17 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
||||||
Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode();
|
Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode();
|
||||||
cameraPitchNode->attachObject(mRendering.getCamera());
|
cameraPitchNode->attachObject(mRendering.getCamera());
|
||||||
|
|
||||||
|
mShadows = new Shadows(&mRendering);
|
||||||
|
mShaderHelper = new ShaderHelper(this);
|
||||||
|
|
||||||
|
mTerrainManager = new TerrainManager(mRendering.getScene(), this,
|
||||||
|
environment);
|
||||||
|
|
||||||
//mSkyManager = 0;
|
//mSkyManager = 0;
|
||||||
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment);
|
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment);
|
||||||
|
|
||||||
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 +150,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 +166,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 +223,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 +290,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 +334,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 +399,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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,7 +420,9 @@ void RenderingManager::skipAnimation (const MWWorld::Ptr& ptr)
|
||||||
|
|
||||||
void RenderingManager::setSunColour(const Ogre::ColourValue& colour)
|
void RenderingManager::setSunColour(const Ogre::ColourValue& colour)
|
||||||
{
|
{
|
||||||
|
if (!mSunEnabled) return;
|
||||||
mSun->setDiffuseColour(colour);
|
mSun->setDiffuseColour(colour);
|
||||||
|
mSun->setSpecularColour(colour);
|
||||||
mTerrainManager->setDiffuse(colour);
|
mTerrainManager->setDiffuse(colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,12 +434,21 @@ void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour)
|
||||||
|
|
||||||
void RenderingManager::sunEnable()
|
void RenderingManager::sunEnable()
|
||||||
{
|
{
|
||||||
if (mSun) mSun->setVisible(true);
|
// Don't disable the light, as the shaders assume the first light to be directional.
|
||||||
|
//if (mSun) mSun->setVisible(true);
|
||||||
|
mSunEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::sunDisable()
|
void RenderingManager::sunDisable()
|
||||||
{
|
{
|
||||||
if (mSun) mSun->setVisible(false);
|
// Don't disable the light, as the shaders assume the first light to be directional.
|
||||||
|
//if (mSun) mSun->setVisible(false);
|
||||||
|
mSunEnabled = false;
|
||||||
|
if (mSun)
|
||||||
|
{
|
||||||
|
mSun->setDiffuseColour(ColourValue(0,0,0));
|
||||||
|
mSun->setSpecularColour(ColourValue(0,0,0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::setSunDirection(const Ogre::Vector3& direction)
|
void RenderingManager::setSunDirection(const Ogre::Vector3& direction)
|
||||||
|
@ -428,4 +488,14 @@ void RenderingManager::enableLights()
|
||||||
mObjects.enableLights();
|
mObjects.enableLights();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool RenderingManager::useMRT()
|
||||||
|
{
|
||||||
|
return Settings::Manager::getBool("shader", "Water");
|
||||||
|
}
|
||||||
|
|
||||||
|
Shadows* RenderingManager::getShadows()
|
||||||
|
{
|
||||||
|
return mShadows;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -25,17 +25,12 @@
|
||||||
#include "objects.hpp"
|
#include "objects.hpp"
|
||||||
#include "actors.hpp"
|
#include "actors.hpp"
|
||||||
#include "player.hpp"
|
#include "player.hpp"
|
||||||
#include "water.hpp"
|
|
||||||
#include "localmap.hpp"
|
|
||||||
#include "occlusionquery.hpp"
|
#include "occlusionquery.hpp"
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +43,10 @@ namespace MWWorld
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class Shadows;
|
||||||
|
class ShaderHelper;
|
||||||
|
class LocalMap;
|
||||||
|
class Water;
|
||||||
|
|
||||||
class RenderingManager: private RenderingInterface {
|
class RenderingManager: private RenderingInterface {
|
||||||
|
|
||||||
|
@ -84,6 +82,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
|
||||||
|
|
||||||
|
@ -115,6 +115,8 @@ class RenderingManager: private RenderingInterface {
|
||||||
bool occlusionQuerySupported() { return mOcclusionQuery->supported(); };
|
bool occlusionQuerySupported() { return mOcclusionQuery->supported(); };
|
||||||
OcclusionQuery* getOcclusionQuery() { return mOcclusionQuery; };
|
OcclusionQuery* getOcclusionQuery() { return mOcclusionQuery; };
|
||||||
|
|
||||||
|
Shadows* getShadows();
|
||||||
|
|
||||||
void setGlare(bool glare);
|
void setGlare(bool glare);
|
||||||
void skyEnable ();
|
void skyEnable ();
|
||||||
void skyDisable ();
|
void skyDisable ();
|
||||||
|
@ -150,6 +152,8 @@ class RenderingManager: private RenderingInterface {
|
||||||
|
|
||||||
void setAmbientMode();
|
void setAmbientMode();
|
||||||
|
|
||||||
|
bool mSunEnabled;
|
||||||
|
|
||||||
SkyManager* mSkyManager;
|
SkyManager* mSkyManager;
|
||||||
|
|
||||||
OcclusionQuery* mOcclusionQuery;
|
OcclusionQuery* mOcclusionQuery;
|
||||||
|
@ -181,6 +185,10 @@ class RenderingManager: private RenderingInterface {
|
||||||
MWRender::Debugging *mDebugging;
|
MWRender::Debugging *mDebugging;
|
||||||
|
|
||||||
MWRender::LocalMap* mLocalMap;
|
MWRender::LocalMap* mLocalMap;
|
||||||
|
|
||||||
|
MWRender::Shadows* mShadows;
|
||||||
|
|
||||||
|
MWRender::ShaderHelper* mShaderHelper;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
308
apps/openmw/mwrender/shaderhelper.cpp
Normal file
308
apps/openmw/mwrender/shaderhelper.cpp
Normal file
|
@ -0,0 +1,308 @@
|
||||||
|
#include "shaderhelper.hpp"
|
||||||
|
#include "renderingmanager.hpp"
|
||||||
|
#include "shadows.hpp"
|
||||||
|
|
||||||
|
#include <OgreHighLevelGpuProgramManager.h>
|
||||||
|
#include <OgreHighLevelGpuProgram.h>
|
||||||
|
#include <OgreGpuProgramParams.h>
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
using namespace Ogre;
|
||||||
|
using namespace MWRender;
|
||||||
|
|
||||||
|
ShaderHelper::ShaderHelper(RenderingManager* rend)
|
||||||
|
{
|
||||||
|
mRendering = rend;
|
||||||
|
applyShaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderHelper::applyShaders()
|
||||||
|
{
|
||||||
|
if (!Settings::Manager::getBool("shaders", "Objects")) return;
|
||||||
|
|
||||||
|
bool mrt = RenderingManager::useMRT();
|
||||||
|
bool shadows = Settings::Manager::getBool("enabled", "Shadows");
|
||||||
|
bool split = Settings::Manager::getBool("split", "Shadows");
|
||||||
|
|
||||||
|
// shader for normal rendering
|
||||||
|
createShader(mrt, shadows, split, "main");
|
||||||
|
|
||||||
|
// fallback shader without mrt and without shadows
|
||||||
|
// (useful for reflection and for minimap)
|
||||||
|
createShader(false, false, false, "main_fallback");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderHelper::createShader(const bool mrt, const bool shadows, const bool split, const std::string& name)
|
||||||
|
{
|
||||||
|
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||||
|
|
||||||
|
const int numsplits = 3;
|
||||||
|
|
||||||
|
// the number of lights to support.
|
||||||
|
// when rendering an object, OGRE automatically picks the lights that are
|
||||||
|
// closest to the object being rendered. unfortunately this mechanism does
|
||||||
|
// not work perfectly for objects batched together (they will all use the same
|
||||||
|
// lights). to work around this, we are simply pushing the maximum number
|
||||||
|
// of lights here in order to minimize disappearing lights.
|
||||||
|
int num_lights = Settings::Manager::getInt("num lights", "Objects");
|
||||||
|
|
||||||
|
{
|
||||||
|
// vertex
|
||||||
|
HighLevelGpuProgramPtr vertex;
|
||||||
|
if (!mgr.getByName(name+"_vp").isNull())
|
||||||
|
mgr.remove(name+"_vp");
|
||||||
|
|
||||||
|
vertex = mgr.createProgram(name+"_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
"cg", GPT_VERTEX_PROGRAM);
|
||||||
|
vertex->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1");
|
||||||
|
vertex->setParameter("entry_point", "main_vp");
|
||||||
|
StringUtil::StrStreamType outStream;
|
||||||
|
outStream <<
|
||||||
|
"void main_vp( \n"
|
||||||
|
" float4 position : POSITION, \n"
|
||||||
|
" float4 normal : NORMAL, \n"
|
||||||
|
" float4 colour : COLOR, \n"
|
||||||
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
|
" out float2 oUV : TEXCOORD0, \n"
|
||||||
|
" out float4 oPosition : POSITION, \n"
|
||||||
|
" out float4 oPositionObjSpace : TEXCOORD1, \n"
|
||||||
|
" out float4 oNormal : TEXCOORD2, \n"
|
||||||
|
" out float oDepth : TEXCOORD3, \n"
|
||||||
|
" out float4 oVertexColour : TEXCOORD4, \n";
|
||||||
|
if (shadows && !split) outStream <<
|
||||||
|
" out float4 oLightSpacePos0 : TEXCOORD5, \n"
|
||||||
|
" uniform float4x4 worldMatrix, \n"
|
||||||
|
" uniform float4x4 texViewProjMatrix0, \n";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i=0; i<numsplits; ++i)
|
||||||
|
{
|
||||||
|
outStream <<
|
||||||
|
" out float4 oLightSpacePos"<<i<<" : TEXCOORD"<<i+5<<", \n"
|
||||||
|
" uniform float4x4 texViewProjMatrix"<<i<<", \n";
|
||||||
|
}
|
||||||
|
outStream <<
|
||||||
|
" uniform float4x4 worldMatrix, \n";
|
||||||
|
}
|
||||||
|
outStream <<
|
||||||
|
" uniform float4x4 worldViewProj \n"
|
||||||
|
") \n"
|
||||||
|
"{ \n"
|
||||||
|
" oVertexColour = colour; \n"
|
||||||
|
" oUV = uv; \n"
|
||||||
|
" oNormal = normal; \n"
|
||||||
|
" oPosition = mul( worldViewProj, position ); \n"
|
||||||
|
" oDepth = oPosition.z; \n"
|
||||||
|
" oPositionObjSpace = position; \n";
|
||||||
|
if (shadows && !split) outStream <<
|
||||||
|
" oLightSpacePos0 = mul(texViewProjMatrix0, mul(worldMatrix, position)); \n";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outStream <<
|
||||||
|
" float4 wPos = mul(worldMatrix, position); \n";
|
||||||
|
for (int i=0; i<numsplits; ++i)
|
||||||
|
{
|
||||||
|
outStream <<
|
||||||
|
" oLightSpacePos"<<i<<" = mul(texViewProjMatrix"<<i<<", wPos); \n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outStream <<
|
||||||
|
"}";
|
||||||
|
vertex->setSource(outStream.str());
|
||||||
|
vertex->load();
|
||||||
|
vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||||
|
if (shadows)
|
||||||
|
{
|
||||||
|
vertex->getDefaultParameters()->setNamedAutoConstant("worldMatrix", GpuProgramParameters::ACT_WORLD_MATRIX);
|
||||||
|
if (!split)
|
||||||
|
vertex->getDefaultParameters()->setNamedAutoConstant("texViewProjMatrix0", GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i=0; i<numsplits; ++i)
|
||||||
|
{
|
||||||
|
vertex->getDefaultParameters()->setNamedAutoConstant("texViewProjMatrix"+StringConverter::toString(i), GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// fragment
|
||||||
|
HighLevelGpuProgramPtr fragment;
|
||||||
|
if (!mgr.getByName(name+"_fp").isNull())
|
||||||
|
mgr.remove(name+"_fp");
|
||||||
|
|
||||||
|
fragment = mgr.createProgram(name+"_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
"cg", GPT_FRAGMENT_PROGRAM);
|
||||||
|
fragment->setParameter("profiles", "ps_4_0 ps_2_x fp40 arbfp1");
|
||||||
|
fragment->setParameter("entry_point", "main_fp");
|
||||||
|
StringUtil::StrStreamType outStream;
|
||||||
|
|
||||||
|
if (shadows) outStream <<
|
||||||
|
"float depthShadow(sampler2D shadowMap, float4 shadowMapPos, float2 offset) \n"
|
||||||
|
"{ \n"
|
||||||
|
" shadowMapPos /= shadowMapPos.w; \n"
|
||||||
|
" float3 o = float3(offset.xy, -offset.x) * 0.3f; \n"
|
||||||
|
" float c = (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy - o.xy).r) ? 1 : 0; // top left \n"
|
||||||
|
" c += (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy + o.xy).r) ? 1 : 0; // bottom right \n"
|
||||||
|
" c += (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy + o.zy).r) ? 1 : 0; // bottom left \n"
|
||||||
|
" c += (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy - o.zy).r) ? 1 : 0; // top right \n"
|
||||||
|
" return c / 4; \n"
|
||||||
|
"} \n";
|
||||||
|
|
||||||
|
outStream <<
|
||||||
|
"void main_fp( \n"
|
||||||
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
|
" out float4 oColor : COLOR, \n"
|
||||||
|
" uniform sampler2D texture : register(s0), \n"
|
||||||
|
" float4 positionObjSpace : TEXCOORD1, \n"
|
||||||
|
" float4 normal : TEXCOORD2, \n"
|
||||||
|
" float iDepth : TEXCOORD3, \n"
|
||||||
|
" float4 vertexColour : TEXCOORD4, \n"
|
||||||
|
" uniform float4 fogColour, \n"
|
||||||
|
" uniform float4 fogParams, \n";
|
||||||
|
|
||||||
|
if (shadows) outStream <<
|
||||||
|
" uniform float4 shadowFar_fadeStart, \n";
|
||||||
|
|
||||||
|
if (shadows && !split) outStream <<
|
||||||
|
" uniform sampler2D shadowMap : register(s1), \n"
|
||||||
|
" float4 lightSpacePos0 : TEXCOORD5, \n"
|
||||||
|
" uniform float4 invShadowmapSize0, \n";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outStream <<
|
||||||
|
" uniform float4 pssmSplitPoints, \n";
|
||||||
|
for (int i=0; i<numsplits; ++i)
|
||||||
|
{
|
||||||
|
outStream <<
|
||||||
|
" uniform sampler2D shadowMap"<<i<<" : register(s"<<i+1<<"), \n"
|
||||||
|
" float4 lightSpacePos"<<i<<" : TEXCOORD"<<i+5<<", \n"
|
||||||
|
" uniform float4 invShadowmapSize"<<i<<", \n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mrt) outStream <<
|
||||||
|
" out float4 oColor1 : COLOR1, \n"
|
||||||
|
" uniform float far, \n";
|
||||||
|
|
||||||
|
for (int i=0; i<num_lights; ++i)
|
||||||
|
{
|
||||||
|
outStream <<
|
||||||
|
" uniform float4 lightDiffuse"<<i<<", \n"
|
||||||
|
" uniform float4 lightPositionObjSpace"<<i<<", \n"
|
||||||
|
" uniform float4 lightAttenuation"<<i<<", \n";
|
||||||
|
}
|
||||||
|
outStream <<
|
||||||
|
" uniform float4 lightAmbient, \n"
|
||||||
|
" uniform float4 ambient, \n"
|
||||||
|
" uniform float4 diffuse, \n"
|
||||||
|
" uniform float4 emissive \n"
|
||||||
|
") \n"
|
||||||
|
"{ \n"
|
||||||
|
" float4 tex = tex2D(texture, uv); \n"
|
||||||
|
" float d; \n"
|
||||||
|
" float attn; \n"
|
||||||
|
" float3 lightDir; \n"
|
||||||
|
" float3 lightColour = float3(0, 0, 0); \n";
|
||||||
|
|
||||||
|
for (int i=0; i<num_lights; ++i)
|
||||||
|
{
|
||||||
|
outStream <<
|
||||||
|
" lightDir = lightPositionObjSpace"<<i<<".xyz - (positionObjSpace.xyz * lightPositionObjSpace"<<i<<".w); \n"
|
||||||
|
|
||||||
|
// pre-multiply light color with attenuation factor
|
||||||
|
" d = length( lightDir ); \n"
|
||||||
|
" attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n"
|
||||||
|
" lightDiffuse"<<i<<" *= attn; \n";
|
||||||
|
|
||||||
|
if (i == 0 && shadows)
|
||||||
|
{
|
||||||
|
outStream <<
|
||||||
|
" float shadow; \n";
|
||||||
|
if (!split) outStream <<
|
||||||
|
" shadow = depthShadow(shadowMap, lightSpacePos0, invShadowmapSize0.xy); \n";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int j=0; j<numsplits; ++j)
|
||||||
|
{
|
||||||
|
std::string channel;
|
||||||
|
if (j==0) channel = "x";
|
||||||
|
else if (j==1) channel = "y";
|
||||||
|
else if (j==2) channel = "z";
|
||||||
|
|
||||||
|
if (j==0)
|
||||||
|
outStream << " if (iDepth <= pssmSplitPoints." << channel << ") \n";
|
||||||
|
else if (j < numsplits - 1)
|
||||||
|
outStream << " else if (iDepth <= pssmSplitPoints." << channel << ") \n";
|
||||||
|
else
|
||||||
|
outStream << " else \n";
|
||||||
|
|
||||||
|
outStream <<
|
||||||
|
" { \n"
|
||||||
|
" shadow = depthShadow(shadowMap" << j << ", lightSpacePos" << j << ", invShadowmapSize" << j << ".xy); \n"
|
||||||
|
" } \n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outStream <<
|
||||||
|
" float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; \n"
|
||||||
|
" float fade = 1-((iDepth - shadowFar_fadeStart.y) / fadeRange); \n"
|
||||||
|
" shadow = (iDepth > shadowFar_fadeStart.x) ? 1 : ((iDepth > shadowFar_fadeStart.y) ? 1-((1-shadow)*fade) : shadow); \n"
|
||||||
|
" lightColour.xyz += shadow * lit(dot(normalize(lightDir), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
|
||||||
|
}
|
||||||
|
else outStream <<
|
||||||
|
" lightColour.xyz += lit(dot(normalize(lightDir), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
outStream <<
|
||||||
|
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * 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.xyz, fogValue); \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->load();
|
||||||
|
|
||||||
|
for (int i=0; i<num_lights; ++i)
|
||||||
|
{
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightPositionObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i);
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightDiffuse"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i);
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
|
||||||
|
}
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
|
||||||
|
|
||||||
|
if (shadows)
|
||||||
|
{
|
||||||
|
fragment->getDefaultParameters()->setNamedConstant("shadowFar_fadeStart", Vector4(mRendering->getShadows()->getShadowFar(), mRendering->getShadows()->getFadeStart()*mRendering->getShadows()->getShadowFar(), 0, 0));
|
||||||
|
for (int i=0; i < (split ? numsplits : 1); ++i)
|
||||||
|
{
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("invShadowmapSize" + StringConverter::toString(i), GpuProgramParameters::ACT_INVERSE_TEXTURE_SIZE, i+1);
|
||||||
|
}
|
||||||
|
if (split)
|
||||||
|
{
|
||||||
|
Vector4 splitPoints;
|
||||||
|
const PSSMShadowCameraSetup::SplitPointList& splitPointList = mRendering->getShadows()->getPSSMSetup()->getSplitPoints();
|
||||||
|
// Populate from split point 1, not 0, since split 0 isn't useful (usually 0)
|
||||||
|
for (int i = 1; i < numsplits; ++i)
|
||||||
|
{
|
||||||
|
splitPoints[i-1] = splitPointList[i];
|
||||||
|
}
|
||||||
|
fragment->getDefaultParameters()->setNamedConstant("pssmSplitPoints", splitPoints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mrt)
|
||||||
|
fragment->getDefaultParameters()->setNamedAutoConstant("far", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
|
||||||
|
}
|
||||||
|
}
|
29
apps/openmw/mwrender/shaderhelper.hpp
Normal file
29
apps/openmw/mwrender/shaderhelper.hpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef GAME_SHADERHELPER_H
|
||||||
|
#define GAME_SHADERHELPER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
class RenderingManager;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief manages the main shader
|
||||||
|
///
|
||||||
|
class ShaderHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShaderHelper(RenderingManager* rend);
|
||||||
|
|
||||||
|
void applyShaders();
|
||||||
|
///< apply new settings
|
||||||
|
|
||||||
|
private:
|
||||||
|
RenderingManager* mRendering;
|
||||||
|
|
||||||
|
void createShader(const bool mrt, const bool shadows, const bool split, const std::string& name);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
173
apps/openmw/mwrender/shadows.cpp
Normal file
173
apps/openmw/mwrender/shadows.cpp
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
#include "shadows.hpp"
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
#include <openengine/ogre/renderer.hpp>
|
||||||
|
|
||||||
|
#include <OgreSceneManager.h>
|
||||||
|
#include <OgreColourValue.h>
|
||||||
|
#include <OgreShadowCameraSetupLiSPSM.h>
|
||||||
|
#include <OgreShadowCameraSetupPSSM.h>
|
||||||
|
#include <OgreHardwarePixelBuffer.h>
|
||||||
|
|
||||||
|
#include <OgreOverlayContainer.h>
|
||||||
|
#include <OgreOverlayManager.h>
|
||||||
|
|
||||||
|
#include "renderconst.hpp"
|
||||||
|
|
||||||
|
using namespace Ogre;
|
||||||
|
using namespace MWRender;
|
||||||
|
|
||||||
|
Shadows::Shadows(OEngine::Render::OgreRenderer* rend) :
|
||||||
|
mShadowFar(1000), mFadeStart(0.9)
|
||||||
|
{
|
||||||
|
mRendering = rend;
|
||||||
|
mSceneMgr = mRendering->getScene();
|
||||||
|
recreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shadows::recreate()
|
||||||
|
{
|
||||||
|
bool enabled = Settings::Manager::getBool("enabled", "Shadows");
|
||||||
|
|
||||||
|
// Split shadow maps are currently disabled because the terrain cannot cope with them
|
||||||
|
// (Too many texture units) Solution would be a multi-pass terrain material
|
||||||
|
bool split = Settings::Manager::getBool("split", "Shadows");
|
||||||
|
//const bool split = false;
|
||||||
|
|
||||||
|
if (!enabled)
|
||||||
|
{
|
||||||
|
mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int texsize = Settings::Manager::getInt("texture size", "Shadows");
|
||||||
|
mSceneMgr->setShadowTextureSize(texsize);
|
||||||
|
|
||||||
|
mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED);
|
||||||
|
|
||||||
|
// no point light shadows, i'm afraid. might revisit this with Deferred Shading
|
||||||
|
mSceneMgr->setShadowTextureCountPerLightType(Light::LT_POINT, 0);
|
||||||
|
|
||||||
|
mSceneMgr->setShadowTextureCountPerLightType(Light::LT_DIRECTIONAL, split ? 3 : 1);
|
||||||
|
mSceneMgr->setShadowTextureCount(split ? 3 : 1);
|
||||||
|
|
||||||
|
mSceneMgr->setShadowTextureSelfShadow(true);
|
||||||
|
mSceneMgr->setShadowCasterRenderBackFaces(true);
|
||||||
|
mSceneMgr->setShadowTextureCasterMaterial("depth_shadow_caster");
|
||||||
|
mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R);
|
||||||
|
mSceneMgr->setShadowDirectionalLightExtrusionDistance(1000000);
|
||||||
|
|
||||||
|
mShadowFar = split ? Settings::Manager::getInt("split shadow distance", "Shadows") : Settings::Manager::getInt("shadow distance", "Shadows");
|
||||||
|
mSceneMgr->setShadowFarDistance(mShadowFar);
|
||||||
|
|
||||||
|
mFadeStart = Settings::Manager::getFloat("fade start", "Shadows");
|
||||||
|
|
||||||
|
ShadowCameraSetupPtr shadowCameraSetup;
|
||||||
|
if (split)
|
||||||
|
{
|
||||||
|
mPSSMSetup = new PSSMShadowCameraSetup();
|
||||||
|
mPSSMSetup->setSplitPadding(5);
|
||||||
|
mPSSMSetup->calculateSplitPoints(3, mRendering->getCamera()->getNearClipDistance(), mShadowFar);
|
||||||
|
|
||||||
|
const Real adjustFactors[3] = {64, 64, 64};
|
||||||
|
for (int i=0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
mPSSMSetup->setOptimalAdjustFactor(i, adjustFactors[i]);
|
||||||
|
/*if (i==0)
|
||||||
|
mSceneMgr->setShadowTextureConfig(i, texsize, texsize, Ogre::PF_FLOAT32_R);
|
||||||
|
else if (i ==1)
|
||||||
|
mSceneMgr->setShadowTextureConfig(i, texsize/2, texsize/2, Ogre::PF_FLOAT32_R);
|
||||||
|
else if (i ==2)
|
||||||
|
mSceneMgr->setShadowTextureConfig(i, texsize/4, texsize/4, Ogre::PF_FLOAT32_R);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowCameraSetup = ShadowCameraSetupPtr(mPSSMSetup);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LiSPSMShadowCameraSetup* lispsmSetup = new LiSPSMShadowCameraSetup();
|
||||||
|
lispsmSetup->setOptimalAdjustFactor(2);
|
||||||
|
//lispsmSetup->setCameraLightDirectionThreshold(Degree(0));
|
||||||
|
//lispsmSetup->setUseAggressiveFocusRegion(false);
|
||||||
|
shadowCameraSetup = ShadowCameraSetupPtr(lispsmSetup);
|
||||||
|
}
|
||||||
|
mSceneMgr->setShadowCameraSetup(shadowCameraSetup);
|
||||||
|
|
||||||
|
// Set visibility mask for the shadow render textures
|
||||||
|
int visibilityMask = RV_Actors * Settings::Manager::getBool("actor shadows", "Shadows")
|
||||||
|
+ (RV_Statics + RV_StaticsSmall) * Settings::Manager::getBool("statics shadows", "Shadows")
|
||||||
|
+ RV_Misc * Settings::Manager::getBool("misc shadows", "Shadows");
|
||||||
|
|
||||||
|
for (int i = 0; i < (split ? 3 : 1); ++i)
|
||||||
|
{
|
||||||
|
TexturePtr shadowTexture = mSceneMgr->getShadowTexture(i);
|
||||||
|
Viewport* vp = shadowTexture->getBuffer()->getRenderTarget()->getViewport(0);
|
||||||
|
vp->setVisibilityMask(visibilityMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||||
|
// --------------------------- Debug overlays to display the content of shadow maps -----------------------------------
|
||||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
OverlayManager& mgr = OverlayManager::getSingleton();
|
||||||
|
Overlay* overlay;
|
||||||
|
|
||||||
|
// destroy if already exists
|
||||||
|
if (overlay = mgr.getByName("DebugOverlay"))
|
||||||
|
mgr.destroy(overlay);
|
||||||
|
|
||||||
|
overlay = mgr.create("DebugOverlay");
|
||||||
|
for (size_t i = 0; i < (split ? 3 : 1); ++i) {
|
||||||
|
TexturePtr tex = mRendering->getScene()->getShadowTexture(i);
|
||||||
|
|
||||||
|
// Set up a debug panel to display the shadow
|
||||||
|
|
||||||
|
if (MaterialManager::getSingleton().resourceExists("Ogre/DebugTexture" + StringConverter::toString(i)))
|
||||||
|
MaterialManager::getSingleton().remove("Ogre/DebugTexture" + StringConverter::toString(i));
|
||||||
|
MaterialPtr debugMat = MaterialManager::getSingleton().create(
|
||||||
|
"Ogre/DebugTexture" + StringConverter::toString(i),
|
||||||
|
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||||
|
|
||||||
|
debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
|
||||||
|
TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName());
|
||||||
|
t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
|
||||||
|
|
||||||
|
OverlayContainer* debugPanel;
|
||||||
|
|
||||||
|
// destroy container if exists
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (debugPanel =
|
||||||
|
static_cast<OverlayContainer*>(
|
||||||
|
mgr.getOverlayElement("Ogre/DebugTexPanel" + StringConverter::toString(i)
|
||||||
|
)))
|
||||||
|
mgr.destroyOverlayElement(debugPanel);
|
||||||
|
}
|
||||||
|
catch (Ogre::Exception&) {}
|
||||||
|
|
||||||
|
debugPanel = (OverlayContainer*)
|
||||||
|
(OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugTexPanel" + StringConverter::toString(i)));
|
||||||
|
debugPanel->_setPosition(0.8, i*0.25);
|
||||||
|
debugPanel->_setDimensions(0.2, 0.24);
|
||||||
|
debugPanel->setMaterialName(debugMat->getName());
|
||||||
|
debugPanel->show();
|
||||||
|
overlay->add2D(debugPanel);
|
||||||
|
overlay->show();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
PSSMShadowCameraSetup* Shadows::getPSSMSetup()
|
||||||
|
{
|
||||||
|
return mPSSMSetup;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Shadows::getShadowFar() const
|
||||||
|
{
|
||||||
|
return mShadowFar;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Shadows::getFadeStart() const
|
||||||
|
{
|
||||||
|
return mFadeStart;
|
||||||
|
}
|
39
apps/openmw/mwrender/shadows.hpp
Normal file
39
apps/openmw/mwrender/shadows.hpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef GAME_SHADOWS_H
|
||||||
|
#define GAME_SHADOWS_H
|
||||||
|
|
||||||
|
// forward declares
|
||||||
|
namespace Ogre
|
||||||
|
{
|
||||||
|
class SceneManager;
|
||||||
|
class PSSMShadowCameraSetup;
|
||||||
|
}
|
||||||
|
namespace OEngine{
|
||||||
|
namespace Render{
|
||||||
|
class OgreRenderer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
class Shadows
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Shadows(OEngine::Render::OgreRenderer* rend);
|
||||||
|
|
||||||
|
void recreate();
|
||||||
|
|
||||||
|
Ogre::PSSMShadowCameraSetup* getPSSMSetup();
|
||||||
|
float getShadowFar() const;
|
||||||
|
float getFadeStart() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OEngine::Render::OgreRenderer* mRendering;
|
||||||
|
Ogre::SceneManager* mSceneMgr;
|
||||||
|
|
||||||
|
Ogre::PSSMShadowCameraSetup* mPSSMSetup;
|
||||||
|
float mShadowFar;
|
||||||
|
float mFadeStart;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -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,13 +95,14 @@ 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);
|
||||||
mBBSet->createBillboard(0,0,0);
|
mBBSet->createBillboard(0,0,0);
|
||||||
|
mBBSet->setCastShadows(false);
|
||||||
|
|
||||||
mMaterial = MaterialManager::getSingleton().create("BillboardMaterial"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
mMaterial = MaterialManager::getSingleton().create("BillboardMaterial"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||||
mMaterial->removeAllTechniques();
|
mMaterial->removeAllTechniques();
|
||||||
|
@ -109,6 +116,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 +223,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 +234,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 +430,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 +449,9 @@ 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);
|
||||||
|
night1_ent->setCastShadows(false);
|
||||||
|
|
||||||
mAtmosphereNight = mRootNode->createChildSceneNode();
|
mAtmosphereNight = mRootNode->createChildSceneNode();
|
||||||
mAtmosphereNight->attachObject(night1_ent);
|
mAtmosphereNight->attachObject(night1_ent);
|
||||||
|
@ -413,7 +489,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 +500,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();
|
||||||
|
@ -445,10 +527,12 @@ void SkyManager::create()
|
||||||
// Atmosphere (day)
|
// Atmosphere (day)
|
||||||
mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif");
|
mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif");
|
||||||
Entity* atmosphere_ent = mSceneMgr->createEntity("meshes\\sky_atmosphere.nif");
|
Entity* atmosphere_ent = mSceneMgr->createEntity("meshes\\sky_atmosphere.nif");
|
||||||
|
atmosphere_ent->setCastShadows(false);
|
||||||
|
|
||||||
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,29 +550,56 @@ 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();
|
||||||
|
clouds_ent->setCastShadows(false);
|
||||||
|
|
||||||
// Clouds vertex shader
|
// Clouds vertex shader
|
||||||
HighLevelGpuProgramPtr vshader2 = mgr.createProgram("Clouds_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
HighLevelGpuProgramPtr vshader2 = mgr.createProgram("Clouds_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
@ -525,8 +636,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 +652,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();
|
||||||
|
@ -564,6 +681,8 @@ void SkyManager::create()
|
||||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
|
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
|
||||||
|
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("textures\\tx_sky_cloudy.dds");
|
||||||
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("");
|
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("");
|
||||||
|
|
||||||
mCreated = true;
|
mCreated = true;
|
||||||
|
@ -653,12 +772,14 @@ void SkyManager::disable()
|
||||||
|
|
||||||
void SkyManager::setMoonColour (bool red)
|
void SkyManager::setMoonColour (bool red)
|
||||||
{
|
{
|
||||||
|
if (!mCreated) return;
|
||||||
mSecunda->setColour( red ? ColourValue(1.0, 0.0784, 0.0784)
|
mSecunda->setColour( red ? ColourValue(1.0, 0.0784, 0.0784)
|
||||||
: ColourValue(1.0, 1.0, 1.0));
|
: ColourValue(1.0, 1.0, 1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyManager::setCloudsOpacity(float opacity)
|
void SkyManager::setCloudsOpacity(float opacity)
|
||||||
{
|
{
|
||||||
|
if (!mCreated) return;
|
||||||
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(opacity));
|
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,7 +855,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);
|
||||||
}
|
}
|
||||||
|
@ -813,11 +935,13 @@ void SkyManager::setThunder(const float factor)
|
||||||
|
|
||||||
void SkyManager::setMasserFade(const float fade)
|
void SkyManager::setMasserFade(const float fade)
|
||||||
{
|
{
|
||||||
|
if (!mCreated) return;
|
||||||
mMasser->setVisibility(fade);
|
mMasser->setVisibility(fade);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyManager::setSecundaFade(const float fade)
|
void SkyManager::setSecundaFade(const float fade)
|
||||||
{
|
{
|
||||||
|
if (!mCreated) return;
|
||||||
mSecunda->setVisibility(fade);
|
mSecunda->setVisibility(fade);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -837,3 +961,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,7 +6,9 @@
|
||||||
|
|
||||||
#include "terrainmaterial.hpp"
|
#include "terrainmaterial.hpp"
|
||||||
#include "terrain.hpp"
|
#include "terrain.hpp"
|
||||||
|
#include "renderconst.hpp"
|
||||||
|
#include "shadows.hpp"
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
|
|
||||||
|
@ -15,8 +17,8 @@ namespace MWRender
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
TerrainManager::TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& evn) :
|
TerrainManager::TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend, const MWWorld::Environment& evn) :
|
||||||
mEnvironment(evn), mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize))
|
mEnvironment(evn), mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend)
|
||||||
{
|
{
|
||||||
|
|
||||||
TerrainMaterialGeneratorPtr matGen;
|
TerrainMaterialGeneratorPtr matGen;
|
||||||
|
@ -47,9 +49,19 @@ namespace MWRender
|
||||||
mActiveProfile->setLayerSpecularMappingEnabled(false);
|
mActiveProfile->setLayerSpecularMappingEnabled(false);
|
||||||
mActiveProfile->setLayerNormalMappingEnabled(false);
|
mActiveProfile->setLayerNormalMappingEnabled(false);
|
||||||
mActiveProfile->setLayerParallaxMappingEnabled(false);
|
mActiveProfile->setLayerParallaxMappingEnabled(false);
|
||||||
mActiveProfile->setReceiveDynamicShadowsEnabled(false);
|
|
||||||
|
|
||||||
//composite maps lead to a drastic reduction in loading time so are
|
bool shadows = Settings::Manager::getBool("enabled", "Shadows");
|
||||||
|
mActiveProfile->setReceiveDynamicShadowsEnabled(shadows);
|
||||||
|
mActiveProfile->setReceiveDynamicShadowsDepth(shadows);
|
||||||
|
if (Settings::Manager::getBool("split", "Shadows"))
|
||||||
|
mActiveProfile->setReceiveDynamicShadowsPSSM(mRendering->getShadows()->getPSSMSetup());
|
||||||
|
else
|
||||||
|
mActiveProfile->setReceiveDynamicShadowsPSSM(0);
|
||||||
|
|
||||||
|
mActiveProfile->setShadowFar(mRendering->getShadows()->getShadowFar());
|
||||||
|
mActiveProfile->setShadowFadeStart(mRendering->getShadows()->getFadeStart());
|
||||||
|
|
||||||
|
//composite maps lead to a drastic increase in loading time so are
|
||||||
//disabled
|
//disabled
|
||||||
mActiveProfile->setCompositeMapEnabled(false);
|
mActiveProfile->setCompositeMapEnabled(false);
|
||||||
|
|
||||||
|
@ -162,6 +174,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 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace MWRender{
|
||||||
*/
|
*/
|
||||||
class TerrainManager{
|
class TerrainManager{
|
||||||
public:
|
public:
|
||||||
TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& env);
|
TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend, const MWWorld::Environment& env);
|
||||||
virtual ~TerrainManager();
|
virtual ~TerrainManager();
|
||||||
|
|
||||||
void setDiffuse(const Ogre::ColourValue& diffuse);
|
void setDiffuse(const Ogre::ColourValue& diffuse);
|
||||||
|
@ -37,6 +37,7 @@ namespace MWRender{
|
||||||
Ogre::TerrainGroup mTerrainGroup;
|
Ogre::TerrainGroup mTerrainGroup;
|
||||||
|
|
||||||
const MWWorld::Environment& mEnvironment;
|
const MWWorld::Environment& mEnvironment;
|
||||||
|
RenderingManager* mRendering;
|
||||||
|
|
||||||
Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile;
|
Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -85,6 +86,7 @@ namespace Ogre
|
||||||
, mPSSM(0)
|
, mPSSM(0)
|
||||||
, mDepthShadows(false)
|
, mDepthShadows(false)
|
||||||
, mLowLodShadows(false)
|
, mLowLodShadows(false)
|
||||||
|
, mShadowFar(1300)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -100,6 +102,24 @@ namespace Ogre
|
||||||
terrain->_setNormalMapRequired(true);
|
terrain->_setNormalMapRequired(true);
|
||||||
terrain->_setLightMapRequired(mLightmapEnabled, true);
|
terrain->_setLightMapRequired(mLightmapEnabled, true);
|
||||||
terrain->_setCompositeMapRequired(mCompositeMapEnabled);
|
terrain->_setCompositeMapRequired(mCompositeMapEnabled);
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
void TerrainMaterialGeneratorB::SM2Profile::setShadowFar(float far)
|
||||||
|
{
|
||||||
|
if (mShadowFar != far)
|
||||||
|
{
|
||||||
|
mShadowFar = far;
|
||||||
|
mParent->_markChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
void TerrainMaterialGeneratorB::SM2Profile::setShadowFadeStart(float fadestart)
|
||||||
|
{
|
||||||
|
if (mShadowFadeStart != fadestart)
|
||||||
|
{
|
||||||
|
mShadowFadeStart = fadestart;
|
||||||
|
mParent->_markChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
void TerrainMaterialGeneratorB::SM2Profile::setLayerNormalMappingEnabled(bool enabled)
|
void TerrainMaterialGeneratorB::SM2Profile::setLayerNormalMappingEnabled(bool enabled)
|
||||||
|
@ -461,6 +481,7 @@ namespace Ogre
|
||||||
|
|
||||||
StringUtil::StrStreamType sourceStr;
|
StringUtil::StrStreamType sourceStr;
|
||||||
generateFragmentProgramSource(prof, terrain, tt, sourceStr);
|
generateFragmentProgramSource(prof, terrain, tt, sourceStr);
|
||||||
|
|
||||||
ret->setSource(sourceStr.str());
|
ret->setSource(sourceStr.str());
|
||||||
ret->load();
|
ret->load();
|
||||||
defaultFpParams(prof, terrain, tt, ret);
|
defaultFpParams(prof, terrain, tt, ret);
|
||||||
|
@ -532,8 +553,8 @@ namespace Ogre
|
||||||
GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i);
|
GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i);
|
||||||
if (prof->getReceiveDynamicShadowsDepth())
|
if (prof->getReceiveDynamicShadowsDepth())
|
||||||
{
|
{
|
||||||
params->setNamedAutoConstant("depthRange" + StringConverter::toString(i),
|
//params->setNamedAutoConstant("depthRange" + StringConverter::toString(i),
|
||||||
GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i);
|
//GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -558,11 +579,15 @@ 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);
|
||||||
|
|
||||||
if (prof->isShadowingEnabled(tt, terrain))
|
if (prof->isShadowingEnabled(tt, terrain))
|
||||||
{
|
{
|
||||||
|
params->setNamedConstant("shadowFar_fadeStart", Vector4(prof->mShadowFar, prof->mShadowFadeStart * prof->mShadowFar, 0, 0));
|
||||||
uint numTextures = 1;
|
uint numTextures = 1;
|
||||||
if (prof->getReceiveDynamicShadowsPSSM())
|
if (prof->getReceiveDynamicShadowsPSSM())
|
||||||
{
|
{
|
||||||
|
@ -728,7 +753,7 @@ namespace Ogre
|
||||||
ret->unload();
|
ret->unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
ret->setParameter("profiles", "vs_3_0 vs_2_0 arbvp1");
|
ret->setParameter("profiles", "vs_3_0 vs_2_0 vp40 arbvp1");
|
||||||
ret->setParameter("entry_point", "main_vp");
|
ret->setParameter("entry_point", "main_vp");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -753,11 +778,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");
|
||||||
|
|
||||||
|
@ -791,9 +811,9 @@ namespace Ogre
|
||||||
|
|
||||||
outStream <<
|
outStream <<
|
||||||
"out float4 oPos : POSITION,\n"
|
"out float4 oPos : POSITION,\n"
|
||||||
"out float4 oPosObj : TEXCOORD0 \n";
|
"out float4 oPosObj : COLOR \n";
|
||||||
|
|
||||||
uint texCoordSet = 1;
|
uint texCoordSet = 0;
|
||||||
outStream <<
|
outStream <<
|
||||||
", out float4 oUVMisc : TEXCOORD" << texCoordSet++ <<" // xy = uv, z = camDepth\n";
|
", out float4 oUVMisc : TEXCOORD" << texCoordSet++ <<" // xy = uv, z = camDepth\n";
|
||||||
|
|
||||||
|
@ -819,8 +839,8 @@ namespace Ogre
|
||||||
if (fog)
|
if (fog)
|
||||||
{
|
{
|
||||||
outStream <<
|
outStream <<
|
||||||
", uniform float4 fogParams\n"
|
", uniform float4 fogParams\n";
|
||||||
", out float fogVal : COLOR\n";
|
//", out float fogVal : COLOR\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prof->isShadowingEnabled(tt, terrain))
|
if (prof->isShadowingEnabled(tt, terrain))
|
||||||
|
@ -832,7 +852,7 @@ namespace Ogre
|
||||||
if (texCoordSet > 8)
|
if (texCoordSet > 8)
|
||||||
{
|
{
|
||||||
OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
|
OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
|
||||||
"Requested options require too many texture coordinate sets! Try reducing the number of layers.",
|
"Requested options require too many texture coordinate sets! Try reducing the number of layers. requested: " + StringConverter::toString(texCoordSet),
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -917,10 +937,10 @@ namespace Ogre
|
||||||
|
|
||||||
|
|
||||||
outStream <<
|
outStream <<
|
||||||
"float4 main_fp(\n"
|
"void main_fp(\n"
|
||||||
"float4 position : TEXCOORD0,\n";
|
"float4 position : COLOR,\n";
|
||||||
|
|
||||||
uint texCoordSet = 1;
|
uint texCoordSet = 0;
|
||||||
outStream <<
|
outStream <<
|
||||||
"float4 uvMisc : TEXCOORD" << texCoordSet++ << ",\n";
|
"float4 uvMisc : TEXCOORD" << texCoordSet++ << ",\n";
|
||||||
|
|
||||||
|
@ -949,8 +969,8 @@ namespace Ogre
|
||||||
if (fog)
|
if (fog)
|
||||||
{
|
{
|
||||||
outStream <<
|
outStream <<
|
||||||
"uniform float3 fogColour, \n"
|
"uniform float3 fogColour, \n";
|
||||||
"float fogVal : COLOR,\n";
|
//"float fogVal : COLOR,\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
uint currentSamplerIdx = 0;
|
uint currentSamplerIdx = 0;
|
||||||
|
@ -1034,12 +1054,20 @@ 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"
|
||||||
" float2 uv = uvMisc.xy;\n"
|
" float2 uv = uvMisc.xy;\n"
|
||||||
|
" float fogVal = position.w; \n"
|
||||||
// base colour
|
// base colour
|
||||||
" outputCol = float4(0,0,0,1);\n";
|
" outputCol = float4(0,0,0,1);\n";
|
||||||
|
|
||||||
|
@ -1241,19 +1269,25 @@ 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)
|
||||||
{
|
{
|
||||||
if (terrain->getSceneManager()->getFogMode() == FOG_LINEAR)
|
if (terrain->getSceneManager()->getFogMode() == FOG_LINEAR)
|
||||||
{
|
{
|
||||||
outStream <<
|
outStream <<
|
||||||
" fogVal = saturate((oPos.z - fogParams.y) * fogParams.w);\n";
|
" float fogVal = saturate((oPos.z - fogParams.y) * fogParams.w);\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outStream <<
|
outStream <<
|
||||||
" fogVal = saturate(1 / (exp(oPos.z * fogParams.x)));\n";
|
" float fogVal = saturate(1 / (exp(oPos.z * fogParams.x)));\n";
|
||||||
}
|
}
|
||||||
|
outStream <<
|
||||||
|
" oPosObj.w = fogVal; \n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prof->isShadowingEnabled(tt, terrain))
|
if (prof->isShadowingEnabled(tt, terrain))
|
||||||
|
@ -1337,7 +1371,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";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1349,7 +1388,7 @@ namespace Ogre
|
||||||
outStream <<
|
outStream <<
|
||||||
"// Simple PCF \n"
|
"// Simple PCF \n"
|
||||||
"// Number of samples in one dimension (square for total samples) \n"
|
"// Number of samples in one dimension (square for total samples) \n"
|
||||||
"#define NUM_SHADOW_SAMPLES_1D 2.0 \n"
|
"#define NUM_SHADOW_SAMPLES_1D 1.0 \n"
|
||||||
"#define SHADOW_FILTER_SCALE 1 \n"
|
"#define SHADOW_FILTER_SCALE 1 \n"
|
||||||
|
|
||||||
"#define SHADOW_SAMPLES NUM_SHADOW_SAMPLES_1D*NUM_SHADOW_SAMPLES_1D \n"
|
"#define SHADOW_SAMPLES NUM_SHADOW_SAMPLES_1D*NUM_SHADOW_SAMPLES_1D \n"
|
||||||
|
@ -1362,27 +1401,17 @@ namespace Ogre
|
||||||
if (prof->getReceiveDynamicShadowsDepth())
|
if (prof->getReceiveDynamicShadowsDepth())
|
||||||
{
|
{
|
||||||
outStream <<
|
outStream <<
|
||||||
"float calcDepthShadow(sampler2D shadowMap, float4 uv, float invShadowMapSize) \n"
|
"float calcDepthShadow(sampler2D shadowMap, float4 shadowMapPos, float2 offset) \n"
|
||||||
" { \n"
|
" { \n"
|
||||||
" // 4-sample PCF \n"
|
" shadowMapPos = shadowMapPos / shadowMapPos.w; \n"
|
||||||
|
" float2 uv = shadowMapPos.xy; \n"
|
||||||
" float shadow = 0.0; \n"
|
" float3 o = float3(offset, -offset.x) * 0.3f; \n"
|
||||||
" float offset = (NUM_SHADOW_SAMPLES_1D/2 - 0.5) * SHADOW_FILTER_SCALE; \n"
|
" // Note: We using 2x2 PCF. Good enough and is alot faster. \n"
|
||||||
" for (float y = -offset; y <= offset; y += SHADOW_FILTER_SCALE) \n"
|
" float c = (shadowMapPos.z <= tex2D(shadowMap, uv.xy - o.xy).r) ? 1 : 0; // top left \n"
|
||||||
" for (float x = -offset; x <= offset; x += SHADOW_FILTER_SCALE) \n"
|
" c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy + o.xy).r) ? 1 : 0; // bottom right \n"
|
||||||
" { \n"
|
" c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy + o.zy).r) ? 1 : 0; // bottom left \n"
|
||||||
" float4 newUV = offsetSample(uv, float2(x, y), invShadowMapSize);\n"
|
" c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy - o.zy).r) ? 1 : 0; // top right \n"
|
||||||
" // manually project and assign derivatives \n"
|
" return c / 4; \n"
|
||||||
" // to avoid gradient issues inside loops \n"
|
|
||||||
" newUV = newUV / newUV.w; \n"
|
|
||||||
" float depth = tex2D(shadowMap, newUV.xy, 1, 1).x; \n"
|
|
||||||
" if (depth >= 1 || depth >= uv.z)\n"
|
|
||||||
" shadow += 1.0;\n"
|
|
||||||
" } \n"
|
|
||||||
|
|
||||||
" shadow /= SHADOW_SAMPLES; \n"
|
|
||||||
|
|
||||||
" return shadow; \n"
|
|
||||||
" } \n";
|
" } \n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1421,7 +1450,7 @@ namespace Ogre
|
||||||
{
|
{
|
||||||
outStream << "\n ";
|
outStream << "\n ";
|
||||||
for (uint i = 0; i < numTextures; ++i)
|
for (uint i = 0; i < numTextures; ++i)
|
||||||
outStream << "float invShadowmapSize" << i << ", ";
|
outStream << "float2 invShadowmapSize" << i << ", ";
|
||||||
}
|
}
|
||||||
outStream << "\n"
|
outStream << "\n"
|
||||||
" float4 pssmSplitPoints, float camDepth) \n"
|
" float4 pssmSplitPoints, float camDepth) \n"
|
||||||
|
@ -1443,7 +1472,7 @@ namespace Ogre
|
||||||
if (prof->getReceiveDynamicShadowsDepth())
|
if (prof->getReceiveDynamicShadowsDepth())
|
||||||
{
|
{
|
||||||
outStream <<
|
outStream <<
|
||||||
" shadow = calcDepthShadow(shadowMap" << i << ", lsPos" << i << ", invShadowmapSize" << i << "); \n";
|
" shadow = calcDepthShadow(shadowMap" << i << ", lsPos" << i << ", invShadowmapSize" << i << ".xy); \n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1505,20 +1534,12 @@ namespace Ogre
|
||||||
if (prof->getReceiveDynamicShadowsDepth())
|
if (prof->getReceiveDynamicShadowsDepth())
|
||||||
{
|
{
|
||||||
// make linear
|
// make linear
|
||||||
outStream <<
|
//outStream <<
|
||||||
"oLightSpacePos" << i << ".z = (oLightSpacePos" << i << ".z - depthRange" << i << ".x) * depthRange" << i << ".w;\n";
|
// "oLightSpacePos" << i << ".z = (oLightSpacePos" << i << ".z - depthRange" << i << ".x) * depthRange" << i << ".w;\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (prof->getReceiveDynamicShadowsPSSM())
|
|
||||||
{
|
|
||||||
outStream <<
|
|
||||||
" // pass cam depth\n"
|
|
||||||
" oUVMisc.z = oPos.z;\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateFpDynamicShadowsParams(
|
void TerrainMaterialGeneratorB::SM2Profile::ShaderHelperCg::generateFpDynamicShadowsParams(
|
||||||
|
@ -1531,6 +1552,8 @@ namespace Ogre
|
||||||
|
|
||||||
// in semantics & params
|
// in semantics & params
|
||||||
uint numTextures = 1;
|
uint numTextures = 1;
|
||||||
|
outStream <<
|
||||||
|
", uniform float4 shadowFar_fadeStart \n";
|
||||||
if (prof->getReceiveDynamicShadowsPSSM())
|
if (prof->getReceiveDynamicShadowsPSSM())
|
||||||
{
|
{
|
||||||
numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
|
numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
|
||||||
|
@ -1547,7 +1570,7 @@ namespace Ogre
|
||||||
if (prof->getReceiveDynamicShadowsDepth())
|
if (prof->getReceiveDynamicShadowsDepth())
|
||||||
{
|
{
|
||||||
outStream <<
|
outStream <<
|
||||||
", uniform float inverseShadowmapSize" << i << " \n";
|
", uniform float4 inverseShadowmapSize" << i << " \n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1582,7 +1605,7 @@ namespace Ogre
|
||||||
{
|
{
|
||||||
outStream << "\n ";
|
outStream << "\n ";
|
||||||
for (uint i = 0; i < numTextures; ++i)
|
for (uint i = 0; i < numTextures; ++i)
|
||||||
outStream << "inverseShadowmapSize" << i << ", ";
|
outStream << "inverseShadowmapSize" << i << ".xy, ";
|
||||||
}
|
}
|
||||||
outStream << "\n" <<
|
outStream << "\n" <<
|
||||||
" pssmSplitPoints, camDepth);\n";
|
" pssmSplitPoints, camDepth);\n";
|
||||||
|
@ -1593,7 +1616,7 @@ namespace Ogre
|
||||||
if (prof->getReceiveDynamicShadowsDepth())
|
if (prof->getReceiveDynamicShadowsDepth())
|
||||||
{
|
{
|
||||||
outStream <<
|
outStream <<
|
||||||
" float rtshadow = calcDepthShadow(shadowMap0, lightSpacePos0, inverseShadowmapSize0);";
|
" float rtshadow = calcDepthShadow(shadowMap0, lightSpacePos0, inverseShadowmapSize0.xy);";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1603,6 +1626,10 @@ namespace Ogre
|
||||||
}
|
}
|
||||||
|
|
||||||
outStream <<
|
outStream <<
|
||||||
|
" float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; \n"
|
||||||
|
" float fade = 1-((uvMisc.z - shadowFar_fadeStart.y) / fadeRange); \n"
|
||||||
|
" rtshadow = (uvMisc.z > shadowFar_fadeStart.x) ? 1 : ((uvMisc.z > shadowFar_fadeStart.y) ? 1-((1-rtshadow)*fade) : rtshadow); \n"
|
||||||
|
" rtshadow = (1-(1-rtshadow)*0.6); \n" // make the shadow a little less intensive
|
||||||
" shadow = min(shadow, rtshadow);\n";
|
" shadow = min(shadow, rtshadow);\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,9 @@ namespace Ogre
|
||||||
void updateParamsForCompositeMap(const MaterialPtr& mat, const Terrain* terrain);
|
void updateParamsForCompositeMap(const MaterialPtr& mat, const Terrain* terrain);
|
||||||
void requestOptions(Terrain* terrain);
|
void requestOptions(Terrain* terrain);
|
||||||
|
|
||||||
|
void setShadowFar(float far);
|
||||||
|
void setShadowFadeStart(float fadestart);
|
||||||
|
|
||||||
/** Whether to support normal mapping per layer in the shader (default true).
|
/** Whether to support normal mapping per layer in the shader (default true).
|
||||||
*/
|
*/
|
||||||
bool isLayerNormalMappingEnabled() const { return mLayerNormalMappingEnabled; }
|
bool isLayerNormalMappingEnabled() const { return mLayerNormalMappingEnabled; }
|
||||||
|
@ -245,6 +248,8 @@ namespace Ogre
|
||||||
bool mDepthShadows;
|
bool mDepthShadows;
|
||||||
bool mLowLodShadows;
|
bool mLowLodShadows;
|
||||||
bool mSM3Available;
|
bool mSM3Available;
|
||||||
|
float mShadowFar;
|
||||||
|
float mShadowFadeStart;
|
||||||
|
|
||||||
bool isShadowingEnabled(TechniqueType tt, const Terrain* terrain) const;
|
bool isShadowingEnabled(TechniqueType tt, const Terrain* terrain) const;
|
||||||
|
|
||||||
|
|
|
@ -1,50 +1,151 @@
|
||||||
#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), mToggled(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->setCastShadows(false);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
mReflectionCamera = mSceneManager->createCamera("ReflectionCamera");
|
||||||
|
|
||||||
if(!(cell->data.flags & cell->Interior))
|
if(!(cell->data.flags & cell->Interior))
|
||||||
{
|
{
|
||||||
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");
|
||||||
|
|
||||||
|
TexturePtr tex;
|
||||||
|
if (Settings::Manager::getBool("shader", "Water"))
|
||||||
|
{
|
||||||
|
tex = TextureManager::getSingleton().createManual("WaterReflection",
|
||||||
|
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_FLOAT16_RGBA, TU_RENDERTARGET);
|
||||||
|
|
||||||
|
RenderTarget* rtt = tex->getBuffer()->getRenderTarget();
|
||||||
|
Viewport* vp = rtt->addViewport(mReflectionCamera);
|
||||||
|
vp->setOverlaysEnabled(false);
|
||||||
|
vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f));
|
||||||
|
vp->setShadowsEnabled(false);
|
||||||
|
vp->setVisibilityMask( mVisibilityFlags );
|
||||||
|
// use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain)
|
||||||
|
//vp->setMaterialScheme("Fallback");
|
||||||
|
rtt->addListener(this);
|
||||||
|
rtt->setActive(true);
|
||||||
|
|
||||||
|
mReflectionTarget = rtt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT";
|
||||||
|
|
||||||
|
createMaterial();
|
||||||
|
mWater->setMaterial(mMaterial);
|
||||||
|
|
||||||
|
mUnderwaterEffect = Settings::Manager::getBool("underwater effect", "Water");
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------------
|
||||||
|
// ---------------------------------- reflection debug overlay ----------------------------------
|
||||||
|
// ----------------------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
if (Settings::Manager::getBool("shader", "Water"))
|
||||||
|
{
|
||||||
|
OverlayManager& mgr = OverlayManager::getSingleton();
|
||||||
|
Overlay* overlay;
|
||||||
|
// destroy if already exists
|
||||||
|
if (overlay = mgr.getByName("ReflectionDebugOverlay"))
|
||||||
|
mgr.destroy(overlay);
|
||||||
|
|
||||||
|
overlay = mgr.create("ReflectionDebugOverlay");
|
||||||
|
|
||||||
|
if (MaterialManager::getSingleton().resourceExists("Ogre/ReflectionDebugTexture"))
|
||||||
|
MaterialManager::getSingleton().remove("Ogre/ReflectionDebugTexture");
|
||||||
|
MaterialPtr debugMat = MaterialManager::getSingleton().create(
|
||||||
|
"Ogre/ReflectionDebugTexture",
|
||||||
|
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||||
|
|
||||||
|
debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
|
||||||
|
TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName());
|
||||||
|
t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
|
||||||
|
|
||||||
|
OverlayContainer* debugPanel;
|
||||||
|
|
||||||
|
// destroy container if exists
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (debugPanel =
|
||||||
|
static_cast<OverlayContainer*>(
|
||||||
|
mgr.getOverlayElement("Ogre/ReflectionDebugTexPanel"
|
||||||
|
)))
|
||||||
|
mgr.destroyOverlayElement(debugPanel);
|
||||||
|
}
|
||||||
|
catch (Ogre::Exception&) {}
|
||||||
|
|
||||||
|
debugPanel = (OverlayContainer*)
|
||||||
|
(OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/ReflectionDebugTexPanel"));
|
||||||
|
debugPanel->_setPosition(0, 0.55);
|
||||||
|
debugPanel->_setDimensions(0.3, 0.3);
|
||||||
|
debugPanel->setMaterialName(debugMat->getName());
|
||||||
|
debugPanel->show();
|
||||||
|
overlay->add2D(debugPanel);
|
||||||
|
overlay->show();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void Water::setActive(bool active)
|
||||||
|
{
|
||||||
|
mActive = active;
|
||||||
|
updateVisible();
|
||||||
|
}
|
||||||
|
|
||||||
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 +166,128 @@ void Water::setHeight(const float height)
|
||||||
|
|
||||||
void Water::toggle()
|
void Water::toggle()
|
||||||
{
|
{
|
||||||
mWater->setVisible(!mWater->getVisible());
|
mToggled = !mToggled;
|
||||||
|
updateVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
mWater->setRenderQueueGroup(RQG_UnderWater);
|
||||||
|
|
||||||
mIsUnderwater = true;
|
mIsUnderwater = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 Water::getSceneNodeCoordinates(int gridX, int gridY)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
mReflectionCamera->setOrientation(mCamera->getDerivedOrientation());
|
||||||
|
mReflectionCamera->setPosition(mCamera->getDerivedPosition());
|
||||||
|
mReflectionCamera->setNearClipDistance(mCamera->getNearClipDistance());
|
||||||
|
mReflectionCamera->setFarClipDistance(mCamera->getFarClipDistance());
|
||||||
|
mReflectionCamera->setAspectRatio(mCamera->getAspectRatio());
|
||||||
|
mReflectionCamera->setFOVy(mCamera->getFOVy());
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
mReflectionCamera->enableCustomNearClipPlane(Plane(Vector3::UNIT_Y, mTop));
|
||||||
|
mReflectionCamera->enableReflection(Plane(Vector3::UNIT_Y, mTop));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ogre::Vector3 Water::getSceneNodeCoordinates(int gridX, int gridY)
|
void Water::postRenderTargetUpdate(const RenderTargetEvent& evt)
|
||||||
{
|
{
|
||||||
return Ogre::Vector3(gridX * CELL_SIZE + (CELL_SIZE / 2), mTop, -gridY * CELL_SIZE - (CELL_SIZE / 2));
|
if (evt.source == mReflectionTarget)
|
||||||
|
{
|
||||||
|
mSky->resetSkyPosition();
|
||||||
|
mSky->scaleSky(1);
|
||||||
|
mReflectionCamera->disableCustomNearClipPlane();
|
||||||
|
mReflectionCamera->disableReflection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Water::updateVisible()
|
||||||
|
{
|
||||||
|
mWater->setVisible(mToggled && mActive);
|
||||||
|
if (mReflectionTarget)
|
||||||
|
mReflectionTarget->setActive(mToggled && mActive && !mIsUnderwater);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // 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,41 @@ namespace MWRender {
|
||||||
Ogre::Entity *mWater;
|
Ogre::Entity *mWater;
|
||||||
|
|
||||||
bool mIsUnderwater;
|
bool mIsUnderwater;
|
||||||
|
bool mActive;
|
||||||
|
bool mToggled;
|
||||||
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);
|
||||||
|
void updateVisible();
|
||||||
|
|
||||||
|
SkyManager* mSky;
|
||||||
|
|
||||||
|
std::string mCompositorName;
|
||||||
|
|
||||||
|
void createMaterial();
|
||||||
|
Ogre::MaterialPtr mMaterial;
|
||||||
|
|
||||||
|
Ogre::Camera* mReflectionCamera;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
|
@ -129,4 +129,10 @@ op 0x2000143: ModWaterLevel
|
||||||
op 0x2000144: ToggleWater, twa
|
op 0x2000144: ToggleWater, twa
|
||||||
op 0x2000145: ToggleFogOfWar (tfow)
|
op 0x2000145: ToggleFogOfWar (tfow)
|
||||||
op 0x2000146: TogglePathgrid
|
op 0x2000146: TogglePathgrid
|
||||||
opcodes 0x2000147-0x3ffffff unused
|
op 0x2000147: AddSpell
|
||||||
|
op 0x2000148: AddSpell, explicit reference
|
||||||
|
op 0x2000149: RemoveSpell
|
||||||
|
op 0x200014a: RemoveSpell, explicit reference
|
||||||
|
op 0x200014b: GetSpell
|
||||||
|
op 0x200014c: GetSpell, explicit reference
|
||||||
|
opcodes 0x200014d-0x3ffffff unused
|
||||||
|
|
|
@ -280,6 +280,65 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpAddSpell : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.add (id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpRemoveSpell : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.remove (id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class R>
|
||||||
|
class OpGetSpell : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
|
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
|
runtime.pop();
|
||||||
|
|
||||||
|
Interpreter::Type_Integer value = 0;
|
||||||
|
|
||||||
|
for (MWMechanics::Spells::TIterator iter (
|
||||||
|
MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.begin());
|
||||||
|
iter!=MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.end(); ++iter)
|
||||||
|
if (*iter==id)
|
||||||
|
{
|
||||||
|
value = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.push (value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const int numberOfAttributes = 8;
|
const int numberOfAttributes = 8;
|
||||||
|
|
||||||
const int opcodeGetAttribute = 0x2000027;
|
const int opcodeGetAttribute = 0x2000027;
|
||||||
|
@ -311,6 +370,13 @@ namespace MWScript
|
||||||
const int opcodeModSkill = 0x20000fa;
|
const int opcodeModSkill = 0x20000fa;
|
||||||
const int opcodeModSkillExplicit = 0x2000115;
|
const int opcodeModSkillExplicit = 0x2000115;
|
||||||
|
|
||||||
|
const int opcodeAddSpell = 0x2000147;
|
||||||
|
const int opcodeAddSpellExplicit = 0x2000148;
|
||||||
|
const int opcodeRemoveSpell = 0x2000149;
|
||||||
|
const int opcodeRemoveSpellExplicit = 0x200014a;
|
||||||
|
const int opcodeGetSpell = 0x200014b;
|
||||||
|
const int opcodeGetSpellExplicit = 0x200014c;
|
||||||
|
|
||||||
void registerExtensions (Compiler::Extensions& extensions)
|
void registerExtensions (Compiler::Extensions& extensions)
|
||||||
{
|
{
|
||||||
static const char *attributes[numberOfAttributes] =
|
static const char *attributes[numberOfAttributes] =
|
||||||
|
@ -381,6 +447,11 @@ namespace MWScript
|
||||||
extensions.registerInstruction (mod + skills[i], "l",
|
extensions.registerInstruction (mod + skills[i], "l",
|
||||||
opcodeModSkill+i, opcodeModSkillExplicit+i);
|
opcodeModSkill+i, opcodeModSkillExplicit+i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extensions.registerInstruction ("addspell", "c", opcodeAddSpell, opcodeAddSpellExplicit);
|
||||||
|
extensions.registerInstruction ("removespell", "c", opcodeRemoveSpell,
|
||||||
|
opcodeRemoveSpellExplicit);
|
||||||
|
extensions.registerFunction ("getspell", 'l', "c", opcodeGetSpell, opcodeGetSpellExplicit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
|
@ -436,6 +507,14 @@ namespace MWScript
|
||||||
interpreter.installSegment5 (opcodeModSkill+i, new OpModSkill<ImplicitRef> (i));
|
interpreter.installSegment5 (opcodeModSkill+i, new OpModSkill<ImplicitRef> (i));
|
||||||
interpreter.installSegment5 (opcodeModSkillExplicit+i, new OpModSkill<ExplicitRef> (i));
|
interpreter.installSegment5 (opcodeModSkillExplicit+i, new OpModSkill<ExplicitRef> (i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interpreter.installSegment5 (opcodeAddSpell, new OpAddSpell<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeAddSpellExplicit, new OpAddSpell<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeRemoveSpell, new OpRemoveSpell<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeRemoveSpellExplicit,
|
||||||
|
new OpRemoveSpell<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeGetSpell, new OpGetSpell<ImplicitRef>);
|
||||||
|
interpreter.installSegment5 (opcodeGetSpellExplicit, new OpGetSpell<ExplicitRef>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
struct Environment;
|
class Environment;
|
||||||
|
|
||||||
///< \brief Variant of the ContainerStore for NPCs
|
///< \brief Variant of the ContainerStore for NPCs
|
||||||
class InventoryStore : public ContainerStore
|
class InventoryStore : public ContainerStore
|
||||||
|
|
|
@ -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();
|
||||||
|
@ -98,4 +105,9 @@ 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);
|
||||||
|
|
|
@ -221,7 +221,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.
|
||||||
|
@ -274,8 +273,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)
|
||||||
|
|
|
@ -332,13 +332,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
|
||||||
{
|
{
|
||||||
|
@ -352,6 +354,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)
|
||||||
|
@ -469,6 +472,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;
|
||||||
|
|
||||||
|
@ -517,23 +521,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";
|
||||||
|
@ -581,8 +585,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);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,10 @@ add_component_dir (settings
|
||||||
settings
|
settings
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_component_dir (nifoverrides
|
||||||
|
nifoverrides
|
||||||
|
)
|
||||||
|
|
||||||
add_component_dir (bsa
|
add_component_dir (bsa
|
||||||
bsa_archive bsa_file
|
bsa_archive bsa_file
|
||||||
)
|
)
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "ogre_nif_loader.hpp"
|
#include "ogre_nif_loader.hpp"
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
#include <components/nifoverrides/nifoverrides.hpp>
|
||||||
|
|
||||||
typedef unsigned char ubyte;
|
typedef unsigned char ubyte;
|
||||||
|
|
||||||
|
@ -281,16 +282,62 @@ void NIFLoader::createMaterial(const String &name,
|
||||||
// NiAlphaProperty in nif/property.h if you need to decode
|
// NiAlphaProperty in nif/property.h if you need to decode
|
||||||
// other values. 237 basically means normal transparencly.
|
// other values. 237 basically means normal transparencly.
|
||||||
if (alphaFlags == 237)
|
if (alphaFlags == 237)
|
||||||
|
{
|
||||||
|
NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName);
|
||||||
|
if (result.first)
|
||||||
|
{
|
||||||
|
pass->setAlphaRejectFunction(CMPF_GREATER_EQUAL);
|
||||||
|
pass->setAlphaRejectValue(result.second);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// Enable transparency
|
// Enable transparency
|
||||||
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
|
|
||||||
//pass->setDepthCheckEnabled(false);
|
//pass->setDepthCheckEnabled(false);
|
||||||
pass->setDepthWriteEnabled(false);
|
pass->setDepthWriteEnabled(false);
|
||||||
|
//std::cout << "alpha 237; material: " << name << " texName: " << texName << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
warn("Unhandled alpha setting for texture " + texName);
|
warn("Unhandled alpha setting for texture " + texName);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
material->getTechnique(0)->setShadowCasterMaterial("depth_shadow_caster_noalpha");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Settings::Manager::getBool("enabled", "Shadows"))
|
||||||
|
{
|
||||||
|
bool split = Settings::Manager::getBool("split", "Shadows");
|
||||||
|
const int numsplits = 3;
|
||||||
|
for (int i = 0; i < (split ? numsplits : 1); ++i)
|
||||||
|
{
|
||||||
|
TextureUnitState* tu = material->getTechnique(0)->getPass(0)->createTextureUnitState();
|
||||||
|
tu->setName("shadowMap" + StringConverter::toString(i));
|
||||||
|
tu->setContentType(TextureUnitState::CONTENT_SHADOW);
|
||||||
|
tu->setTextureAddressingMode(TextureUnitState::TAM_BORDER);
|
||||||
|
tu->setTextureBorderColour(ColourValue::White);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Settings::Manager::getBool("shaders", "Objects"))
|
||||||
|
{
|
||||||
|
material->getTechnique(0)->getPass(0)->setVertexProgram("main_vp");
|
||||||
|
material->getTechnique(0)->getPass(0)->setFragmentProgram("main_fp");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a fallback technique without shadows and without mrt
|
||||||
|
Technique* tech2 = material->createTechnique();
|
||||||
|
tech2->setSchemeName("Fallback");
|
||||||
|
Pass* pass2 = tech2->createPass();
|
||||||
|
pass2->createTextureUnitState(texName);
|
||||||
|
pass2->setVertexColourTracking(TVC_DIFFUSE);
|
||||||
|
if (Settings::Manager::getBool("shaders", "Objects"))
|
||||||
|
{
|
||||||
|
pass2->setVertexProgram("main_fallback_vp");
|
||||||
|
pass2->setFragmentProgram("main_fallback_fp");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add material bells and whistles
|
// Add material bells and whistles
|
||||||
|
@ -299,137 +346,6 @@ void NIFLoader::createMaterial(const String &name,
|
||||||
material->setSpecular(specular.array[0], specular.array[1], specular.array[2], alpha);
|
material->setSpecular(specular.array[0], specular.array[1], specular.array[2], alpha);
|
||||||
material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]);
|
material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]);
|
||||||
material->setShininess(glossiness);
|
material->setShininess(glossiness);
|
||||||
|
|
||||||
if (Settings::Manager::getBool("shaders", "Objects"))
|
|
||||||
{
|
|
||||||
// Create shader for the material
|
|
||||||
// vertex
|
|
||||||
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
|
||||||
|
|
||||||
HighLevelGpuProgramPtr vertex;
|
|
||||||
if (mgr.getByName("main_vp").isNull())
|
|
||||||
{
|
|
||||||
vertex = mgr.createProgram("main_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
|
||||||
"cg", GPT_VERTEX_PROGRAM);
|
|
||||||
vertex->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1");
|
|
||||||
vertex->setParameter("entry_point", "main_vp");
|
|
||||||
StringUtil::StrStreamType outStream;
|
|
||||||
outStream <<
|
|
||||||
"void main_vp( \n"
|
|
||||||
" float4 position : POSITION, \n"
|
|
||||||
" float4 normal : NORMAL, \n"
|
|
||||||
" float4 colour : COLOR, \n"
|
|
||||||
" in float2 uv : TEXCOORD0, \n"
|
|
||||||
" out float2 oUV : TEXCOORD0, \n"
|
|
||||||
" out float4 oPosition : POSITION, \n"
|
|
||||||
" out float4 oPositionObjSpace : TEXCOORD1, \n"
|
|
||||||
" out float4 oNormal : TEXCOORD2, \n"
|
|
||||||
" out float oFogValue : TEXCOORD3, \n"
|
|
||||||
" out float4 oVertexColour : TEXCOORD4, \n"
|
|
||||||
" uniform float4 fogParams, \n"
|
|
||||||
" uniform float4x4 worldViewProj \n"
|
|
||||||
") \n"
|
|
||||||
"{ \n"
|
|
||||||
" oVertexColour = colour; \n"
|
|
||||||
" oUV = uv; \n"
|
|
||||||
" oNormal = normal; \n"
|
|
||||||
" oPosition = mul( worldViewProj, position ); \n"
|
|
||||||
" oFogValue = saturate((oPosition.z - fogParams.y) * fogParams.w); \n"
|
|
||||||
" oPositionObjSpace = position; \n"
|
|
||||||
"}";
|
|
||||||
vertex->setSource(outStream.str());
|
|
||||||
vertex->load();
|
|
||||||
vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
|
||||||
vertex->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vertex = mgr.getByName("main_vp");
|
|
||||||
material->getTechnique(0)->getPass(0)->setVertexProgram(vertex->getName());
|
|
||||||
|
|
||||||
// the number of lights to support.
|
|
||||||
// when rendering an object, OGRE automatically picks the lights that are
|
|
||||||
// closest to the object being rendered. unfortunately this mechanism does
|
|
||||||
// not work perfectly for objects batched together (they will all use the same
|
|
||||||
// lights). to work around this, we are simply pushing the maximum number
|
|
||||||
// of lights here in order to minimize disappearing lights.
|
|
||||||
int num_lights = Settings::Manager::getInt("num lights", "Objects");
|
|
||||||
|
|
||||||
// fragment
|
|
||||||
HighLevelGpuProgramPtr fragment;
|
|
||||||
if (mgr.getByName("main_fp").isNull())
|
|
||||||
{
|
|
||||||
fragment = mgr.createProgram("main_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
|
||||||
"cg", GPT_FRAGMENT_PROGRAM);
|
|
||||||
fragment->setParameter("profiles", "ps_4_0 ps_2_x fp40 arbfp1");
|
|
||||||
fragment->setParameter("entry_point", "main_fp");
|
|
||||||
StringUtil::StrStreamType outStream;
|
|
||||||
outStream <<
|
|
||||||
"void main_fp( \n"
|
|
||||||
" in float2 uv : TEXCOORD0, \n"
|
|
||||||
" out float4 oColor : COLOR, \n"
|
|
||||||
" uniform sampler2D texture : TEXUNIT0, \n"
|
|
||||||
" float4 positionObjSpace : TEXCOORD1, \n"
|
|
||||||
" float4 normal : TEXCOORD2, \n"
|
|
||||||
" float fogValue : TEXCOORD3, \n"
|
|
||||||
" float4 vertexColour : TEXCOORD4, \n"
|
|
||||||
" uniform float4 fogColour, \n";
|
|
||||||
|
|
||||||
for (int i=0; i<num_lights; ++i)
|
|
||||||
{
|
|
||||||
outStream <<
|
|
||||||
" uniform float4 lightDiffuse"<<i<<", \n"
|
|
||||||
" uniform float4 lightPositionObjSpace"<<i<<", \n"
|
|
||||||
" uniform float4 lightAttenuation"<<i<<", \n";
|
|
||||||
}
|
|
||||||
outStream <<
|
|
||||||
" uniform float4 lightAmbient, \n"
|
|
||||||
" uniform float4 ambient, \n"
|
|
||||||
" uniform float4 diffuse, \n"
|
|
||||||
" uniform float4 emissive \n"
|
|
||||||
") \n"
|
|
||||||
"{ \n"
|
|
||||||
" float4 tex = tex2D(texture, uv); \n"
|
|
||||||
" float d; \n"
|
|
||||||
" float attn; \n"
|
|
||||||
" float3 lightColour = float3(0, 0, 0); \n";
|
|
||||||
|
|
||||||
for (int i=0; i<num_lights; ++i)
|
|
||||||
{
|
|
||||||
outStream <<
|
|
||||||
" float3 lightDir"<<i<<" = lightPositionObjSpace"<<i<<".xyz - (positionObjSpace.xyz * lightPositionObjSpace"<<i<<".w); \n"
|
|
||||||
|
|
||||||
// pre-multiply light color with attenuation factor
|
|
||||||
" d = length( lightDir"<<i<<" ); \n"
|
|
||||||
" attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n"
|
|
||||||
" lightDiffuse"<<i<<" *= attn; \n"
|
|
||||||
|
|
||||||
" lightColour.xyz += lit(dot(normalize(lightDir"<<i<<"), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
outStream <<
|
|
||||||
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
|
|
||||||
" oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour, fogValue); \n"
|
|
||||||
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n"
|
|
||||||
"}";
|
|
||||||
fragment->setSource(outStream.str());
|
|
||||||
fragment->load();
|
|
||||||
|
|
||||||
for (int i=0; i<num_lights; ++i)
|
|
||||||
{
|
|
||||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightPositionObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i);
|
|
||||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightDiffuse"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i);
|
|
||||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
|
|
||||||
}
|
|
||||||
fragment->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
|
||||||
fragment->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
|
||||||
fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
|
|
||||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
|
|
||||||
fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fragment = mgr.getByName("main_fp");
|
|
||||||
material->getTechnique(0)->getPass(0)->setFragmentProgram(fragment->getName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes a name and adds a unique part to it. This is just used to
|
// Takes a name and adds a unique part to it. This is just used to
|
||||||
|
|
37
components/nifoverrides/nifoverrides.cpp
Normal file
37
components/nifoverrides/nifoverrides.cpp
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#include "nifoverrides.hpp"
|
||||||
|
|
||||||
|
#include <OgreStringConverter.h>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
|
using namespace NifOverrides;
|
||||||
|
|
||||||
|
Ogre::ConfigFile Overrides::mTransparencyOverrides = Ogre::ConfigFile();
|
||||||
|
|
||||||
|
void Overrides::loadTransparencyOverrides (const std::string& file)
|
||||||
|
{
|
||||||
|
mTransparencyOverrides.load(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
TransparencyResult Overrides::getTransparencyOverride(const std::string& texture)
|
||||||
|
{
|
||||||
|
TransparencyResult result;
|
||||||
|
result.first = false;
|
||||||
|
|
||||||
|
std::string tex = texture;
|
||||||
|
boost::to_lower(tex);
|
||||||
|
|
||||||
|
Ogre::ConfigFile::SectionIterator seci = mTransparencyOverrides.getSectionIterator();
|
||||||
|
while (seci.hasMoreElements())
|
||||||
|
{
|
||||||
|
Ogre::String sectionName = seci.peekNextKey();
|
||||||
|
if (sectionName == tex)
|
||||||
|
{
|
||||||
|
result.first = true;
|
||||||
|
result.second = Ogre::StringConverter::parseInt(mTransparencyOverrides.getSetting("alphaRejectValue", sectionName));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
seci.getNext();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
23
components/nifoverrides/nifoverrides.hpp
Normal file
23
components/nifoverrides/nifoverrides.hpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef COMPONENTS_NIFOVERRIDES_H
|
||||||
|
#define COMPONENTS_NIFOVERRIDES_H
|
||||||
|
|
||||||
|
#include <OgreConfigFile.h>
|
||||||
|
|
||||||
|
namespace NifOverrides
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef std::pair<bool, int> TransparencyResult;
|
||||||
|
|
||||||
|
/// \brief provide overrides for some model / texture properties that bethesda has chosen poorly
|
||||||
|
class Overrides
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static Ogre::ConfigFile mTransparencyOverrides;
|
||||||
|
void loadTransparencyOverrides (const std::string& file);
|
||||||
|
|
||||||
|
static TransparencyResult getTransparencyOverride(const std::string& texture);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,13 +1,16 @@
|
||||||
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)
|
||||||
|
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/shadows/depthshadowcaster.material "${OpenMW_BINARY_DIR}/resources/shadows/depthshadowcaster.material" COPYONLY)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/shadows/depthshadowcaster.cg "${OpenMW_BINARY_DIR}/resources/shadows/depthshadowcaster.cg" COPYONLY)
|
||||||
|
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,6 @@ configure_file("${SDIR}/bigbars.png" "${DDIR}/bigbars.png" COPYONLY)
|
||||||
configure_file("${SDIR}/black.png" "${DDIR}/black.png" COPYONLY)
|
configure_file("${SDIR}/black.png" "${DDIR}/black.png" COPYONLY)
|
||||||
configure_file("${SDIR}/core.skin" "${DDIR}/core.skin" COPYONLY)
|
configure_file("${SDIR}/core.skin" "${DDIR}/core.skin" COPYONLY)
|
||||||
configure_file("${SDIR}/core.xml" "${DDIR}/core.xml" COPYONLY)
|
configure_file("${SDIR}/core.xml" "${DDIR}/core.xml" COPYONLY)
|
||||||
configure_file("${SDIR}/mwpointer.png" "${DDIR}/mwpointer.png" COPYONLY)
|
|
||||||
configure_file("${SDIR}/mwgui.png" "${DDIR}/mwgui.png" COPYONLY)
|
configure_file("${SDIR}/mwgui.png" "${DDIR}/mwgui.png" COPYONLY)
|
||||||
configure_file("${SDIR}/openmw_images.xml" "${DDIR}/openmw_images.xml" COPYONLY)
|
configure_file("${SDIR}/openmw_images.xml" "${DDIR}/openmw_images.xml" COPYONLY)
|
||||||
configure_file("${SDIR}/openmw_settings.xml" "${DDIR}/openmw_settings.xml" COPYONLY)
|
configure_file("${SDIR}/openmw_settings.xml" "${DDIR}/openmw_settings.xml" COPYONLY)
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.7 KiB |
|
@ -2,37 +2,37 @@
|
||||||
|
|
||||||
<MyGUI type="Resource">
|
<MyGUI type="Resource">
|
||||||
<Resource type="ResourceImageSet" name="ArrowPointerImage">
|
<Resource type="ResourceImageSet" name="ArrowPointerImage">
|
||||||
<Group name="Pointer" texture="mwpointer.png" size="32 32">
|
<Group name="Pointer" texture="textures\tx_cursor.dds" size="32 32">
|
||||||
<Index name="Pointer" >
|
<Index name="Pointer" >
|
||||||
<Frame point="0 0"/>
|
<Frame point="0 0"/>
|
||||||
</Index>
|
</Index>
|
||||||
</Group>
|
</Group>
|
||||||
</Resource>
|
</Resource>
|
||||||
<Resource type="ResourceImageSet" name="HResizePointerImage">
|
<Resource type="ResourceImageSet" name="HResizePointerImage">
|
||||||
<Group name="Pointer" texture="mwpointer.png" size="32 32">
|
<Group name="Pointer" texture="textures\tx_cursormove.dds" size="32 32">
|
||||||
<Index name="Pointer" >
|
<Index name="Pointer" >
|
||||||
<Frame point="32 0"/>
|
<Frame point="0 0"/>
|
||||||
</Index>
|
</Index>
|
||||||
</Group>
|
</Group>
|
||||||
</Resource>
|
</Resource>
|
||||||
<Resource type="ResourceImageSet" name="VResizePointerImage">
|
<Resource type="ResourceImageSet" name="VResizePointerImage">
|
||||||
<Group name="Pointer" texture="mwpointer.png" size="32 32">
|
<Group name="Pointer" texture="mwpointer_vresize.png" size="32 32">
|
||||||
<Index name="Pointer" >
|
<Index name="Pointer" >
|
||||||
<Frame point="0 32"/>
|
<Frame point="0 0"/>
|
||||||
</Index>
|
</Index>
|
||||||
</Group>
|
</Group>
|
||||||
</Resource>
|
</Resource>
|
||||||
<Resource type="ResourceImageSet" name="DResizePointerImage">
|
<Resource type="ResourceImageSet" name="DResizePointerImage">
|
||||||
<Group name="Pointer" texture="mwpointer.png" size="32 32">
|
<Group name="Pointer" texture="mwpointer_dresize1.png" size="32 32">
|
||||||
<Index name="Pointer" >
|
<Index name="Pointer" >
|
||||||
<Frame point="32 32"/>
|
<Frame point="o o"/>
|
||||||
</Index>
|
</Index>
|
||||||
</Group>
|
</Group>
|
||||||
</Resource>
|
</Resource>
|
||||||
<Resource type="ResourceImageSet" name="DResize2PointerImage">
|
<Resource type="ResourceImageSet" name="DResize2PointerImage">
|
||||||
<Group name="Pointer" texture="mwpointer.png" size="32 32">
|
<Group name="Pointer" texture="mwpointer_dresize2.png" size="32 32">
|
||||||
<Index name="Pointer" >
|
<Index name="Pointer" >
|
||||||
<Frame point="64 32"/>
|
<Frame point="0 0"/>
|
||||||
</Index>
|
</Index>
|
||||||
</Group>
|
</Group>
|
||||||
</Resource>
|
</Resource>
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<MyGUI type="Resource" version="1.1">
|
|
||||||
<Resource type="ResourceSkin" name="Skin name 0" size="32 32" texture="">
|
|
||||||
<BasisSkin type="SubSkin" offset="0 0 32 32" align="Stretch">
|
|
||||||
<State name="normal" offset="0 0 32 32"/>
|
|
||||||
</BasisSkin>
|
|
||||||
</Resource>
|
|
||||||
</MyGUI>
|
|
|
@ -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
|
||||||
|
@ -14,6 +18,32 @@ anisotropy = 4
|
||||||
# Number of texture mipmaps to generate
|
# Number of texture mipmaps to generate
|
||||||
num mipmaps = 5
|
num mipmaps = 5
|
||||||
|
|
||||||
|
[Shadows]
|
||||||
|
# Shadows are only supported when object shaders are on!
|
||||||
|
enabled = false
|
||||||
|
|
||||||
|
# Split the shadow maps, allows for a larger shadow distance
|
||||||
|
# Warning: enabling this will cause some terrain textures to disappear due to
|
||||||
|
# hitting the texture unit limit of the terrain material
|
||||||
|
split = false
|
||||||
|
|
||||||
|
# Increasing shadow distance will lower the shadow quality.
|
||||||
|
# Uses "shadow distance" or "split shadow distance" depending on "split" setting.
|
||||||
|
shadow distance = 1300
|
||||||
|
# This one shouldn't be too low, otherwise you'll see artifacts. Use at least 2x max viewing distance.
|
||||||
|
split shadow distance = 14000
|
||||||
|
|
||||||
|
# Size of the shadow textures, higher means higher quality
|
||||||
|
texture size = 1024
|
||||||
|
|
||||||
|
# Turn on/off various shadow casters
|
||||||
|
actor shadows = true
|
||||||
|
misc shadows = true
|
||||||
|
statics shadows = true
|
||||||
|
|
||||||
|
# Fraction of the total shadow distance after which the shadow starts to fade out
|
||||||
|
fade start = 0.8
|
||||||
|
|
||||||
[HUD]
|
[HUD]
|
||||||
# FPS counter
|
# FPS counter
|
||||||
# 0: not visible
|
# 0: not visible
|
||||||
|
@ -54,6 +84,21 @@ 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 =
|
||||||
|
|
51
files/shadows/depthshadowcaster.cg
Normal file
51
files/shadows/depthshadowcaster.cg
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
void main_vp(
|
||||||
|
float4 position : POSITION,
|
||||||
|
float2 uv : TEXCOORD0,
|
||||||
|
|
||||||
|
out float4 oPosition : POSITION,
|
||||||
|
out float2 oDepth : TEXCOORD0,
|
||||||
|
out float2 oUv : TEXCOORD1,
|
||||||
|
|
||||||
|
uniform float4x4 wvpMat)
|
||||||
|
{
|
||||||
|
// this is the view space position
|
||||||
|
oPosition = mul(wvpMat, position);
|
||||||
|
|
||||||
|
// depth info for the fragment.
|
||||||
|
oDepth.x = oPosition.z;
|
||||||
|
oDepth.y = oPosition.w;
|
||||||
|
|
||||||
|
// clamp z to zero. seem to do the trick. :-/
|
||||||
|
oPosition.z = max(oPosition.z, 0);
|
||||||
|
|
||||||
|
oUv = uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_fp(
|
||||||
|
float2 depth : TEXCOORD0,
|
||||||
|
float2 uv : TEXCOORD1,
|
||||||
|
uniform sampler2D texture1 : register(s0),
|
||||||
|
|
||||||
|
out float4 oColour : COLOR)
|
||||||
|
{
|
||||||
|
float finalDepth = depth.x / depth.y;
|
||||||
|
|
||||||
|
// use alpha channel of the first texture
|
||||||
|
float alpha = tex2D(texture1, uv).a;
|
||||||
|
|
||||||
|
// discard if alpha is less than 0.5
|
||||||
|
clip((alpha >= 0.5) ? 1 : -1);
|
||||||
|
|
||||||
|
oColour = float4(finalDepth, finalDepth, finalDepth, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_fp_noalpha(
|
||||||
|
float2 depth : TEXCOORD0,
|
||||||
|
float2 uv : TEXCOORD1,
|
||||||
|
|
||||||
|
out float4 oColour : COLOR)
|
||||||
|
{
|
||||||
|
float finalDepth = depth.x / depth.y;
|
||||||
|
|
||||||
|
oColour = float4(finalDepth, finalDepth, finalDepth, 1);
|
||||||
|
}
|
67
files/shadows/depthshadowcaster.material
Normal file
67
files/shadows/depthshadowcaster.material
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
vertex_program depth_shadow_caster_vs cg
|
||||||
|
{
|
||||||
|
source depthshadowcaster.cg
|
||||||
|
profiles vs_1_1 arbvp1
|
||||||
|
entry_point main_vp
|
||||||
|
|
||||||
|
default_params
|
||||||
|
{
|
||||||
|
param_named_auto wvpMat worldviewproj_matrix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment_program depth_shadow_caster_ps cg
|
||||||
|
{
|
||||||
|
source depthshadowcaster.cg
|
||||||
|
profiles ps_2_0 arbfp1
|
||||||
|
entry_point main_fp
|
||||||
|
|
||||||
|
default_params
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment_program depth_shadow_caster_ps_noalpha cg
|
||||||
|
{
|
||||||
|
source depthshadowcaster.cg
|
||||||
|
profiles ps_2_0 arbfp1
|
||||||
|
entry_point main_fp_noalpha
|
||||||
|
|
||||||
|
default_params
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
material depth_shadow_caster
|
||||||
|
{
|
||||||
|
technique
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
vertex_program_ref depth_shadow_caster_vs
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment_program_ref depth_shadow_caster_ps
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
material depth_shadow_caster_noalpha
|
||||||
|
{
|
||||||
|
technique
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
vertex_program_ref depth_shadow_caster_vs
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment_program_ref depth_shadow_caster_ps_noalpha
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
574
files/transparency-overrides.cfg
Normal file
574
files/transparency-overrides.cfg
Normal file
|
@ -0,0 +1,574 @@
|
||||||
|
# Bethesda has used wrong transparency settings for many textures
|
||||||
|
# (who would have guessed)
|
||||||
|
# This is very unfortunate because objects with real transparency:
|
||||||
|
# - cannot cast shadows
|
||||||
|
# - cannot receive advanced framebuffer effects like depth of field or ambient occlusion
|
||||||
|
# - cannot cover lens flare effects (the lens flare will just shine through)
|
||||||
|
|
||||||
|
# This file lists textures that should be using alpha rejection instead of transparency
|
||||||
|
# basically these are textures that are not translucent (i.e. at one spot on the texture, either transparent or opaque)
|
||||||
|
|
||||||
|
# Note: all the texture names here have to be lowercase
|
||||||
|
|
||||||
|
# fauna
|
||||||
|
[textures\tx_wickwheat_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_wickwheat_03.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_red_lichen_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_stone_flower_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ivy_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ivy_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_saltrice_04.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_black_lichen_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_leaves_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_leaves_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_leaves_03.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_leaves_04.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_leaves_06.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_leaves_07.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ai_heather_01.dds]
|
||||||
|
alphaRejectValue = 96
|
||||||
|
|
||||||
|
[textures\tx_goldkanet_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_goldkanet_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_plant_tails00.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_vine_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_comberry_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_willow_flower_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_cork_bulb_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_green_lichen_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_roobrush_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bittergreen_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_chokeweed_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_branches_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_branches_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_guarskin_hut_03.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_hackle-lo_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bc_fern_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bc_fern_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bc_leaves_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_marshmerrow_03.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bc_moss_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bc_moss_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bc_lilypad_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bc_lilypad_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bc_lilypad_03.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_fire_fern_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
# banners and flags
|
||||||
|
[textures\tx_flag_imp_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_arena_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_comfort_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_child_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_count_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_faith_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_walk_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_imp_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_redoran_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_avs_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_serving_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_speak_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_stdeyln_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_stolms_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_thin_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_vivec_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_vivec_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ashl_banner_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ashl_banner_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ashl_banner_04.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ashl_banner_05.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ashl_banner_06.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ashl_banner_07.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ashl_a_banner.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ashl_e_banner.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ashl_u_banner.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ashl_z_banner.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_banner_6th.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_banner_6th_tall.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_banner_gnisis_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_banner_gnisis_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_bhm_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_03.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_04.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_05.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_06.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_07.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_08.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_08.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_09.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_10.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_11.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_12.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_tapestry_13.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_lutestrings_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_fabric_imp_altar_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_akatosh_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_apprentice_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_arkay_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_dibella_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_golem_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_julianos_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_kynareth_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_lady_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_lord_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_lover_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_mara_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_ritual_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_shadow_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_steed_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_stendarr_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_thief_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_tower_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_warrior_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_wizard_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_c_t_zenithar_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_banner_dagoth_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bannerd_tavern_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bannerd_goods_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bannerd_danger_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bannerd_welcome_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bannerd_clothing_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bannerd_alchemy_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_banner_hlaalu_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_banner_redoran_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_banner_temple_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_banner_temple_03.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_book_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_ald_velothi.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_gnaar_mok.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_hla_oad.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_khull.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_pawn_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_sadrith_mora.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_tel_aruhn.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_tel_branora.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_tel_fyr.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_tel_mora.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_telvani_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_tel_vos.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_de_banner_vos.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bannerd_w_a_shop_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_banner_temple_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_mural1_00.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_mural1_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_mural4_00.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_mural4_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_mural5_00.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_telvanni_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_v_b_hlaalu_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_fabric_tapestry.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_fabric_tapestry_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_fabric_tapestry_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_fabric_tapestry_03.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_fabric_tapestry_04.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
# characters
|
||||||
|
[textures\tx_netchgod00.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_b_n_argonian_f_hair02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_b_n_argonian_f_hair03.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_b_n_argonian_m_hair01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_b_n_argonian_m_hair04.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_b_n_argonian_m_hair05.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_b_n_khajiit_f_hair01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_b_n_khajiit_f_hair02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_b_n_khajiit_m_hair01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_corprus_stalker12.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_a_clavicus02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_b_n_dark elf_m_hair11.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_b_n_dark elf_f_hair10.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
# misc items
|
||||||
|
[textures\tx_sail.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_longboatsail01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_longboatsail01a.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_longboatsail01b.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_longboatsail02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_quill.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_note_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_note_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_parchment_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_parchment_03.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_scroll_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_scroll_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_scroll_03.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_alpha_small_edge.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_alpha_shadow_circular.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
# building materials
|
||||||
|
[textures\tx_shack_thatch_strip.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_rug00.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_rug_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_rug_edge_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_awning_thatch_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_awning_woven_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_bridgeropes.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_rope_woven_01.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_rope_woven_02.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_ashl_tent_06.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_guar_tarp.dds]
|
||||||
|
alphaRejectValue = 128
|
||||||
|
|
||||||
|
[textures\tx_velothi_glyph00.dds]
|
||||||
|
alphaRejectValue = 128
|
|
@ -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 Fallback
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
cull_hardware none
|
||||||
|
scene_blend alpha_blend
|
||||||
|
depth_write off
|
||||||
|
diffuse 0 0 0 1
|
||||||
|
emissive 0.6 0.7 1.0
|
||||||
|
ambient 0 0 0
|
||||||
|
texture_unit
|
||||||
|
{
|
||||||
|
// texture names set via code
|
||||||
|
scale 0.1 0.1
|
||||||
|
alpha_op_ex source1 src_manual src_current 0.7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
material Water/CompositorNoMRT
|
||||||
|
{
|
||||||
|
technique
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
depth_check off
|
||||||
|
vertex_program_ref UnderwaterEffectVP
|
||||||
|
{
|
||||||
|
param_named_auto timeVal time 0.25
|
||||||
|
param_named scale float 0.1
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment_program_ref UnderwaterEffectFP_NoMRT
|
||||||
|
{
|
||||||
|
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.
74
libs/openengine/ogre/imagerotate.cpp
Normal file
74
libs/openengine/ogre/imagerotate.cpp
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#include "imagerotate.hpp"
|
||||||
|
|
||||||
|
#include <OgreRoot.h>
|
||||||
|
#include <OgreSceneManager.h>
|
||||||
|
#include <OgreImage.h>
|
||||||
|
#include <OgreTexture.h>
|
||||||
|
#include <OgreRenderTarget.h>
|
||||||
|
#include <OgreCamera.h>
|
||||||
|
#include <OgreTextureUnitState.h>
|
||||||
|
#include <OgreHardwarePixelBuffer.h>
|
||||||
|
|
||||||
|
using namespace Ogre;
|
||||||
|
using namespace OEngine::Render;
|
||||||
|
|
||||||
|
void ImageRotate::rotate(const std::string& sourceImage, const std::string& destImage, const float angle)
|
||||||
|
{
|
||||||
|
Root* root = Ogre::Root::getSingletonPtr();
|
||||||
|
|
||||||
|
SceneManager* sceneMgr = root->createSceneManager(ST_GENERIC);
|
||||||
|
Camera* camera = sceneMgr->createCamera("ImageRotateCamera");
|
||||||
|
|
||||||
|
MaterialPtr material = MaterialManager::getSingleton().create("ImageRotateMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||||
|
material->getTechnique(0)->getPass(0)->setLightingEnabled(false);
|
||||||
|
material->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
|
||||||
|
TextureUnitState* tus = material->getTechnique(0)->getPass(0)->createTextureUnitState(sourceImage);
|
||||||
|
Degree deg(angle);
|
||||||
|
tus->setTextureRotate(Radian(deg.valueRadians()));
|
||||||
|
tus->setTextureAddressingMode(TextureUnitState::TAM_BORDER);
|
||||||
|
tus->setTextureBorderColour(ColourValue(0, 0, 0, 0));
|
||||||
|
|
||||||
|
Rectangle2D* rect = new Rectangle2D(true);
|
||||||
|
rect->setCorners(-1.0, 1.0, 1.0, -1.0);
|
||||||
|
rect->setMaterial("ImageRotateMaterial");
|
||||||
|
// Render the background before everything else
|
||||||
|
rect->setRenderQueueGroup(RENDER_QUEUE_BACKGROUND);
|
||||||
|
|
||||||
|
// Use infinite AAB to always stay visible
|
||||||
|
AxisAlignedBox aabInf;
|
||||||
|
aabInf.setInfinite();
|
||||||
|
rect->setBoundingBox(aabInf);
|
||||||
|
|
||||||
|
// Attach background to the scene
|
||||||
|
SceneNode* node = sceneMgr->getRootSceneNode()->createChildSceneNode();
|
||||||
|
node->attachObject(rect);
|
||||||
|
|
||||||
|
// retrieve image width and height
|
||||||
|
TexturePtr sourceTexture = TextureManager::getSingleton().getByName(sourceImage);
|
||||||
|
unsigned int width = sourceTexture->getWidth();
|
||||||
|
unsigned int height = sourceTexture->getHeight();
|
||||||
|
|
||||||
|
TexturePtr destTexture = TextureManager::getSingleton().createManual(
|
||||||
|
destImage,
|
||||||
|
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
TEX_TYPE_2D,
|
||||||
|
width, height,
|
||||||
|
0,
|
||||||
|
PF_A8R8G8B8,
|
||||||
|
TU_RENDERTARGET);
|
||||||
|
|
||||||
|
RenderTarget* rtt = destTexture->getBuffer()->getRenderTarget();
|
||||||
|
rtt->setAutoUpdated(false);
|
||||||
|
Viewport* vp = rtt->addViewport(camera);
|
||||||
|
vp->setOverlaysEnabled(false);
|
||||||
|
vp->setShadowsEnabled(false);
|
||||||
|
vp->setBackgroundColour(ColourValue(0,0,0,0));
|
||||||
|
vp->setClearEveryFrame(true, FBT_DEPTH);
|
||||||
|
|
||||||
|
rtt->update();
|
||||||
|
|
||||||
|
// remove all the junk we've created
|
||||||
|
MaterialManager::getSingleton().remove("ImageRotateMaterial");
|
||||||
|
root->destroySceneManager(sceneMgr);
|
||||||
|
delete rect;
|
||||||
|
}
|
27
libs/openengine/ogre/imagerotate.hpp
Normal file
27
libs/openengine/ogre/imagerotate.hpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef OENGINE_OGRE_IMAGEROTATE_HPP
|
||||||
|
#define OENGINE_OGRE_IMAGEROTATE_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace OEngine
|
||||||
|
{
|
||||||
|
namespace Render
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Rotate an image by certain degrees and save as file, uses the GPU
|
||||||
|
/// Make sure Ogre Root is initialised before calling
|
||||||
|
class ImageRotate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @param source image (file name - has to exist in an resource group)
|
||||||
|
* @param name of the destination texture to save to (in memory)
|
||||||
|
* @param angle in degrees to turn
|
||||||
|
*/
|
||||||
|
static void rotate(const std::string& sourceImage, const std::string& destImage, const float angle);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -95,6 +95,7 @@ Allowed options:
|
||||||
CREDITS
|
CREDITS
|
||||||
|
|
||||||
Current Developers:
|
Current Developers:
|
||||||
|
Aleksandar Jovanov
|
||||||
Alexander “Ace” Olofsson
|
Alexander “Ace” Olofsson
|
||||||
athile
|
athile
|
||||||
BrotherBrick
|
BrotherBrick
|
||||||
|
|
Loading…
Reference in a new issue