diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index 713524a41..444530dbe 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -179,7 +179,7 @@ namespace SceneUtil // possible optimization: return a StateSet containing all requested lights plus some extra lights (if a suitable one exists) size_t hash = 0; for (unsigned int i=0; igetId()); + boost::hash_combine(hash, lightList[i]->mLightSource->getId()); LightStateSetMap::iterator found = mStateSetCache.find(hash); if (found != mStateSetCache.end()) @@ -189,7 +189,7 @@ namespace SceneUtil std::vector > lights; for (unsigned int i=0; igetLight()); + lights.push_back(lightList[i]->mLightSource->getLight()); osg::ref_ptr attr = new LightStateAttribute(mStartLight, lights); @@ -237,6 +237,12 @@ namespace SceneUtil mId = sLightId++; } + + bool sortLights (const LightManager::LightSourceTransform* left, const LightManager::LightSourceTransform* right) + { + return left->mViewBound.center().length2() < right->mViewBound.center().length2(); + } + void LightListCallback::operator()(osg::Node *node, osg::NodeVisitor *nv) { osgUtil::CullVisitor* cv = static_cast(nv); @@ -279,12 +285,12 @@ namespace SceneUtil osg::Matrixf mat = *cv->getModelViewMatrix(); transformBoundingSphere(mat, nodeBound); - std::vector lightList; + std::vector lightList; for (unsigned int i=0; i maxLights) { - //std::cerr << "More than 8 lights!" << std::endl; + // remove lights culled by this camera + for (LightManager::LightList::iterator it = lightList.begin(); it != lightList.end();) + { + osg::CullStack::CullingStack& stack = cv->getProjectionCullingStack(); - // TODO: sort lights by certain criteria + if (stack.back().isCulled(osg::BoundingSphere((*it)->mViewBound.center(), (*it)->mViewBound.radius()*2))) + { + it = lightList.erase(it); + continue; + } + else + ++it; + } - while (lightList.size() > maxLights) - lightList.pop_back(); + if (lightList.size() > maxLights) + { + // sort by proximity to camera, then get rid of furthest away lights + std::sort(lightList.begin(), lightList.end(), sortLights); + while (lightList.size() > maxLights) + lightList.pop_back(); + } } osg::StateSet* stateset = mLightManager->getLightListStateSet(lightList); diff --git a/components/sceneutil/lightmanager.hpp b/components/sceneutil/lightmanager.hpp index ac819958f..f338e42ec 100644 --- a/components/sceneutil/lightmanager.hpp +++ b/components/sceneutil/lightmanager.hpp @@ -85,7 +85,7 @@ namespace SceneUtil const std::vector& getLights() const; - typedef std::vector LightList; + typedef std::vector LightList; osg::ref_ptr getLightListStateSet(const LightList& lightList);