mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-22 12:23:53 +00:00
light improvements
This commit is contained in:
parent
fb0e649191
commit
c6da3872b4
6 changed files with 113 additions and 68 deletions
|
@ -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,34 +191,35 @@ 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;
|
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)
|
quadratic = !mInterior;
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,13 +275,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 +292,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 +301,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 +316,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 +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<LightInfo>::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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,37 +10,41 @@
|
||||||
|
|
||||||
namespace MWRender{
|
namespace MWRender{
|
||||||
|
|
||||||
|
/// information about light needed for rendering
|
||||||
|
struct LightInfo
|
||||||
|
{
|
||||||
|
std::string name; // ogre handle
|
||||||
|
Ogre::ColourValue colour;
|
||||||
|
float radius;
|
||||||
|
};
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
static bool lightOutQuadInLin;
|
static bool lightOutQuadInLin;
|
||||||
|
|
||||||
|
bool mInterior;
|
||||||
|
|
||||||
void clearSceneNode (Ogre::SceneNode *node);
|
void clearSceneNode (Ogre::SceneNode *node);
|
||||||
///< 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), mInterior(true) {}
|
||||||
~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 +53,12 @@ public:
|
||||||
void enableLights();
|
void enableLights();
|
||||||
void disableLights();
|
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*);
|
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
|
||||||
|
|
||||||
|
|
|
@ -213,6 +213,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);
|
||||||
|
|
||||||
|
@ -508,4 +509,14 @@ Shadows* RenderingManager::getShadows()
|
||||||
return mShadows;
|
return mShadows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingManager::switchToInterior()
|
||||||
|
{
|
||||||
|
mObjects.setInterior(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingManager::switchToExterior()
|
||||||
|
{
|
||||||
|
mObjects.setInterior(false);
|
||||||
|
}
|
||||||
|
|
||||||
} // 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 ();
|
||||||
|
|
|
@ -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 <<
|
||||||
|
|
|
@ -203,6 +203,8 @@ namespace MWWorld
|
||||||
// Sky system
|
// Sky system
|
||||||
mWorld->adjustSky();
|
mWorld->adjustSky();
|
||||||
|
|
||||||
|
mRendering.switchToExterior();
|
||||||
|
|
||||||
mCellChanged = true;
|
mCellChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,8 +250,9 @@ namespace MWWorld
|
||||||
// adjust player
|
// adjust player
|
||||||
mCurrentCell = cell;
|
mCurrentCell = cell;
|
||||||
playerCellChange (cell, position);
|
playerCellChange (cell, position);
|
||||||
|
|
||||||
// adjust fog
|
// adjust fog
|
||||||
|
mRendering.switchToInterior();
|
||||||
mRendering.configureFog(*cell);
|
mRendering.configureFog(*cell);
|
||||||
|
|
||||||
// Sky system
|
// Sky system
|
||||||
|
|
Loading…
Reference in a new issue