mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-25 11:26:37 +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; |  | ||||||
| 
 | 
 | ||||||
|  |     bool quadratic = false; | ||||||
|     if (!lightOutQuadInLin) |     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; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue