forked from mirror/openmw-tes3mp
Add glow effect for enchanted items
This commit is contained in:
parent
0b9676aaa3
commit
3452bd2e0b
10 changed files with 180 additions and 33 deletions
|
@ -17,6 +17,8 @@
|
|||
#include "../mwbase/soundmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include <extern/shiny/Main/Factory.hpp>
|
||||
|
||||
#include "../mwmechanics/character.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
|
@ -24,6 +26,7 @@
|
|||
|
||||
#include "renderconst.hpp"
|
||||
|
||||
|
||||
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::uint8 mSolidQueue, mTransQueue;
|
||||
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(),
|
||||
VisQueueSet(visflags, solidqueue, transqueue, dist));
|
||||
std::for_each(objlist.mParticles.begin(), objlist.mParticles.end(),
|
||||
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)
|
||||
: Animation(ptr, ptr.getRefData().getBaseNode())
|
||||
|
@ -1132,9 +1185,10 @@ ObjectAnimation::ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &mod
|
|||
small = false;
|
||||
|
||||
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()) ?
|
||||
(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)
|
||||
|
|
|
@ -191,10 +191,15 @@ protected:
|
|||
|
||||
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();
|
||||
|
||||
// TODO: Should not be here
|
||||
Ogre::Vector3 getEnchantmentColor(MWWorld::Ptr item);
|
||||
|
||||
public:
|
||||
Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node);
|
||||
virtual ~Animation();
|
||||
|
|
|
@ -208,17 +208,19 @@ void NpcAnimation::updateParts()
|
|||
removeIndividualPart(ESM::PRT_Hair);
|
||||
|
||||
int prio = 1;
|
||||
bool enchantedGlow = !store->getClass().getEnchantment(*store).empty();
|
||||
Ogre::Vector3 glowColor = getEnchantmentColor(*store);
|
||||
if(store->getTypeName() == typeid(ESM::Clothing).name())
|
||||
{
|
||||
prio = ((slotlist[i].mBasePriority+1)<<1) + 0;
|
||||
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())
|
||||
{
|
||||
prio = ((slotlist[i].mBasePriority+1)<<1) + 1;
|
||||
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)
|
||||
|
@ -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);
|
||||
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.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])
|
||||
return false;
|
||||
|
@ -484,7 +487,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
|
|||
mPartslots[type] = group;
|
||||
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)
|
||||
{
|
||||
Ogre::SkeletonInstance *skel = mObjectParts[type].mSkelBase->getSkeleton();
|
||||
|
@ -521,7 +524,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
|
|||
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::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)
|
||||
addOrReplaceIndividualPart((ESM::PartReferenceType)part->mPart, group, priority, "meshes\\"+bodypart->mModel);
|
||||
addOrReplaceIndividualPart((ESM::PartReferenceType)part->mPart, group, priority, "meshes\\"+bodypart->mModel, enchantedGlow, glowColor);
|
||||
else
|
||||
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);
|
||||
if(weapon != inv.end()) // special case for weapons
|
||||
{
|
||||
Ogre::Vector3 glowColor = getEnchantmentColor(*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
|
||||
|
|
|
@ -51,14 +51,17 @@ private:
|
|||
|
||||
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 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 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:
|
||||
/**
|
||||
|
|
|
@ -33,6 +33,8 @@ class Objects{
|
|||
|
||||
void insertBegin(const MWWorld::Ptr& ptr);
|
||||
|
||||
|
||||
|
||||
public:
|
||||
Objects(OEngine::Render::OgreRenderer &renderer)
|
||||
: mRenderer(renderer)
|
||||
|
|
|
@ -49,8 +49,9 @@ struct MagicEffect
|
|||
int mSchool; // SpellSchool, see defs.hpp
|
||||
float mBaseCost;
|
||||
int mFlags;
|
||||
// Properties of the fired magic 'ball' I think
|
||||
int mRed, mBlue, mGreen;
|
||||
// Glow color for enchanted items with this effect
|
||||
int mRed, mGreen, mBlue;
|
||||
// Properties of the fired magic 'ball'
|
||||
float mSpeed, mSize, mSizeCap;
|
||||
}; // 36 bytes
|
||||
|
||||
|
|
3
extern/shiny/Main/Factory.hpp
vendored
3
extern/shiny/Main/Factory.hpp
vendored
|
@ -259,8 +259,9 @@ namespace sh
|
|||
Platform* mPlatform;
|
||||
|
||||
MaterialInstance* findInstance (const std::string& name);
|
||||
public:
|
||||
MaterialInstance* searchInstance (const std::string& name);
|
||||
|
||||
private:
|
||||
/// @return was anything removed?
|
||||
bool removeCache (const std::string& pattern);
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#include "OgreTextureUnitState.hpp"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "OgrePass.hpp"
|
||||
#include "OgrePlatform.hpp"
|
||||
#include "OgreMaterialSerializer.hpp"
|
||||
|
@ -28,6 +31,32 @@ namespace sh
|
|||
setTextureName (retrieveValue<StringValue>(value, context).get());
|
||||
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")
|
||||
return true; // handled elsewhere
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ material openmw_objects_base
|
|||
alpha_rejection default
|
||||
transparent_sorting default
|
||||
polygon_mode default
|
||||
env_map false
|
||||
env_map_color 1 1 1
|
||||
|
||||
pass
|
||||
{
|
||||
|
@ -33,6 +35,8 @@ material openmw_objects_base
|
|||
detailMapUVSet $detailMapUVSet
|
||||
emissiveMap $emissiveMap
|
||||
detailMap $detailMap
|
||||
env_map $env_map
|
||||
env_map_color $env_map_color
|
||||
}
|
||||
|
||||
diffuse $diffuse
|
||||
|
@ -75,6 +79,14 @@ material openmw_objects_base
|
|||
direct_texture $detailMap
|
||||
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
|
||||
{
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#define VIEWPROJ_FIX @shGlobalSettingBool(viewproj_fix)
|
||||
|
||||
#define ENV_MAP @shPropertyBool(env_map)
|
||||
|
||||
#ifdef SH_VERTEX_SHADER
|
||||
|
||||
// ------------------------------------- VERTEX ---------------------------------------
|
||||
|
@ -61,7 +63,7 @@
|
|||
shOutput(float3, tangentPassthrough)
|
||||
#endif
|
||||
|
||||
#if !VERTEX_LIGHTING
|
||||
#if !VERTEX_LIGHTING || ENV_MAP
|
||||
shOutput(float3, normalPassthrough)
|
||||
#endif
|
||||
|
||||
|
@ -79,12 +81,15 @@
|
|||
shOutput(float4, colourPassthrough)
|
||||
#endif
|
||||
|
||||
#if ENV_MAP || VERTEX_LIGHTING
|
||||
shUniform(float4x4, worldView) @shAutoConstant(worldView, worldview_matrix)
|
||||
#endif
|
||||
|
||||
#if VERTEX_LIGHTING
|
||||
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, lightAttenuation[@shGlobalSettingString(num_lights)]) @shAutoConstant(lightAttenuation, light_attenuation_array, @shGlobalSettingString(num_lights))
|
||||
shUniform(float4, lightAmbient) @shAutoConstant(lightAmbient, ambient_light_colour)
|
||||
shUniform(float4x4, worldView) @shAutoConstant(worldView, worldview_matrix)
|
||||
#if VERTEXCOLOR_MODE != 2
|
||||
shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour)
|
||||
#endif
|
||||
|
@ -125,10 +130,23 @@
|
|||
UV.zw = uv1;
|
||||
#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
|
||||
tangentPassthrough = tangent.xyz;
|
||||
#endif
|
||||
#if !VERTEX_LIGHTING
|
||||
#if !VERTEX_LIGHTING || ENV_MAP
|
||||
normalPassthrough = normal.xyz;
|
||||
#endif
|
||||
#if VERTEXCOLOR_MODE != 0 && !VERTEX_LIGHTING
|
||||
|
@ -173,7 +191,6 @@
|
|||
|
||||
#if VERTEX_LIGHTING
|
||||
float3 viewPos = shMatrixMult(worldView, shInputPosition).xyz;
|
||||
float3 viewNormal = normalize(shMatrixMult(worldView, float4(normal.xyz, 0)).xyz);
|
||||
|
||||
float3 lightDir;
|
||||
float d;
|
||||
|
@ -242,12 +259,18 @@
|
|||
shSampler2D(detailMap)
|
||||
#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)
|
||||
|
||||
#if NORMAL_MAP
|
||||
shInput(float3, tangentPassthrough)
|
||||
#endif
|
||||
#if !VERTEX_LIGHTING
|
||||
#if !VERTEX_LIGHTING || ENV_MAP
|
||||
shInput(float3, normalPassthrough)
|
||||
#endif
|
||||
|
||||
|
@ -327,8 +350,11 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if NORMAL_MAP
|
||||
#if !VERTEX_LIGHTING || ENV_MAP
|
||||
float3 normal = normalPassthrough;
|
||||
#endif
|
||||
|
||||
#if NORMAL_MAP
|
||||
float3 binormal = cross(tangentPassthrough.xyz, normal.xyz);
|
||||
float3x3 tbn = float3x3(tangentPassthrough.xyz, binormal, normal.xyz);
|
||||
|
||||
|
@ -420,6 +446,23 @@
|
|||
shOutputColour(0) *= lightResult;
|
||||
#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
|
||||
float fogValue = shSaturate((depthPassthrough - fogParams.y) * fogParams.w);
|
||||
|
||||
|
@ -430,14 +473,6 @@
|
|||
shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue);
|
||||
#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
|
||||
|
||||
// prevent negative colour output (for example with negative lights)
|
||||
|
|
Loading…
Reference in a new issue