From c6da3872b443572b5c686eae15d14f4ac35ab8c1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 19 Apr 2012 20:59:57 +0200 Subject: [PATCH] light improvements --- apps/openmw/mwrender/objects.cpp | 132 ++++++++++++---------- apps/openmw/mwrender/objects.hpp | 26 +++-- apps/openmw/mwrender/renderingmanager.cpp | 11 ++ apps/openmw/mwrender/renderingmanager.hpp | 3 + apps/openmw/mwrender/terrainmaterial.cpp | 4 +- apps/openmw/mwworld/scene.cpp | 5 +- 6 files changed, 113 insertions(+), 68 deletions(-) diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index eb7e440cb..a79d72989 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -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,34 +191,35 @@ 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; + LightInfo info; + info.name = light->getName(); + info.radius = radius; + info.colour = Ogre::ColourValue(r, g, b); + mLights.push_back(info); - if(lightConst) - cval = lightConstValue; - if(!lightOutQuadInLin) + bool quadratic = false; + if (!lightOutQuadInLin) + quadratic = lightQuadratic; + else { - if(lightLinear) - radius *= lightLinearRadiusMult; - if(lightQuadratic) - radius *= lightQuadraticRadiusMult; + quadratic = !mInterior; + } - 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); } @@ -290,13 +275,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 +292,6 @@ void Objects::buildStaticGeometry(ESMS::CellStore& 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 +301,12 @@ Ogre::AxisAlignedBox Objects::getDimensions(MWWorld::Ptr::CellStore* cell) void Objects::enableLights() { - std::vector::iterator it = mLights.begin(); + std::vector::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 +316,12 @@ void Objects::enableLights() void Objects::disableLights() { - std::vector::iterator it = mLights.begin(); + std::vector::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 +329,48 @@ void Objects::disableLights() } } +void Objects::setInterior(const bool interior) +{ + mInterior = interior; +} + +void Objects::update(const float dt) +{ + // 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. + std::vector::iterator it = mLights.begin(); + while (it != mLights.end()) + { + if (mMwRoot->getCreator()->hasLight(it->name)) + { + Ogre::Light* light = mMwRoot->getCreator()->getLight(it->name); + + bool quadratic = false; + if (!lightOutQuadInLin) + quadratic = lightQuadratic; + else + { + quadratic = !mInterior; + } + + if (!quadratic) + { + float radius = it->radius * lightLinearRadiusMult; + float attenuation = lightLinearValue / it->radius; + light->setAttenuation(radius*10, 0, attenuation, 0); + } + else + { + float radius = it->radius * lightQuadraticRadiusMult; + float attenuation = lightQuadraticValue / pow(it->radius, 2); + light->setAttenuation(radius*10, 0, 0, attenuation); + } + + ++it; + } + else + it = mLights.erase(it); + } +} diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp index 0c19f9f33..63e639ef7 100644 --- a/apps/openmw/mwrender/objects.hpp +++ b/apps/openmw/mwrender/objects.hpp @@ -10,37 +10,41 @@ namespace MWRender{ +/// information about light needed for rendering +struct LightInfo +{ + std::string name; // ogre handle + Ogre::ColourValue colour; + float radius; +}; + class Objects{ OEngine::Render::OgreRenderer &mRenderer; std::map mCellSceneNodes; std::map mStaticGeometry; std::map mStaticGeometrySmall; - //std::map mStaticGeometryAlpha; std::map mBounds; - std::vector mLights; + std::vector 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; static bool lightOutQuadInLin; + bool mInterior; + void clearSceneNode (Ogre::SceneNode *node); ///< Remove all movable objects from \a node. public: - Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer){} + Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer), mInterior(true) {} ~Objects(){} void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_); void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh); @@ -49,6 +53,12 @@ public: void enableLights(); void disableLights(); + void update (const float dt); + ///< per-frame update + + void setInterior(const bool interior); + ///< call this to switch from interior to exterior or vice versa + Ogre::AxisAlignedBox getDimensions(MWWorld::Ptr::CellStore*); ///< get a bounding box that encloses all objects in the specified cell diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 581973811..5232c5140 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -213,6 +213,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); @@ -508,4 +509,14 @@ Shadows* RenderingManager::getShadows() return mShadows; } +void RenderingManager::switchToInterior() +{ + mObjects.setInterior(true); +} + +void RenderingManager::switchToExterior() +{ + mObjects.setInterior(false); +} + } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index a563d78c6..cc3bc62b5 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -117,6 +117,9 @@ class RenderingManager: private RenderingInterface { Shadows* getShadows(); + void switchToInterior(); + void switchToExterior(); + void setGlare(bool glare); void skyEnable (); void skyDisable (); diff --git a/apps/openmw/mwrender/terrainmaterial.cpp b/apps/openmw/mwrender/terrainmaterial.cpp index 9785ec903..a3265b2a5 100644 --- a/apps/openmw/mwrender/terrainmaterial.cpp +++ b/apps/openmw/mwrender/terrainmaterial.cpp @@ -1149,8 +1149,8 @@ namespace Ogre // simple per-pixel lighting with no normal mapping for (int i=0; igetNumberOfLightsSupported(); ++i) { - outStream << " float3 halfAngle"< 0) outStream << diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 2123b4799..c8b20b8b1 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -203,6 +203,8 @@ namespace MWWorld // Sky system mWorld->adjustSky(); + mRendering.switchToExterior(); + mCellChanged = true; } @@ -248,8 +250,9 @@ namespace MWWorld // adjust player mCurrentCell = cell; playerCellChange (cell, position); - + // adjust fog + mRendering.switchToInterior(); mRendering.configureFog(*cell); // Sky system