mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 20:19:57 +00:00
Merge branch 'next' into tooltips
This commit is contained in:
commit
50d79a8815
18 changed files with 269 additions and 91 deletions
|
@ -140,8 +140,7 @@ namespace MWClass
|
||||||
case ESM::Armor::Boots: typeGmst = "iBootsWeight"; break;
|
case ESM::Armor::Boots: typeGmst = "iBootsWeight"; break;
|
||||||
case ESM::Armor::LGauntlet:
|
case ESM::Armor::LGauntlet:
|
||||||
case ESM::Armor::RGauntlet: typeGmst = "iGauntletWeight"; break;
|
case ESM::Armor::RGauntlet: typeGmst = "iGauntletWeight"; break;
|
||||||
/// \todo how to determine if shield light, medium or heavy?
|
case ESM::Armor::Shield: typeGmst = "iShieldWeight"; break;
|
||||||
// case ESM::Armor::Shield:
|
|
||||||
case ESM::Armor::LBracer:
|
case ESM::Armor::LBracer:
|
||||||
case ESM::Armor::RBracer: typeGmst = "iGauntletWeight"; break;
|
case ESM::Armor::RBracer: typeGmst = "iGauntletWeight"; break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,7 +299,6 @@ namespace MWClass
|
||||||
void Npc::registerSelf()
|
void Npc::registerSelf()
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Class> instance (new Npc);
|
boost::shared_ptr<Class> instance (new Npc);
|
||||||
std::cout << "class npc:" << typeid (ESM::NPC).name();
|
|
||||||
registerClass (typeid (ESM::NPC).name(), instance);
|
registerClass (typeid (ESM::NPC).name(), instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,20 +8,15 @@
|
||||||
|
|
||||||
using namespace MWRender;
|
using namespace MWRender;
|
||||||
|
|
||||||
bool Objects::lightConst = false;
|
// These are the Morrowind.ini defaults
|
||||||
float Objects::lightConstValue = 0.0f;
|
|
||||||
|
|
||||||
bool Objects::lightLinear = true;
|
|
||||||
int Objects::lightLinearMethod = 1;
|
|
||||||
float Objects::lightLinearValue = 3;
|
float Objects::lightLinearValue = 3;
|
||||||
float Objects::lightLinearRadiusMult = 1;
|
float Objects::lightLinearRadiusMult = 1;
|
||||||
|
|
||||||
bool Objects::lightQuadratic = false;
|
|
||||||
int Objects::lightQuadraticMethod = 2;
|
|
||||||
float Objects::lightQuadraticValue = 16;
|
float Objects::lightQuadraticValue = 16;
|
||||||
float Objects::lightQuadraticRadiusMult = 1;
|
float Objects::lightQuadraticRadiusMult = 1;
|
||||||
|
|
||||||
bool Objects::lightOutQuadInLin = false;
|
bool Objects::lightOutQuadInLin = true;
|
||||||
|
bool Objects::lightQuadratic = false;
|
||||||
|
|
||||||
int Objects::uniqueID = 0;
|
int Objects::uniqueID = 0;
|
||||||
|
|
||||||
|
@ -132,7 +127,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects"))
|
if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || transparent)
|
||||||
{
|
{
|
||||||
insert->attachObject(ent);
|
insert->attachObject(ent);
|
||||||
|
|
||||||
|
@ -144,18 +139,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
||||||
{
|
{
|
||||||
Ogre::StaticGeometry* sg = 0;
|
Ogre::StaticGeometry* sg = 0;
|
||||||
|
|
||||||
/* if (transparent)
|
if (small)
|
||||||
{
|
|
||||||
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())
|
||||||
{
|
{
|
||||||
|
@ -207,35 +191,61 @@ void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, f
|
||||||
assert(insert);
|
assert(insert);
|
||||||
Ogre::Light *light = mRenderer.getScene()->createLight();
|
Ogre::Light *light = mRenderer.getScene()->createLight();
|
||||||
light->setDiffuseColour (r, g, b);
|
light->setDiffuseColour (r, g, b);
|
||||||
mLights.push_back(light->getName());
|
|
||||||
|
|
||||||
float cval=0.0f, lval=0.0f, qval=0.0f;
|
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
|
||||||
|
ptr.get<ESM::Light>();
|
||||||
|
|
||||||
if(lightConst)
|
LightInfo info;
|
||||||
cval = lightConstValue;
|
info.name = light->getName();
|
||||||
|
info.radius = radius;
|
||||||
|
info.colour = Ogre::ColourValue(r, g, b);
|
||||||
|
|
||||||
if(!lightOutQuadInLin)
|
if (ref->base->data.flags & ESM::Light::Negative)
|
||||||
|
info.colour *= -1;
|
||||||
|
|
||||||
|
info.interior = (ptr.getCell()->cell->data.flags & ESM::Cell::Interior);
|
||||||
|
|
||||||
|
if (ref->base->data.flags & ESM::Light::Flicker)
|
||||||
|
info.type = LT_Flicker;
|
||||||
|
else if (ref->base->data.flags & ESM::Light::FlickerSlow)
|
||||||
|
info.type = LT_FlickerSlow;
|
||||||
|
else if (ref->base->data.flags & ESM::Light::Pulse)
|
||||||
|
info.type = LT_Pulse;
|
||||||
|
else if (ref->base->data.flags & ESM::Light::PulseSlow)
|
||||||
|
info.type = LT_PulseSlow;
|
||||||
|
else
|
||||||
|
info.type = LT_Normal;
|
||||||
|
|
||||||
|
// random starting phase for the animation
|
||||||
|
info.time = Ogre::Math::RangeRandom(0, 2 * M_PI);
|
||||||
|
|
||||||
|
// adjust the lights depending if we're in an interior or exterior cell
|
||||||
|
// quadratic means the light intensity falls off quite fast, resulting in a
|
||||||
|
// dark, atmospheric environment (perfect for exteriors)
|
||||||
|
// for interiors, we want more "warm" lights, so use linear attenuation.
|
||||||
|
bool quadratic = false;
|
||||||
|
if (!lightOutQuadInLin)
|
||||||
|
quadratic = lightQuadratic;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if(lightLinear)
|
quadratic = !info.interior;
|
||||||
radius *= lightLinearRadiusMult;
|
}
|
||||||
if(lightQuadratic)
|
|
||||||
radius *= lightQuadraticRadiusMult;
|
|
||||||
|
|
||||||
if(lightLinear)
|
if (!quadratic)
|
||||||
lval = lightLinearValue / pow(radius, lightLinearMethod);
|
{
|
||||||
if(lightQuadratic)
|
float r = radius * lightLinearRadiusMult;
|
||||||
qval = lightQuadraticValue / pow(radius, lightQuadraticMethod);
|
float attenuation = lightLinearValue / r;
|
||||||
|
light->setAttenuation(r*10, 0, attenuation, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// FIXME:
|
float r = radius * lightQuadraticRadiusMult;
|
||||||
// Do quadratic or linear, depending if we're in an exterior or interior
|
float attenuation = lightQuadraticValue / pow(r, 2);
|
||||||
// cell, respectively. Ignore lightLinear and lightQuadratic.
|
light->setAttenuation(r*10, 0, 0, attenuation);
|
||||||
}
|
}
|
||||||
|
|
||||||
light->setAttenuation(10*radius, cval, lval, qval);
|
|
||||||
|
|
||||||
insert->attachObject(light);
|
insert->attachObject(light);
|
||||||
|
mLights.push_back(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Objects::deleteObject (const MWWorld::Ptr& ptr)
|
bool Objects::deleteObject (const MWWorld::Ptr& ptr)
|
||||||
|
@ -290,13 +300,6 @@ 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);
|
||||||
|
@ -314,11 +317,6 @@ 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)
|
||||||
|
@ -328,12 +326,12 @@ Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell)
|
||||||
|
|
||||||
void Objects::enableLights()
|
void Objects::enableLights()
|
||||||
{
|
{
|
||||||
std::vector<std::string>::iterator it = mLights.begin();
|
std::vector<LightInfo>::iterator it = mLights.begin();
|
||||||
while (it != mLights.end())
|
while (it != mLights.end())
|
||||||
{
|
{
|
||||||
if (mMwRoot->getCreator()->hasLight(*it))
|
if (mMwRoot->getCreator()->hasLight(it->name))
|
||||||
{
|
{
|
||||||
mMwRoot->getCreator()->getLight(*it)->setVisible(true);
|
mMwRoot->getCreator()->getLight(it->name)->setVisible(true);
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -343,12 +341,12 @@ void Objects::enableLights()
|
||||||
|
|
||||||
void Objects::disableLights()
|
void Objects::disableLights()
|
||||||
{
|
{
|
||||||
std::vector<std::string>::iterator it = mLights.begin();
|
std::vector<LightInfo>::iterator it = mLights.begin();
|
||||||
while (it != mLights.end())
|
while (it != mLights.end())
|
||||||
{
|
{
|
||||||
if (mMwRoot->getCreator()->hasLight(*it))
|
if (mMwRoot->getCreator()->hasLight(it->name))
|
||||||
{
|
{
|
||||||
mMwRoot->getCreator()->getLight(*it)->setVisible(false);
|
mMwRoot->getCreator()->getLight(it->name)->setVisible(false);
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -356,3 +354,90 @@ void Objects::disableLights()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Objects::update(const float dt)
|
||||||
|
{
|
||||||
|
std::vector<LightInfo>::iterator it = mLights.begin();
|
||||||
|
while (it != mLights.end())
|
||||||
|
{
|
||||||
|
if (mMwRoot->getCreator()->hasLight(it->name))
|
||||||
|
{
|
||||||
|
Ogre::Light* light = mMwRoot->getCreator()->getLight(it->name);
|
||||||
|
|
||||||
|
// Light animation (pulse & flicker)
|
||||||
|
it->time += dt;
|
||||||
|
const float phase = std::fmod(static_cast<double> (it->time), (32 * 2 * M_PI)) * 20;
|
||||||
|
float pulseConstant;
|
||||||
|
|
||||||
|
// These formulas are just guesswork, but they work pretty well
|
||||||
|
if (it->type == LT_Normal)
|
||||||
|
{
|
||||||
|
// Less than 1/255 light modifier for a constant light:
|
||||||
|
pulseConstant = (const float)(1.0 + sin(phase) / 255.0 );
|
||||||
|
}
|
||||||
|
else if (it->type == LT_Flicker)
|
||||||
|
{
|
||||||
|
// Let's do a 50% -> 100% sine wave pulse over 1 second:
|
||||||
|
// This is 75% +/- 25%
|
||||||
|
pulseConstant = (const float)(0.75 + sin(phase) * 0.25);
|
||||||
|
|
||||||
|
// Then add a 25% flicker variation:
|
||||||
|
it->resetTime -= dt;
|
||||||
|
if (it->resetTime < 0)
|
||||||
|
{
|
||||||
|
it->flickerVariation = (rand() % 1000) / 1000 * 0.25;
|
||||||
|
it->resetTime = 0.5;
|
||||||
|
}
|
||||||
|
if (it->resetTime > 0.25)
|
||||||
|
{
|
||||||
|
pulseConstant = (pulseConstant+it->flickerVariation) * (1-it->resetTime * 2.0f) + pulseConstant * it->resetTime * 2.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pulseConstant = (pulseConstant+it->flickerVariation) * (it->resetTime * 2.0f) + pulseConstant * (1-it->resetTime * 2.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (it->type == LT_FlickerSlow)
|
||||||
|
{
|
||||||
|
// Let's do a 50% -> 100% sine wave pulse over 1 second:
|
||||||
|
// This is 75% +/- 25%
|
||||||
|
pulseConstant = (const float)(0.75 + sin(phase / 4.0) * 0.25);
|
||||||
|
|
||||||
|
// Then add a 25% flicker variation:
|
||||||
|
it->resetTime -= dt;
|
||||||
|
if (it->resetTime < 0)
|
||||||
|
{
|
||||||
|
it->flickerVariation = (rand() % 1000) / 1000 * 0.25;
|
||||||
|
it->resetTime = 0.5;
|
||||||
|
}
|
||||||
|
if (it->resetTime > 0.5)
|
||||||
|
{
|
||||||
|
pulseConstant = (pulseConstant+it->flickerVariation) * (1-it->resetTime) + pulseConstant * it->resetTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pulseConstant = (pulseConstant+it->flickerVariation) * (it->resetTime) + pulseConstant * (1-it->resetTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (it->type == LT_Pulse)
|
||||||
|
{
|
||||||
|
// Let's do a 75% -> 125% sine wave pulse over 1 second:
|
||||||
|
// This is 100% +/- 25%
|
||||||
|
pulseConstant = (const float)(1.0 + sin(phase) * 0.25);
|
||||||
|
}
|
||||||
|
else if (it->type == LT_PulseSlow)
|
||||||
|
{
|
||||||
|
// Let's do a 75% -> 125% sine wave pulse over 1 second:
|
||||||
|
// This is 100% +/- 25%
|
||||||
|
pulseConstant = (const float)(1.0 + sin(phase / 4.0) * 0.25);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
assert(0 && "Invalid light type");
|
||||||
|
|
||||||
|
light->setDiffuseColour( it->colour * pulseConstant );
|
||||||
|
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
it = mLights.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,27 +10,55 @@
|
||||||
|
|
||||||
namespace MWRender{
|
namespace MWRender{
|
||||||
|
|
||||||
|
/// information about light needed for rendering
|
||||||
|
enum LightType
|
||||||
|
{
|
||||||
|
// These are all mutually exclusive
|
||||||
|
LT_Normal=0,
|
||||||
|
LT_Flicker=1,
|
||||||
|
LT_FlickerSlow=2,
|
||||||
|
LT_Pulse=3,
|
||||||
|
LT_PulseSlow=4
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LightInfo
|
||||||
|
{
|
||||||
|
// Constants
|
||||||
|
std::string name; // ogre handle
|
||||||
|
Ogre::ColourValue colour;
|
||||||
|
float radius;
|
||||||
|
bool interior; // Does this light belong to an interior or exterior cell
|
||||||
|
LightType type;
|
||||||
|
|
||||||
|
// Runtime variables
|
||||||
|
float flickerVariation; // 25% flicker variation, reset once every 0.5 seconds
|
||||||
|
float flickerSlowVariation; // 25% flicker variation, reset once every 1.0 seconds
|
||||||
|
float resetTime;
|
||||||
|
long double time;
|
||||||
|
|
||||||
|
|
||||||
|
LightInfo() :
|
||||||
|
flickerVariation(0), resetTime(0.5),
|
||||||
|
flickerSlowVariation(0), time(0), interior(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class Objects{
|
class Objects{
|
||||||
OEngine::Render::OgreRenderer &mRenderer;
|
OEngine::Render::OgreRenderer &mRenderer;
|
||||||
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<LightInfo> mLights;
|
||||||
Ogre::SceneNode* mMwRoot;
|
Ogre::SceneNode* mMwRoot;
|
||||||
bool mIsStatic;
|
bool mIsStatic;
|
||||||
static int uniqueID;
|
static int uniqueID;
|
||||||
static bool lightConst;
|
|
||||||
static float lightConstValue;
|
|
||||||
|
|
||||||
static bool lightLinear;
|
|
||||||
static int lightLinearMethod;
|
|
||||||
static float lightLinearValue;
|
static float lightLinearValue;
|
||||||
static float lightLinearRadiusMult;
|
static float lightLinearRadiusMult;
|
||||||
|
|
||||||
static bool lightQuadratic;
|
static bool lightQuadratic;
|
||||||
static int lightQuadraticMethod;
|
|
||||||
static float lightQuadraticValue;
|
static float lightQuadraticValue;
|
||||||
static float lightQuadraticRadiusMult;
|
static float lightQuadraticRadiusMult;
|
||||||
|
|
||||||
|
@ -40,7 +68,7 @@ class Objects{
|
||||||
///< Remove all movable objects from \a node.
|
///< Remove all movable objects from \a node.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer){}
|
Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer) {}
|
||||||
~Objects(){}
|
~Objects(){}
|
||||||
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
|
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
|
||||||
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);
|
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);
|
||||||
|
@ -49,6 +77,9 @@ public:
|
||||||
void enableLights();
|
void enableLights();
|
||||||
void disableLights();
|
void disableLights();
|
||||||
|
|
||||||
|
void update (const float dt);
|
||||||
|
///< per-frame update
|
||||||
|
|
||||||
Ogre::AxisAlignedBox getDimensions(MWWorld::Ptr::CellStore*);
|
Ogre::AxisAlignedBox getDimensions(MWWorld::Ptr::CellStore*);
|
||||||
///< get a bounding box that encloses all objects in the specified cell
|
///< get a bounding box that encloses all objects in the specified cell
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
||||||
mBBQueryTotal->createBillboard(Vector3::ZERO);
|
mBBQueryTotal->createBillboard(Vector3::ZERO);
|
||||||
mBBQueryTotal->setMaterialName("QueryTotalPixels");
|
mBBQueryTotal->setMaterialName("QueryTotalPixels");
|
||||||
mBBQueryTotal->setRenderQueueGroup(RQG_OcclusionQuery+1);
|
mBBQueryTotal->setRenderQueueGroup(RQG_OcclusionQuery+1);
|
||||||
|
mBBQueryTotal->setVisibilityFlags(RV_OcclusionQuery);
|
||||||
mBBNodeReal->attachObject(mBBQueryTotal);
|
mBBNodeReal->attachObject(mBBQueryTotal);
|
||||||
|
|
||||||
mBBQueryVisible = mRendering->getScene()->createBillboardSet(1);
|
mBBQueryVisible = mRendering->getScene()->createBillboardSet(1);
|
||||||
|
@ -73,6 +74,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
||||||
mBBQueryVisible->createBillboard(Vector3::ZERO);
|
mBBQueryVisible->createBillboard(Vector3::ZERO);
|
||||||
mBBQueryVisible->setMaterialName("QueryVisiblePixels");
|
mBBQueryVisible->setMaterialName("QueryVisiblePixels");
|
||||||
mBBQueryVisible->setRenderQueueGroup(RQG_OcclusionQuery+1);
|
mBBQueryVisible->setRenderQueueGroup(RQG_OcclusionQuery+1);
|
||||||
|
mBBQueryVisible->setVisibilityFlags(RV_OcclusionQuery);
|
||||||
mBBNodeReal->attachObject(mBBQueryVisible);
|
mBBNodeReal->attachObject(mBBQueryVisible);
|
||||||
|
|
||||||
mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1);
|
mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1);
|
||||||
|
@ -82,6 +84,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
||||||
mBBQuerySingleObject->createBillboard(Vector3::ZERO);
|
mBBQuerySingleObject->createBillboard(Vector3::ZERO);
|
||||||
mBBQuerySingleObject->setMaterialName("QueryVisiblePixels");
|
mBBQuerySingleObject->setMaterialName("QueryVisiblePixels");
|
||||||
mBBQuerySingleObject->setRenderQueueGroup(RQG_OcclusionQuery);
|
mBBQuerySingleObject->setRenderQueueGroup(RQG_OcclusionQuery);
|
||||||
|
mBBQuerySingleObject->setVisibilityFlags(RV_OcclusionQuery);
|
||||||
mObjectNode->attachObject(mBBQuerySingleObject);
|
mObjectNode->attachObject(mBBQuerySingleObject);
|
||||||
|
|
||||||
mRendering->getScene()->addRenderObjectListener(this);
|
mRendering->getScene()->addRenderObjectListener(this);
|
||||||
|
|
|
@ -52,6 +52,8 @@ enum VisibilityFlags
|
||||||
// Sun glare (not visible in reflection)
|
// Sun glare (not visible in reflection)
|
||||||
RV_Glare = 128,
|
RV_Glare = 128,
|
||||||
|
|
||||||
|
RV_OcclusionQuery = 256,
|
||||||
|
|
||||||
RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water,
|
RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water,
|
||||||
|
|
||||||
/// \todo markers (normally hidden)
|
/// \todo markers (normally hidden)
|
||||||
|
|
|
@ -52,11 +52,16 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
||||||
// Load resources
|
// Load resources
|
||||||
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
|
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
|
||||||
|
|
||||||
|
// Due to the huge world size of MW, we'll want camera-relative rendering.
|
||||||
|
// This prevents precision artifacts when moving very far from the origin.
|
||||||
|
mRendering.getScene()->setCameraRelativeRendering(true);
|
||||||
|
|
||||||
// disable unsupported effects
|
// disable unsupported effects
|
||||||
const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
|
const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
|
||||||
if (caps->getNumMultiRenderTargets() < 2)
|
if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects"))
|
||||||
Settings::Manager::setBool("shader", "Water", false);
|
Settings::Manager::setBool("shader", "Water", false);
|
||||||
if (!caps->isShaderProfileSupported("fp40") && !caps->isShaderProfileSupported("ps_4_0"))
|
if ( !(caps->isShaderProfileSupported("fp40") || caps->isShaderProfileSupported("ps_4_0"))
|
||||||
|
|| !Settings::Manager::getBool("shaders", "Objects"))
|
||||||
Settings::Manager::setBool("enabled", "Shadows", false);
|
Settings::Manager::setBool("enabled", "Shadows", false);
|
||||||
|
|
||||||
// note that the order is important here
|
// note that the order is important here
|
||||||
|
@ -207,6 +212,7 @@ void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Ve
|
||||||
void RenderingManager::update (float duration){
|
void RenderingManager::update (float duration){
|
||||||
|
|
||||||
mActors.update (duration);
|
mActors.update (duration);
|
||||||
|
mObjects.update (duration);
|
||||||
|
|
||||||
mOcclusionQuery->update(duration);
|
mOcclusionQuery->update(duration);
|
||||||
|
|
||||||
|
@ -219,6 +225,8 @@ void RenderingManager::update (float duration){
|
||||||
mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealOrientation() );
|
mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealOrientation() );
|
||||||
|
|
||||||
checkUnderwater();
|
checkUnderwater();
|
||||||
|
|
||||||
|
mWater->update();
|
||||||
}
|
}
|
||||||
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){
|
||||||
|
@ -500,4 +508,14 @@ Shadows* RenderingManager::getShadows()
|
||||||
return mShadows;
|
return mShadows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingManager::switchToInterior()
|
||||||
|
{
|
||||||
|
mRendering.getScene()->setCameraRelativeRendering(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingManager::switchToExterior()
|
||||||
|
{
|
||||||
|
mRendering.getScene()->setCameraRelativeRendering(true);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -117,6 +117,9 @@ class RenderingManager: private RenderingInterface {
|
||||||
|
|
||||||
Shadows* getShadows();
|
Shadows* getShadows();
|
||||||
|
|
||||||
|
void switchToInterior();
|
||||||
|
void switchToExterior();
|
||||||
|
|
||||||
void setGlare(bool glare);
|
void setGlare(bool glare);
|
||||||
void skyEnable ();
|
void skyEnable ();
|
||||||
void skyDisable ();
|
void skyDisable ();
|
||||||
|
|
|
@ -256,9 +256,9 @@ void ShaderHelper::createShader(const bool mrt, const bool shadows, const bool s
|
||||||
}
|
}
|
||||||
|
|
||||||
outStream <<
|
outStream <<
|
||||||
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
|
" float3 lightingFinal = lightColour.xyz * diffuse.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
|
||||||
" float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); \n"
|
" float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); \n"
|
||||||
" oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour.xyz, fogValue); \n"
|
" oColor.xyz = lerp(lightingFinal * tex.xyz * vertexColour.xyz, fogColour.xyz, fogValue); \n"
|
||||||
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n";
|
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n";
|
||||||
|
|
||||||
if (mrt) outStream <<
|
if (mrt) outStream <<
|
||||||
|
|
|
@ -1149,8 +1149,8 @@ namespace Ogre
|
||||||
// simple per-pixel lighting with no normal mapping
|
// simple per-pixel lighting with no normal mapping
|
||||||
for (int i=0; i<prof->getNumberOfLightsSupported(); ++i)
|
for (int i=0; i<prof->getNumberOfLightsSupported(); ++i)
|
||||||
{
|
{
|
||||||
outStream << " float3 halfAngle"<<i<<" = normalize(lightDir"<<i<<" + eyeDir);\n"
|
outStream <<
|
||||||
" float4 litRes"<<i<<" = lit(dot(normalize(lightDir"<<i<<"), normal), dot(halfAngle"<<i<<", normal), scaleBiasSpecular.z);\n";
|
" float4 litRes"<<i<<" = lit(dot(normalize(lightDir"<<i<<"), normalize(normal)), 0, scaleBiasSpecular.z);\n";
|
||||||
|
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
outStream <<
|
outStream <<
|
||||||
|
|
|
@ -11,7 +11,8 @@ namespace MWRender
|
||||||
Water::Water (Ogre::Camera *camera, SkyManager* sky, 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), mVisibilityFlags(0),
|
mIsUnderwater(false), mVisibilityFlags(0),
|
||||||
mReflectionTarget(0), mActive(1), mToggled(1)
|
mReflectionTarget(0), mActive(1), mToggled(1),
|
||||||
|
mReflectionRenderActive(false)
|
||||||
{
|
{
|
||||||
mSky = sky;
|
mSky = sky;
|
||||||
|
|
||||||
|
@ -81,6 +82,8 @@ Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
||||||
|
|
||||||
mUnderwaterEffect = Settings::Manager::getBool("underwater effect", "Water");
|
mUnderwaterEffect = Settings::Manager::getBool("underwater effect", "Water");
|
||||||
|
|
||||||
|
mSceneManager->addRenderQueueListener(this);
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------------
|
||||||
// ---------------------------------- reflection debug overlay ----------------------------------
|
// ---------------------------------- reflection debug overlay ----------------------------------
|
||||||
|
@ -161,6 +164,7 @@ void Water::changeCell(const ESM::Cell* cell)
|
||||||
void Water::setHeight(const float height)
|
void Water::setHeight(const float height)
|
||||||
{
|
{
|
||||||
mTop = height;
|
mTop = height;
|
||||||
|
mWaterPlane = Plane(Vector3::UNIT_Y, height);
|
||||||
mWaterNode->setPosition(0, height, 0);
|
mWaterNode->setPosition(0, height, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +176,12 @@ void Water::toggle()
|
||||||
|
|
||||||
void Water::checkUnderwater(float y)
|
void Water::checkUnderwater(float y)
|
||||||
{
|
{
|
||||||
if (!mActive) return;
|
if (!mActive)
|
||||||
|
{
|
||||||
|
CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((mIsUnderwater && y > mTop) || !mWater->isVisible() || mCamera->getPolygonMode() != Ogre::PM_SOLID)
|
if ((mIsUnderwater && y > mTop) || !mWater->isVisible() || mCamera->getPolygonMode() != Ogre::PM_SOLID)
|
||||||
{
|
{
|
||||||
CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false);
|
CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false);
|
||||||
|
@ -220,17 +229,15 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt)
|
||||||
mReflectionCamera->setFarClipDistance(mCamera->getFarClipDistance());
|
mReflectionCamera->setFarClipDistance(mCamera->getFarClipDistance());
|
||||||
mReflectionCamera->setAspectRatio(mCamera->getAspectRatio());
|
mReflectionCamera->setAspectRatio(mCamera->getAspectRatio());
|
||||||
mReflectionCamera->setFOVy(mCamera->getFOVy());
|
mReflectionCamera->setFOVy(mCamera->getFOVy());
|
||||||
|
mReflectionRenderActive = true;
|
||||||
|
|
||||||
// Some messy code to get the skybox to show up at all
|
/// \todo For some reason this camera is delayed for 1 frame, which causes ugly sky reflection behaviour..
|
||||||
// The problem here is that it gets clipped by the water plane
|
/// to circumvent this we just scale the sky up, so it's not that noticable
|
||||||
// Therefore scale it up a bit
|
|
||||||
Vector3 pos = mCamera->getRealPosition();
|
Vector3 pos = mCamera->getRealPosition();
|
||||||
pos.y = mTop*2 - pos.y;
|
pos.y = mTop*2 - pos.y;
|
||||||
mSky->setSkyPosition(pos);
|
mSky->setSkyPosition(pos);
|
||||||
mSky->scaleSky(mCamera->getFarClipDistance() / 1000.f);
|
mSky->scaleSky(mCamera->getFarClipDistance() / 5000.f);
|
||||||
|
mReflectionCamera->enableReflection(mWaterPlane);
|
||||||
mReflectionCamera->enableCustomNearClipPlane(Plane(Vector3::UNIT_Y, mTop));
|
|
||||||
mReflectionCamera->enableReflection(Plane(Vector3::UNIT_Y, mTop));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,8 +247,9 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt)
|
||||||
{
|
{
|
||||||
mSky->resetSkyPosition();
|
mSky->resetSkyPosition();
|
||||||
mSky->scaleSky(1);
|
mSky->scaleSky(1);
|
||||||
mReflectionCamera->disableCustomNearClipPlane();
|
|
||||||
mReflectionCamera->disableReflection();
|
mReflectionCamera->disableReflection();
|
||||||
|
mReflectionCamera->disableCustomNearClipPlane();
|
||||||
|
mReflectionRenderActive = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,4 +298,27 @@ void Water::updateVisible()
|
||||||
mReflectionTarget->setActive(mToggled && mActive && !mIsUnderwater);
|
mReflectionTarget->setActive(mToggled && mActive && !mIsUnderwater);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Water::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation)
|
||||||
|
{
|
||||||
|
// We don't want the sky to get clipped by custom near clip plane (the water plane)
|
||||||
|
if (queueGroupId < 20 && mReflectionRenderActive)
|
||||||
|
{
|
||||||
|
mReflectionCamera->disableCustomNearClipPlane();
|
||||||
|
Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Water::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation)
|
||||||
|
{
|
||||||
|
if (queueGroupId < 20 && mReflectionRenderActive)
|
||||||
|
{
|
||||||
|
mReflectionCamera->enableCustomNearClipPlane(mWaterPlane);
|
||||||
|
Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mReflectionCamera->getProjectionMatrixRS());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Water::update()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace MWRender {
|
||||||
class SkyManager;
|
class SkyManager;
|
||||||
|
|
||||||
/// Water rendering
|
/// Water rendering
|
||||||
class Water : public Ogre::RenderTargetListener
|
class Water : public Ogre::RenderTargetListener, public Ogre::RenderQueueListener
|
||||||
{
|
{
|
||||||
static const int CELL_SIZE = 8192;
|
static const int CELL_SIZE = 8192;
|
||||||
Ogre::Camera *mCamera;
|
Ogre::Camera *mCamera;
|
||||||
|
@ -27,11 +27,17 @@ namespace MWRender {
|
||||||
bool mToggled;
|
bool mToggled;
|
||||||
int mTop;
|
int mTop;
|
||||||
|
|
||||||
|
bool mReflectionRenderActive;
|
||||||
|
|
||||||
Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY);
|
Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
|
void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
|
||||||
void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
|
void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
|
||||||
|
|
||||||
|
void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation);
|
||||||
|
void renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation);
|
||||||
|
|
||||||
void updateVisible();
|
void updateVisible();
|
||||||
|
|
||||||
SkyManager* mSky;
|
SkyManager* mSky;
|
||||||
|
@ -55,6 +61,7 @@ namespace MWRender {
|
||||||
void setActive(bool active);
|
void setActive(bool active);
|
||||||
|
|
||||||
void toggle();
|
void toggle();
|
||||||
|
void update();
|
||||||
|
|
||||||
void setViewportBackground(const Ogre::ColourValue& bg);
|
void setViewportBackground(const Ogre::ColourValue& bg);
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,6 @@ namespace MWWorld
|
||||||
float* playerPos = mPlayer.mData.getPosition().pos;
|
float* playerPos = mPlayer.mData.getPosition().pos;
|
||||||
playerPos[0] = playerPos[1] = playerPos[2] = 0;
|
playerPos[0] = playerPos[1] = playerPos[2] = 0;
|
||||||
|
|
||||||
std::cout << renderer->getHandle();
|
|
||||||
|
|
||||||
mPlayer.mData.setBaseNode(renderer->getNode());
|
mPlayer.mData.setBaseNode(renderer->getNode());
|
||||||
/// \todo Do not make a copy of classes defined in esm/p records.
|
/// \todo Do not make a copy of classes defined in esm/p records.
|
||||||
mClass = new ESM::Class (*world.getStore().classes.find (player->cls));
|
mClass = new ESM::Class (*world.getStore().classes.find (player->cls));
|
||||||
|
|
|
@ -203,6 +203,8 @@ namespace MWWorld
|
||||||
// Sky system
|
// Sky system
|
||||||
mWorld->adjustSky();
|
mWorld->adjustSky();
|
||||||
|
|
||||||
|
mRendering.switchToExterior();
|
||||||
|
|
||||||
mCellChanged = true;
|
mCellChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,6 +252,7 @@ namespace MWWorld
|
||||||
playerCellChange (cell, position);
|
playerCellChange (cell, position);
|
||||||
|
|
||||||
// adjust fog
|
// adjust fog
|
||||||
|
mRendering.switchToInterior();
|
||||||
mRendering.configureFog(*cell);
|
mRendering.configureFog(*cell);
|
||||||
|
|
||||||
// Sky system
|
// Sky system
|
||||||
|
|
|
@ -522,7 +522,6 @@ void WeatherManager::update(float duration)
|
||||||
// re-scale to 100 percent
|
// re-scale to 100 percent
|
||||||
const float total = clear+cloudy+foggy+overcast+rain+thunder+ash+blight;//+snow+blizzard;
|
const float total = clear+cloudy+foggy+overcast+rain+thunder+ash+blight;//+snow+blizzard;
|
||||||
|
|
||||||
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)
|
||||||
|
|
|
@ -17,7 +17,7 @@ struct Light
|
||||||
{
|
{
|
||||||
Dynamic = 0x001,
|
Dynamic = 0x001,
|
||||||
Carry = 0x002, // Can be carried
|
Carry = 0x002, // Can be carried
|
||||||
Negative = 0x004, // Negative light?
|
Negative = 0x004, // Negative light - i.e. darkness
|
||||||
Flicker = 0x008,
|
Flicker = 0x008,
|
||||||
Fire = 0x010,
|
Fire = 0x010,
|
||||||
OffDefault = 0x020, // Off by default
|
OffDefault = 0x020, // Off by default
|
||||||
|
|
|
@ -86,6 +86,7 @@ num lights = 8
|
||||||
|
|
||||||
[Water]
|
[Water]
|
||||||
# Enable this to get fancy-looking water with reflections and refractions
|
# Enable this to get fancy-looking water with reflections and refractions
|
||||||
|
# Only available if object shaders are on
|
||||||
# All the settings below have no effect if this is false
|
# All the settings below have no effect if this is false
|
||||||
shader = true
|
shader = true
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest
|
||||||
TEX_TYPE_2D,
|
TEX_TYPE_2D,
|
||||||
width, height,
|
width, height,
|
||||||
0,
|
0,
|
||||||
PF_A8R8G8B8,
|
PF_FLOAT16_RGBA,
|
||||||
TU_RENDERTARGET);
|
TU_RENDERTARGET);
|
||||||
|
|
||||||
RenderTarget* rtt = destTexture->getBuffer()->getRenderTarget();
|
RenderTarget* rtt = destTexture->getBuffer()->getRenderTarget();
|
||||||
|
@ -63,7 +63,6 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest
|
||||||
vp->setOverlaysEnabled(false);
|
vp->setOverlaysEnabled(false);
|
||||||
vp->setShadowsEnabled(false);
|
vp->setShadowsEnabled(false);
|
||||||
vp->setBackgroundColour(ColourValue(0,0,0,0));
|
vp->setBackgroundColour(ColourValue(0,0,0,0));
|
||||||
vp->setClearEveryFrame(true, FBT_DEPTH);
|
|
||||||
|
|
||||||
rtt->update();
|
rtt->update();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue