mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-10 12:39:53 +00:00
Add glow effect for enchanted items
This commit is contained in:
parent
0b9676aaa3
commit
3452bd2e0b
@ -17,6 +17,8 @@
|
|||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include <extern/shiny/Main/Factory.hpp>
|
||||||
|
|
||||||
#include "../mwmechanics/character.hpp"
|
#include "../mwmechanics/character.hpp"
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
@ -24,6 +26,7 @@
|
|||||||
|
|
||||||
#include "renderconst.hpp"
|
#include "renderconst.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -166,8 +169,37 @@ void Animation::setObjectRoot(const std::string &model, bool baseonly)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AddGlow
|
||||||
|
{
|
||||||
|
Ogre::Vector3* mColor;
|
||||||
|
AddGlow(Ogre::Vector3* col) : mColor(col) {}
|
||||||
|
|
||||||
class VisQueueSet {
|
// TODO: integrate this with material controllers?
|
||||||
|
void operator()(Ogre::Entity* entity) const
|
||||||
|
{
|
||||||
|
unsigned int numsubs = entity->getNumSubEntities();
|
||||||
|
for(unsigned int i = 0;i < numsubs;++i)
|
||||||
|
{
|
||||||
|
unsigned int numsubs = entity->getNumSubEntities();
|
||||||
|
for(unsigned int i = 0;i < numsubs;++i)
|
||||||
|
{
|
||||||
|
Ogre::SubEntity* subEnt = entity->getSubEntity(i);
|
||||||
|
std::string newName = subEnt->getMaterialName() + "@fx";
|
||||||
|
if (sh::Factory::getInstance().searchInstance(newName) == NULL)
|
||||||
|
{
|
||||||
|
sh::MaterialInstance* instance =
|
||||||
|
sh::Factory::getInstance().createMaterialInstance(newName, subEnt->getMaterialName());
|
||||||
|
instance->setProperty("env_map", sh::makeProperty(new sh::BooleanValue(true)));
|
||||||
|
instance->setProperty("env_map_color", sh::makeProperty(new sh::Vector3(mColor->x, mColor->y, mColor->z)));
|
||||||
|
}
|
||||||
|
subEnt->setMaterialName(newName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class VisQueueSet
|
||||||
|
{
|
||||||
Ogre::uint32 mVisFlags;
|
Ogre::uint32 mVisFlags;
|
||||||
Ogre::uint8 mSolidQueue, mTransQueue;
|
Ogre::uint8 mSolidQueue, mTransQueue;
|
||||||
Ogre::Real mDist;
|
Ogre::Real mDist;
|
||||||
@ -201,12 +233,16 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue, Ogre::Real dist)
|
void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue, Ogre::Real dist, bool enchantedGlow, Ogre::Vector3* glowColor)
|
||||||
{
|
{
|
||||||
std::for_each(objlist.mEntities.begin(), objlist.mEntities.end(),
|
std::for_each(objlist.mEntities.begin(), objlist.mEntities.end(),
|
||||||
VisQueueSet(visflags, solidqueue, transqueue, dist));
|
VisQueueSet(visflags, solidqueue, transqueue, dist));
|
||||||
std::for_each(objlist.mParticles.begin(), objlist.mParticles.end(),
|
std::for_each(objlist.mParticles.begin(), objlist.mParticles.end(),
|
||||||
VisQueueSet(visflags, solidqueue, transqueue, dist));
|
VisQueueSet(visflags, solidqueue, transqueue, dist));
|
||||||
|
|
||||||
|
if (enchantedGlow)
|
||||||
|
std::for_each(objlist.mEntities.begin(), objlist.mEntities.end(),
|
||||||
|
AddGlow(glowColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1116,6 +1152,23 @@ void Animation::updateEffects(float duration)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Should not be here
|
||||||
|
Ogre::Vector3 Animation::getEnchantmentColor(MWWorld::Ptr item)
|
||||||
|
{
|
||||||
|
Ogre::Vector3 result(1,1,1);
|
||||||
|
std::string enchantmentName = item.getClass().getEnchantment(item);
|
||||||
|
if (enchantmentName.empty())
|
||||||
|
return result;
|
||||||
|
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(enchantmentName);
|
||||||
|
assert (enchantment->mEffects.mList.size());
|
||||||
|
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(
|
||||||
|
enchantment->mEffects.mList.front().mEffectID);
|
||||||
|
result.x = magicEffect->mData.mRed / 255.f;
|
||||||
|
result.y = magicEffect->mData.mGreen / 255.f;
|
||||||
|
result.z = magicEffect->mData.mBlue / 255.f;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ObjectAnimation::ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model)
|
ObjectAnimation::ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model)
|
||||||
: Animation(ptr, ptr.getRefData().getBaseNode())
|
: Animation(ptr, ptr.getRefData().getBaseNode())
|
||||||
@ -1132,9 +1185,10 @@ ObjectAnimation::ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &mod
|
|||||||
small = false;
|
small = false;
|
||||||
|
|
||||||
float dist = small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0.0f;
|
float dist = small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0.0f;
|
||||||
|
Ogre::Vector3 col = getEnchantmentColor(ptr);
|
||||||
setRenderProperties(mObjectRoot, (mPtr.getTypeName() == typeid(ESM::Static).name()) ?
|
setRenderProperties(mObjectRoot, (mPtr.getTypeName() == typeid(ESM::Static).name()) ?
|
||||||
(small ? RV_StaticsSmall : RV_Statics) : RV_Misc,
|
(small ? RV_StaticsSmall : RV_Statics) : RV_Misc,
|
||||||
RQG_Main, RQG_Alpha, dist);
|
RQG_Main, RQG_Alpha, dist, !ptr.getClass().getEnchantment(ptr).empty(), &col);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectAnimation::addLight(const ESM::Light *light)
|
void ObjectAnimation::addLight(const ESM::Light *light)
|
||||||
|
@ -191,10 +191,15 @@ protected:
|
|||||||
|
|
||||||
static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects);
|
static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects);
|
||||||
|
|
||||||
static void setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue, Ogre::Real dist=0.0f);
|
static void setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue,
|
||||||
|
Ogre::uint8 transqueue, Ogre::Real dist=0.0f,
|
||||||
|
bool enchantedGlow=false, Ogre::Vector3* glowColor=NULL);
|
||||||
|
|
||||||
void clearAnimSources();
|
void clearAnimSources();
|
||||||
|
|
||||||
|
// TODO: Should not be here
|
||||||
|
Ogre::Vector3 getEnchantmentColor(MWWorld::Ptr item);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node);
|
Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node);
|
||||||
virtual ~Animation();
|
virtual ~Animation();
|
||||||
|
@ -208,17 +208,19 @@ void NpcAnimation::updateParts()
|
|||||||
removeIndividualPart(ESM::PRT_Hair);
|
removeIndividualPart(ESM::PRT_Hair);
|
||||||
|
|
||||||
int prio = 1;
|
int prio = 1;
|
||||||
|
bool enchantedGlow = !store->getClass().getEnchantment(*store).empty();
|
||||||
|
Ogre::Vector3 glowColor = getEnchantmentColor(*store);
|
||||||
if(store->getTypeName() == typeid(ESM::Clothing).name())
|
if(store->getTypeName() == typeid(ESM::Clothing).name())
|
||||||
{
|
{
|
||||||
prio = ((slotlist[i].mBasePriority+1)<<1) + 0;
|
prio = ((slotlist[i].mBasePriority+1)<<1) + 0;
|
||||||
const ESM::Clothing *clothes = store->get<ESM::Clothing>()->mBase;
|
const ESM::Clothing *clothes = store->get<ESM::Clothing>()->mBase;
|
||||||
addPartGroup(slotlist[i].mSlot, prio, clothes->mParts.mParts);
|
addPartGroup(slotlist[i].mSlot, prio, clothes->mParts.mParts, enchantedGlow, &glowColor);
|
||||||
}
|
}
|
||||||
else if(store->getTypeName() == typeid(ESM::Armor).name())
|
else if(store->getTypeName() == typeid(ESM::Armor).name())
|
||||||
{
|
{
|
||||||
prio = ((slotlist[i].mBasePriority+1)<<1) + 1;
|
prio = ((slotlist[i].mBasePriority+1)<<1) + 1;
|
||||||
const ESM::Armor *armor = store->get<ESM::Armor>()->mBase;
|
const ESM::Armor *armor = store->get<ESM::Armor>()->mBase;
|
||||||
addPartGroup(slotlist[i].mSlot, prio, armor->mParts.mParts);
|
addPartGroup(slotlist[i].mSlot, prio, armor->mParts.mParts, enchantedGlow, &glowColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(slotlist[i].mSlot == MWWorld::InventoryStore::Slot_Robe)
|
if(slotlist[i].mSlot == MWWorld::InventoryStore::Slot_Robe)
|
||||||
@ -389,10 +391,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, int group, const std::string &bonename)
|
NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, int group, const std::string &bonename, bool enchantedGlow, Ogre::Vector3* glowColor)
|
||||||
{
|
{
|
||||||
NifOgre::ObjectList objects = NifOgre::Loader::createObjects(mSkelBase, bonename, mInsert, model);
|
NifOgre::ObjectList objects = NifOgre::Loader::createObjects(mSkelBase, bonename, mInsert, model);
|
||||||
setRenderProperties(objects, (mViewMode == VM_FirstPerson) ? RV_FirstPerson : mVisibilityFlags, RQG_Main, RQG_Alpha);
|
setRenderProperties(objects, (mViewMode == VM_FirstPerson) ? RV_FirstPerson : mVisibilityFlags, RQG_Main, RQG_Alpha, 0,
|
||||||
|
enchantedGlow, glowColor);
|
||||||
|
|
||||||
std::for_each(objects.mEntities.begin(), objects.mEntities.end(), SetObjectGroup(group));
|
std::for_each(objects.mEntities.begin(), objects.mEntities.end(), SetObjectGroup(group));
|
||||||
std::for_each(objects.mParticles.begin(), objects.mParticles.end(), SetObjectGroup(group));
|
std::for_each(objects.mParticles.begin(), objects.mParticles.end(), SetObjectGroup(group));
|
||||||
@ -475,7 +478,7 @@ void NpcAnimation::removePartGroup(int group)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int group, int priority, const std::string &mesh)
|
bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int group, int priority, const std::string &mesh, bool enchantedGlow, Ogre::Vector3* glowColor)
|
||||||
{
|
{
|
||||||
if(priority <= mPartPriorities[type])
|
if(priority <= mPartPriorities[type])
|
||||||
return false;
|
return false;
|
||||||
@ -484,7 +487,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
|
|||||||
mPartslots[type] = group;
|
mPartslots[type] = group;
|
||||||
mPartPriorities[type] = priority;
|
mPartPriorities[type] = priority;
|
||||||
|
|
||||||
mObjectParts[type] = insertBoundedPart(mesh, group, sPartList.at(type));
|
mObjectParts[type] = insertBoundedPart(mesh, group, sPartList.at(type), enchantedGlow, glowColor);
|
||||||
if(mObjectParts[type].mSkelBase)
|
if(mObjectParts[type].mSkelBase)
|
||||||
{
|
{
|
||||||
Ogre::SkeletonInstance *skel = mObjectParts[type].mSkelBase->getSkeleton();
|
Ogre::SkeletonInstance *skel = mObjectParts[type].mSkelBase->getSkeleton();
|
||||||
@ -521,7 +524,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts)
|
void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts, bool enchantedGlow, Ogre::Vector3* glowColor)
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
|
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
|
||||||
@ -559,7 +562,7 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(bodypart)
|
if(bodypart)
|
||||||
addOrReplaceIndividualPart((ESM::PartReferenceType)part->mPart, group, priority, "meshes\\"+bodypart->mModel);
|
addOrReplaceIndividualPart((ESM::PartReferenceType)part->mPart, group, priority, "meshes\\"+bodypart->mModel, enchantedGlow, glowColor);
|
||||||
else
|
else
|
||||||
reserveIndividualPart((ESM::PartReferenceType)part->mPart, group, priority);
|
reserveIndividualPart((ESM::PartReferenceType)part->mPart, group, priority);
|
||||||
}
|
}
|
||||||
@ -574,8 +577,10 @@ void NpcAnimation::showWeapons(bool showWeapon)
|
|||||||
MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
if(weapon != inv.end()) // special case for weapons
|
if(weapon != inv.end()) // special case for weapons
|
||||||
{
|
{
|
||||||
|
Ogre::Vector3 glowColor = getEnchantmentColor(*weapon);
|
||||||
std::string mesh = MWWorld::Class::get(*weapon).getModel(*weapon);
|
std::string mesh = MWWorld::Class::get(*weapon).getModel(*weapon);
|
||||||
addOrReplaceIndividualPart(ESM::PRT_Weapon, MWWorld::InventoryStore::Slot_CarriedRight, 1, mesh);
|
addOrReplaceIndividualPart(ESM::PRT_Weapon, MWWorld::InventoryStore::Slot_CarriedRight, 1,
|
||||||
|
mesh, !weapon->getClass().getEnchantment(*weapon).empty(), &glowColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -51,14 +51,17 @@ private:
|
|||||||
|
|
||||||
void updateNpcBase();
|
void updateNpcBase();
|
||||||
|
|
||||||
NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename);
|
NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename,
|
||||||
|
bool enchantedGlow, Ogre::Vector3* glowColor=NULL);
|
||||||
|
|
||||||
void removeIndividualPart(ESM::PartReferenceType type);
|
void removeIndividualPart(ESM::PartReferenceType type);
|
||||||
void reserveIndividualPart(ESM::PartReferenceType type, int group, int priority);
|
void reserveIndividualPart(ESM::PartReferenceType type, int group, int priority);
|
||||||
|
|
||||||
bool addOrReplaceIndividualPart(ESM::PartReferenceType type, int group, int priority, const std::string &mesh);
|
bool addOrReplaceIndividualPart(ESM::PartReferenceType type, int group, int priority, const std::string &mesh,
|
||||||
|
bool enchantedGlow=false, Ogre::Vector3* glowColor=NULL);
|
||||||
void removePartGroup(int group);
|
void removePartGroup(int group);
|
||||||
void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts);
|
void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts,
|
||||||
|
bool enchantedGlow=false, Ogre::Vector3* glowColor=NULL);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -33,6 +33,8 @@ class Objects{
|
|||||||
|
|
||||||
void insertBegin(const MWWorld::Ptr& ptr);
|
void insertBegin(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Objects(OEngine::Render::OgreRenderer &renderer)
|
Objects(OEngine::Render::OgreRenderer &renderer)
|
||||||
: mRenderer(renderer)
|
: mRenderer(renderer)
|
||||||
|
@ -49,8 +49,9 @@ struct MagicEffect
|
|||||||
int mSchool; // SpellSchool, see defs.hpp
|
int mSchool; // SpellSchool, see defs.hpp
|
||||||
float mBaseCost;
|
float mBaseCost;
|
||||||
int mFlags;
|
int mFlags;
|
||||||
// Properties of the fired magic 'ball' I think
|
// Glow color for enchanted items with this effect
|
||||||
int mRed, mBlue, mGreen;
|
int mRed, mGreen, mBlue;
|
||||||
|
// Properties of the fired magic 'ball'
|
||||||
float mSpeed, mSize, mSizeCap;
|
float mSpeed, mSize, mSizeCap;
|
||||||
}; // 36 bytes
|
}; // 36 bytes
|
||||||
|
|
||||||
|
3
extern/shiny/Main/Factory.hpp
vendored
3
extern/shiny/Main/Factory.hpp
vendored
@ -259,8 +259,9 @@ namespace sh
|
|||||||
Platform* mPlatform;
|
Platform* mPlatform;
|
||||||
|
|
||||||
MaterialInstance* findInstance (const std::string& name);
|
MaterialInstance* findInstance (const std::string& name);
|
||||||
|
public:
|
||||||
MaterialInstance* searchInstance (const std::string& name);
|
MaterialInstance* searchInstance (const std::string& name);
|
||||||
|
private:
|
||||||
/// @return was anything removed?
|
/// @return was anything removed?
|
||||||
bool removeCache (const std::string& pattern);
|
bool removeCache (const std::string& pattern);
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#include "OgreTextureUnitState.hpp"
|
#include "OgreTextureUnitState.hpp"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
#include "OgrePass.hpp"
|
#include "OgrePass.hpp"
|
||||||
#include "OgrePlatform.hpp"
|
#include "OgrePlatform.hpp"
|
||||||
#include "OgreMaterialSerializer.hpp"
|
#include "OgreMaterialSerializer.hpp"
|
||||||
@ -28,6 +31,32 @@ namespace sh
|
|||||||
setTextureName (retrieveValue<StringValue>(value, context).get());
|
setTextureName (retrieveValue<StringValue>(value, context).get());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (name == "anim_texture2")
|
||||||
|
{
|
||||||
|
std::string val = retrieveValue<StringValue>(value, context).get();
|
||||||
|
std::vector<std::string> tokens;
|
||||||
|
boost::split(tokens, val, boost::is_any_of(" "));
|
||||||
|
assert(tokens.size() == 3);
|
||||||
|
std::string texture = tokens[0];
|
||||||
|
int frames = boost::lexical_cast<int>(tokens[1]);
|
||||||
|
float duration = boost::lexical_cast<float>(tokens[2]);
|
||||||
|
|
||||||
|
std::vector<Ogre::String> frameTextures;
|
||||||
|
for (int i=0; i<frames; ++i)
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << std::setw(2);
|
||||||
|
stream << std::setfill('0');
|
||||||
|
stream << i;
|
||||||
|
stream << '.';
|
||||||
|
std::string tex = texture;
|
||||||
|
boost::replace_last(tex, ".", stream.str());
|
||||||
|
frameTextures.push_back(tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
mTextureUnitState->setAnimatedTextureName(&frameTextures[0], frames, duration);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else if (name == "create_in_ffp")
|
else if (name == "create_in_ffp")
|
||||||
return true; // handled elsewhere
|
return true; // handled elsewhere
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ material openmw_objects_base
|
|||||||
alpha_rejection default
|
alpha_rejection default
|
||||||
transparent_sorting default
|
transparent_sorting default
|
||||||
polygon_mode default
|
polygon_mode default
|
||||||
|
env_map false
|
||||||
|
env_map_color 1 1 1
|
||||||
|
|
||||||
pass
|
pass
|
||||||
{
|
{
|
||||||
@ -33,6 +35,8 @@ material openmw_objects_base
|
|||||||
detailMapUVSet $detailMapUVSet
|
detailMapUVSet $detailMapUVSet
|
||||||
emissiveMap $emissiveMap
|
emissiveMap $emissiveMap
|
||||||
detailMap $detailMap
|
detailMap $detailMap
|
||||||
|
env_map $env_map
|
||||||
|
env_map_color $env_map_color
|
||||||
}
|
}
|
||||||
|
|
||||||
diffuse $diffuse
|
diffuse $diffuse
|
||||||
@ -76,6 +80,14 @@ material openmw_objects_base
|
|||||||
tex_coord_set $detailMapUVSet
|
tex_coord_set $detailMapUVSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
texture_unit envMap
|
||||||
|
{
|
||||||
|
create_in_ffp $env_map
|
||||||
|
env_map spherical
|
||||||
|
anim_texture2 textures\magicitem\caust.dds 32 2
|
||||||
|
colour_op add
|
||||||
|
}
|
||||||
|
|
||||||
texture_unit shadowMap0
|
texture_unit shadowMap0
|
||||||
{
|
{
|
||||||
content_type shadow
|
content_type shadow
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
#define VIEWPROJ_FIX @shGlobalSettingBool(viewproj_fix)
|
#define VIEWPROJ_FIX @shGlobalSettingBool(viewproj_fix)
|
||||||
|
|
||||||
|
#define ENV_MAP @shPropertyBool(env_map)
|
||||||
|
|
||||||
#ifdef SH_VERTEX_SHADER
|
#ifdef SH_VERTEX_SHADER
|
||||||
|
|
||||||
// ------------------------------------- VERTEX ---------------------------------------
|
// ------------------------------------- VERTEX ---------------------------------------
|
||||||
@ -61,7 +63,7 @@
|
|||||||
shOutput(float3, tangentPassthrough)
|
shOutput(float3, tangentPassthrough)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !VERTEX_LIGHTING
|
#if !VERTEX_LIGHTING || ENV_MAP
|
||||||
shOutput(float3, normalPassthrough)
|
shOutput(float3, normalPassthrough)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -79,12 +81,15 @@
|
|||||||
shOutput(float4, colourPassthrough)
|
shOutput(float4, colourPassthrough)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENV_MAP || VERTEX_LIGHTING
|
||||||
|
shUniform(float4x4, worldView) @shAutoConstant(worldView, worldview_matrix)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if VERTEX_LIGHTING
|
#if VERTEX_LIGHTING
|
||||||
shUniform(float4, lightPosition[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightPosition, light_position_view_space_array, @shGlobalSettingString(num_lights))
|
shUniform(float4, lightPosition[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightPosition, light_position_view_space_array, @shGlobalSettingString(num_lights))
|
||||||
shUniform(float4, lightDiffuse[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightDiffuse, light_diffuse_colour_array, @shGlobalSettingString(num_lights))
|
shUniform(float4, lightDiffuse[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightDiffuse, light_diffuse_colour_array, @shGlobalSettingString(num_lights))
|
||||||
shUniform(float4, lightAttenuation[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightAttenuation, light_attenuation_array, @shGlobalSettingString(num_lights))
|
shUniform(float4, lightAttenuation[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightAttenuation, light_attenuation_array, @shGlobalSettingString(num_lights))
|
||||||
shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour)
|
shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour)
|
||||||
shUniform(float4x4, worldView) @shAutoConstant(worldView, worldview_matrix)
|
|
||||||
#if VERTEXCOLOR_MODE != 2
|
#if VERTEXCOLOR_MODE != 2
|
||||||
shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour)
|
shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour)
|
||||||
#endif
|
#endif
|
||||||
@ -125,10 +130,23 @@
|
|||||||
UV.zw = uv1;
|
UV.zw = uv1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENV_MAP || VERTEX_LIGHTING
|
||||||
|
float3 viewNormal = normalize(shMatrixMult(worldView, float4(normal.xyz, 0)).xyz);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENV_MAP
|
||||||
|
float3 viewVec = normalize( shMatrixMult(worldView, shInputPosition).xyz);
|
||||||
|
|
||||||
|
float3 r = reflect( viewVec, viewNormal );
|
||||||
|
float m = 2.0 * sqrt( r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0) );
|
||||||
|
UV.z = r.x/m + 0.5;
|
||||||
|
UV.w = r.y/m + 0.5;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if NORMAL_MAP
|
#if NORMAL_MAP
|
||||||
tangentPassthrough = tangent.xyz;
|
tangentPassthrough = tangent.xyz;
|
||||||
#endif
|
#endif
|
||||||
#if !VERTEX_LIGHTING
|
#if !VERTEX_LIGHTING || ENV_MAP
|
||||||
normalPassthrough = normal.xyz;
|
normalPassthrough = normal.xyz;
|
||||||
#endif
|
#endif
|
||||||
#if VERTEXCOLOR_MODE != 0 && !VERTEX_LIGHTING
|
#if VERTEXCOLOR_MODE != 0 && !VERTEX_LIGHTING
|
||||||
@ -173,7 +191,6 @@
|
|||||||
|
|
||||||
#if VERTEX_LIGHTING
|
#if VERTEX_LIGHTING
|
||||||
float3 viewPos = shMatrixMult(worldView, shInputPosition).xyz;
|
float3 viewPos = shMatrixMult(worldView, shInputPosition).xyz;
|
||||||
float3 viewNormal = normalize(shMatrixMult(worldView, float4(normal.xyz, 0)).xyz);
|
|
||||||
|
|
||||||
float3 lightDir;
|
float3 lightDir;
|
||||||
float d;
|
float d;
|
||||||
@ -242,12 +259,18 @@
|
|||||||
shSampler2D(detailMap)
|
shSampler2D(detailMap)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENV_MAP
|
||||||
|
shSampler2D(envMap)
|
||||||
|
shUniform(float3, env_map_color) @shUniformProperty3f(env_map_color, env_map_color)
|
||||||
|
shUniform(float3, cameraPosObjSpace) @shAutoConstant(cameraPosObjSpace, camera_position_object_space)
|
||||||
|
#endif
|
||||||
|
|
||||||
shInput(float4, UV)
|
shInput(float4, UV)
|
||||||
|
|
||||||
#if NORMAL_MAP
|
#if NORMAL_MAP
|
||||||
shInput(float3, tangentPassthrough)
|
shInput(float3, tangentPassthrough)
|
||||||
#endif
|
#endif
|
||||||
#if !VERTEX_LIGHTING
|
#if !VERTEX_LIGHTING || ENV_MAP
|
||||||
shInput(float3, normalPassthrough)
|
shInput(float3, normalPassthrough)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -327,8 +350,11 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if NORMAL_MAP
|
#if !VERTEX_LIGHTING || ENV_MAP
|
||||||
float3 normal = normalPassthrough;
|
float3 normal = normalPassthrough;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NORMAL_MAP
|
||||||
float3 binormal = cross(tangentPassthrough.xyz, normal.xyz);
|
float3 binormal = cross(tangentPassthrough.xyz, normal.xyz);
|
||||||
float3x3 tbn = float3x3(tangentPassthrough.xyz, binormal, normal.xyz);
|
float3x3 tbn = float3x3(tangentPassthrough.xyz, binormal, normal.xyz);
|
||||||
|
|
||||||
@ -420,6 +446,23 @@
|
|||||||
shOutputColour(0) *= lightResult;
|
shOutputColour(0) *= lightResult;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if EMISSIVE_MAP
|
||||||
|
#if @shPropertyString(emissiveMapUVSet)
|
||||||
|
shOutputColour(0).xyz += shSample(emissiveMap, UV.zw).xyz;
|
||||||
|
#else
|
||||||
|
shOutputColour(0).xyz += shSample(emissiveMap, UV.xy).xyz;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENV_MAP
|
||||||
|
// Everything looks better with fresnel
|
||||||
|
float3 eyeDir = normalize(cameraPosObjSpace.xyz - objSpacePositionPassthrough.xyz);
|
||||||
|
float facing = 1.0 - max(abs(dot(-eyeDir, normal)), 0);
|
||||||
|
float envFactor = shSaturate(0.25 + 0.75 * pow(facing, 1));
|
||||||
|
|
||||||
|
shOutputColour(0).xyz += shSample(envMap, UV.zw).xyz * envFactor * env_map_color;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if FOG
|
#if FOG
|
||||||
float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w);
|
float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w);
|
||||||
|
|
||||||
@ -430,14 +473,6 @@
|
|||||||
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue);
|
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if EMISSIVE_MAP
|
|
||||||
#if @shPropertyString(emissiveMapUVSet)
|
|
||||||
shOutputColour(0).xyz += shSample(emissiveMap, UV.zw).xyz;
|
|
||||||
#else
|
|
||||||
shOutputColour(0).xyz += shSample(emissiveMap, UV.xy).xyz;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// prevent negative colour output (for example with negative lights)
|
// prevent negative colour output (for example with negative lights)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user