mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 18:19:55 +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::LGauntlet:
|
||||
case ESM::Armor::RGauntlet: typeGmst = "iGauntletWeight"; break;
|
||||
/// \todo how to determine if shield light, medium or heavy?
|
||||
// case ESM::Armor::Shield:
|
||||
case ESM::Armor::Shield: typeGmst = "iShieldWeight"; break;
|
||||
case ESM::Armor::LBracer:
|
||||
case ESM::Armor::RBracer: typeGmst = "iGauntletWeight"; break;
|
||||
}
|
||||
|
|
|
@ -299,7 +299,6 @@ namespace MWClass
|
|||
void Npc::registerSelf()
|
||||
{
|
||||
boost::shared_ptr<Class> instance (new Npc);
|
||||
std::cout << "class npc:" << typeid (ESM::NPC).name();
|
||||
registerClass (typeid (ESM::NPC).name(), instance);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,20 +8,15 @@
|
|||
|
||||
using namespace MWRender;
|
||||
|
||||
bool Objects::lightConst = false;
|
||||
float Objects::lightConstValue = 0.0f;
|
||||
|
||||
bool Objects::lightLinear = true;
|
||||
int Objects::lightLinearMethod = 1;
|
||||
// These are the Morrowind.ini defaults
|
||||
float Objects::lightLinearValue = 3;
|
||||
float Objects::lightLinearRadiusMult = 1;
|
||||
|
||||
bool Objects::lightQuadratic = false;
|
||||
int Objects::lightQuadraticMethod = 2;
|
||||
float Objects::lightQuadraticValue = 16;
|
||||
float Objects::lightQuadraticRadiusMult = 1;
|
||||
|
||||
bool Objects::lightOutQuadInLin = false;
|
||||
bool Objects::lightOutQuadInLin = true;
|
||||
bool Objects::lightQuadratic = false;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -144,18 +139,7 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
|||
{
|
||||
Ogre::StaticGeometry* sg = 0;
|
||||
|
||||
/* 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 (small)
|
||||
{
|
||||
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);
|
||||
Ogre::Light *light = mRenderer.getScene()->createLight();
|
||||
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)
|
||||
cval = lightConstValue;
|
||||
LightInfo info;
|
||||
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)
|
||||
radius *= lightLinearRadiusMult;
|
||||
if(lightQuadratic)
|
||||
radius *= lightQuadraticRadiusMult;
|
||||
quadratic = !info.interior;
|
||||
}
|
||||
|
||||
if(lightLinear)
|
||||
lval = lightLinearValue / pow(radius, lightLinearMethod);
|
||||
if(lightQuadratic)
|
||||
qval = lightQuadraticValue / pow(radius, lightQuadraticMethod);
|
||||
if (!quadratic)
|
||||
{
|
||||
float r = radius * lightLinearRadiusMult;
|
||||
float attenuation = lightLinearValue / r;
|
||||
light->setAttenuation(r*10, 0, attenuation, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME:
|
||||
// Do quadratic or linear, depending if we're in an exterior or interior
|
||||
// cell, respectively. Ignore lightLinear and lightQuadratic.
|
||||
float r = radius * lightQuadraticRadiusMult;
|
||||
float attenuation = lightQuadraticValue / pow(r, 2);
|
||||
light->setAttenuation(r*10, 0, 0, attenuation);
|
||||
}
|
||||
|
||||
light->setAttenuation(10*radius, cval, lval, qval);
|
||||
|
||||
insert->attachObject(light);
|
||||
mLights.push_back(info);
|
||||
}
|
||||
|
||||
bool Objects::deleteObject (const MWWorld::Ptr& ptr)
|
||||
|
@ -290,13 +300,6 @@ void Objects::removeCell(MWWorld::Ptr::CellStore* store)
|
|||
mRenderer.getScene()->destroyStaticGeometry (sg);
|
||||
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())
|
||||
mBounds.erase(store);
|
||||
|
@ -314,11 +317,6 @@ void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell)
|
|||
Ogre::StaticGeometry* sg = mStaticGeometrySmall[&cell];
|
||||
sg->build();
|
||||
}
|
||||
/*if(mStaticGeometryAlpha.find(&cell) != mStaticGeometryAlpha.end())
|
||||
{
|
||||
Ogre::StaticGeometry* sg = mStaticGeometryAlpha[&cell];
|
||||
sg->build();
|
||||
}*/
|
||||
}
|
||||
|
||||
Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell)
|
||||
|
@ -328,12 +326,12 @@ Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell)
|
|||
|
||||
void Objects::enableLights()
|
||||
{
|
||||
std::vector<std::string>::iterator it = mLights.begin();
|
||||
std::vector<LightInfo>::iterator it = mLights.begin();
|
||||
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;
|
||||
}
|
||||
else
|
||||
|
@ -343,12 +341,12 @@ void Objects::enableLights()
|
|||
|
||||
void Objects::disableLights()
|
||||
{
|
||||
std::vector<std::string>::iterator it = mLights.begin();
|
||||
std::vector<LightInfo>::iterator it = mLights.begin();
|
||||
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;
|
||||
}
|
||||
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{
|
||||
|
||||
/// 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{
|
||||
OEngine::Render::OgreRenderer &mRenderer;
|
||||
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
|
||||
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry;
|
||||
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::vector<std::string> mLights;
|
||||
std::vector<LightInfo> mLights;
|
||||
Ogre::SceneNode* mMwRoot;
|
||||
bool mIsStatic;
|
||||
static int uniqueID;
|
||||
static bool lightConst;
|
||||
static float lightConstValue;
|
||||
|
||||
static bool lightLinear;
|
||||
static int lightLinearMethod;
|
||||
static float lightLinearValue;
|
||||
static float lightLinearRadiusMult;
|
||||
|
||||
static bool lightQuadratic;
|
||||
static int lightQuadraticMethod;
|
||||
static float lightQuadraticValue;
|
||||
static float lightQuadraticRadiusMult;
|
||||
|
||||
|
@ -40,7 +68,7 @@ class Objects{
|
|||
///< Remove all movable objects from \a node.
|
||||
|
||||
public:
|
||||
Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer){}
|
||||
Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer) {}
|
||||
~Objects(){}
|
||||
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
|
||||
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);
|
||||
|
@ -49,6 +77,9 @@ public:
|
|||
void enableLights();
|
||||
void disableLights();
|
||||
|
||||
void update (const float dt);
|
||||
///< per-frame update
|
||||
|
||||
Ogre::AxisAlignedBox getDimensions(MWWorld::Ptr::CellStore*);
|
||||
///< 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->setMaterialName("QueryTotalPixels");
|
||||
mBBQueryTotal->setRenderQueueGroup(RQG_OcclusionQuery+1);
|
||||
mBBQueryTotal->setVisibilityFlags(RV_OcclusionQuery);
|
||||
mBBNodeReal->attachObject(mBBQueryTotal);
|
||||
|
||||
mBBQueryVisible = mRendering->getScene()->createBillboardSet(1);
|
||||
|
@ -73,6 +74,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
|||
mBBQueryVisible->createBillboard(Vector3::ZERO);
|
||||
mBBQueryVisible->setMaterialName("QueryVisiblePixels");
|
||||
mBBQueryVisible->setRenderQueueGroup(RQG_OcclusionQuery+1);
|
||||
mBBQueryVisible->setVisibilityFlags(RV_OcclusionQuery);
|
||||
mBBNodeReal->attachObject(mBBQueryVisible);
|
||||
|
||||
mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1);
|
||||
|
@ -82,6 +84,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
|||
mBBQuerySingleObject->createBillboard(Vector3::ZERO);
|
||||
mBBQuerySingleObject->setMaterialName("QueryVisiblePixels");
|
||||
mBBQuerySingleObject->setRenderQueueGroup(RQG_OcclusionQuery);
|
||||
mBBQuerySingleObject->setVisibilityFlags(RV_OcclusionQuery);
|
||||
mObjectNode->attachObject(mBBQuerySingleObject);
|
||||
|
||||
mRendering->getScene()->addRenderObjectListener(this);
|
||||
|
|
|
@ -52,6 +52,8 @@ enum VisibilityFlags
|
|||
// Sun glare (not visible in reflection)
|
||||
RV_Glare = 128,
|
||||
|
||||
RV_OcclusionQuery = 256,
|
||||
|
||||
RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water,
|
||||
|
||||
/// \todo markers (normally hidden)
|
||||
|
|
|
@ -52,11 +52,16 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
|||
// Load resources
|
||||
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
|
||||
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);
|
||||
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);
|
||||
|
||||
// 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){
|
||||
|
||||
mActors.update (duration);
|
||||
mObjects.update (duration);
|
||||
|
||||
mOcclusionQuery->update(duration);
|
||||
|
||||
|
@ -219,6 +225,8 @@ void RenderingManager::update (float duration){
|
|||
mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealOrientation() );
|
||||
|
||||
checkUnderwater();
|
||||
|
||||
mWater->update();
|
||||
}
|
||||
void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){
|
||||
if(store->cell->data.flags & store->cell->HasWater){
|
||||
|
@ -500,4 +508,14 @@ Shadows* RenderingManager::getShadows()
|
|||
return mShadows;
|
||||
}
|
||||
|
||||
void RenderingManager::switchToInterior()
|
||||
{
|
||||
mRendering.getScene()->setCameraRelativeRendering(false);
|
||||
}
|
||||
|
||||
void RenderingManager::switchToExterior()
|
||||
{
|
||||
mRendering.getScene()->setCameraRelativeRendering(true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -117,6 +117,9 @@ class RenderingManager: private RenderingInterface {
|
|||
|
||||
Shadows* getShadows();
|
||||
|
||||
void switchToInterior();
|
||||
void switchToExterior();
|
||||
|
||||
void setGlare(bool glare);
|
||||
void skyEnable ();
|
||||
void skyDisable ();
|
||||
|
|
|
@ -256,9 +256,9 @@ void ShaderHelper::createShader(const bool mrt, const bool shadows, const bool s
|
|||
}
|
||||
|
||||
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"
|
||||
" 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";
|
||||
|
||||
if (mrt) outStream <<
|
||||
|
|
|
@ -1149,8 +1149,8 @@ namespace Ogre
|
|||
// simple per-pixel lighting with no normal mapping
|
||||
for (int i=0; i<prof->getNumberOfLightsSupported(); ++i)
|
||||
{
|
||||
outStream << " float3 halfAngle"<<i<<" = normalize(lightDir"<<i<<" + eyeDir);\n"
|
||||
" float4 litRes"<<i<<" = lit(dot(normalize(lightDir"<<i<<"), normal), dot(halfAngle"<<i<<", normal), scaleBiasSpecular.z);\n";
|
||||
outStream <<
|
||||
" float4 litRes"<<i<<" = lit(dot(normalize(lightDir"<<i<<"), normalize(normal)), 0, scaleBiasSpecular.z);\n";
|
||||
|
||||
if (i > 0)
|
||||
outStream <<
|
||||
|
|
|
@ -11,7 +11,8 @@ namespace MWRender
|
|||
Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
||||
mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()),
|
||||
mIsUnderwater(false), mVisibilityFlags(0),
|
||||
mReflectionTarget(0), mActive(1), mToggled(1)
|
||||
mReflectionTarget(0), mActive(1), mToggled(1),
|
||||
mReflectionRenderActive(false)
|
||||
{
|
||||
mSky = sky;
|
||||
|
||||
|
@ -81,6 +82,8 @@ Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
|||
|
||||
mUnderwaterEffect = Settings::Manager::getBool("underwater effect", "Water");
|
||||
|
||||
mSceneManager->addRenderQueueListener(this);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// ---------------------------------- reflection debug overlay ----------------------------------
|
||||
|
@ -161,6 +164,7 @@ void Water::changeCell(const ESM::Cell* cell)
|
|||
void Water::setHeight(const float height)
|
||||
{
|
||||
mTop = height;
|
||||
mWaterPlane = Plane(Vector3::UNIT_Y, height);
|
||||
mWaterNode->setPosition(0, height, 0);
|
||||
}
|
||||
|
||||
|
@ -172,7 +176,12 @@ void Water::toggle()
|
|||
|
||||
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)
|
||||
{
|
||||
CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorName, false);
|
||||
|
@ -220,17 +229,15 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt)
|
|||
mReflectionCamera->setFarClipDistance(mCamera->getFarClipDistance());
|
||||
mReflectionCamera->setAspectRatio(mCamera->getAspectRatio());
|
||||
mReflectionCamera->setFOVy(mCamera->getFOVy());
|
||||
mReflectionRenderActive = true;
|
||||
|
||||
// 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
|
||||
/// \todo For some reason this camera is delayed for 1 frame, which causes ugly sky reflection behaviour..
|
||||
/// to circumvent this we just scale the sky up, so it's not that noticable
|
||||
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));
|
||||
mSky->scaleSky(mCamera->getFarClipDistance() / 5000.f);
|
||||
mReflectionCamera->enableReflection(mWaterPlane);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,8 +247,9 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt)
|
|||
{
|
||||
mSky->resetSkyPosition();
|
||||
mSky->scaleSky(1);
|
||||
mReflectionCamera->disableCustomNearClipPlane();
|
||||
mReflectionCamera->disableReflection();
|
||||
mReflectionCamera->disableCustomNearClipPlane();
|
||||
mReflectionRenderActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,4 +298,27 @@ void Water::updateVisible()
|
|||
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
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace MWRender {
|
|||
class SkyManager;
|
||||
|
||||
/// Water rendering
|
||||
class Water : public Ogre::RenderTargetListener
|
||||
class Water : public Ogre::RenderTargetListener, public Ogre::RenderQueueListener
|
||||
{
|
||||
static const int CELL_SIZE = 8192;
|
||||
Ogre::Camera *mCamera;
|
||||
|
@ -27,11 +27,17 @@ namespace MWRender {
|
|||
bool mToggled;
|
||||
int mTop;
|
||||
|
||||
bool mReflectionRenderActive;
|
||||
|
||||
Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY);
|
||||
|
||||
protected:
|
||||
void preRenderTargetUpdate(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();
|
||||
|
||||
SkyManager* mSky;
|
||||
|
@ -55,6 +61,7 @@ namespace MWRender {
|
|||
void setActive(bool active);
|
||||
|
||||
void toggle();
|
||||
void update();
|
||||
|
||||
void setViewportBackground(const Ogre::ColourValue& bg);
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@ namespace MWWorld
|
|||
float* playerPos = mPlayer.mData.getPosition().pos;
|
||||
playerPos[0] = playerPos[1] = playerPos[2] = 0;
|
||||
|
||||
std::cout << renderer->getHandle();
|
||||
|
||||
mPlayer.mData.setBaseNode(renderer->getNode());
|
||||
/// \todo Do not make a copy of classes defined in esm/p records.
|
||||
mClass = new ESM::Class (*world.getStore().classes.find (player->cls));
|
||||
|
|
|
@ -203,6 +203,8 @@ namespace MWWorld
|
|||
// Sky system
|
||||
mWorld->adjustSky();
|
||||
|
||||
mRendering.switchToExterior();
|
||||
|
||||
mCellChanged = true;
|
||||
}
|
||||
|
||||
|
@ -250,6 +252,7 @@ namespace MWWorld
|
|||
playerCellChange (cell, position);
|
||||
|
||||
// adjust fog
|
||||
mRendering.switchToInterior();
|
||||
mRendering.configureFog(*cell);
|
||||
|
||||
// Sky system
|
||||
|
|
|
@ -522,7 +522,6 @@ void WeatherManager::update(float duration)
|
|||
// re-scale to 100 percent
|
||||
const float total = clear+cloudy+foggy+overcast+rain+thunder+ash+blight;//+snow+blizzard;
|
||||
|
||||
srand(time(NULL));
|
||||
float random = ((rand()%100)/100.f) * total;
|
||||
|
||||
//if (random >= snow+blight+ash+thunder+rain+overcast+foggy+cloudy+clear)
|
||||
|
|
|
@ -17,7 +17,7 @@ struct Light
|
|||
{
|
||||
Dynamic = 0x001,
|
||||
Carry = 0x002, // Can be carried
|
||||
Negative = 0x004, // Negative light?
|
||||
Negative = 0x004, // Negative light - i.e. darkness
|
||||
Flicker = 0x008,
|
||||
Fire = 0x010,
|
||||
OffDefault = 0x020, // Off by default
|
||||
|
|
|
@ -86,6 +86,7 @@ num lights = 8
|
|||
|
||||
[Water]
|
||||
# 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
|
||||
shader = true
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest
|
|||
TEX_TYPE_2D,
|
||||
width, height,
|
||||
0,
|
||||
PF_A8R8G8B8,
|
||||
PF_FLOAT16_RGBA,
|
||||
TU_RENDERTARGET);
|
||||
|
||||
RenderTarget* rtt = destTexture->getBuffer()->getRenderTarget();
|
||||
|
@ -63,7 +63,6 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest
|
|||
vp->setOverlaysEnabled(false);
|
||||
vp->setShadowsEnabled(false);
|
||||
vp->setBackgroundColour(ColourValue(0,0,0,0));
|
||||
vp->setClearEveryFrame(true, FBT_DEPTH);
|
||||
|
||||
rtt->update();
|
||||
|
||||
|
|
Loading…
Reference in a new issue