]> git.mxchange.org Git - simgear.git/commitdiff
Use Effect to implement point lights
authortimoore <timoore>
Wed, 15 Jul 2009 23:10:21 +0000 (23:10 +0000)
committerTim Moore <timoore@redhat.com>
Thu, 16 Jul 2009 10:09:44 +0000 (12:09 +0200)
This allows different OpenGL features (point sprites, point attenuation) to
be used depending on hardware support.

simgear/scene/material/EffectCullVisitor.cxx
simgear/scene/material/mat.cxx
simgear/scene/tgdb/obj.cxx
simgear/scene/tgdb/pt_lights.cxx
simgear/scene/tgdb/pt_lights.hxx

index 8d86d8e0ea6972b6c3716cbca6e1f81ea49578a8..dec2b1bdef69c388d78da3f349d658eb009c815d 100644 (file)
@@ -14,6 +14,8 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
+#include <osg/StateSet>
+
 #include "EffectCullVisitor.hxx"
 
 #include "EffectGeode.hxx"
@@ -53,11 +55,19 @@ void EffectCullVisitor::apply(osg::Geode& node)
         CullVisitor::apply(node);
         return;
     }
+    // push the node's state.
+    osg::StateSet* node_state = node.getStateSet();
+    if (node_state)
+        pushStateSet(node_state);
     for (EffectGeode::DrawablesIterator beginItr = eg->drawablesBegin(),
              e = eg->drawablesEnd();
          beginItr != e;
          beginItr = technique->processDrawables(beginItr, e, this,
                                                 eg->isCullingActive()))
         ;
+    // pop the node's state off the geostate stack.
+    if (node_state)
+        popStateSet();
+
 }
 }
index 2c97551a31569f117803eeea46b8e52e723dc505..dddec02dea7c86fc67382cc75949082699fd6b7c 100644 (file)
@@ -314,8 +314,7 @@ SGMaterial::build_state( bool defer_tex_load )
         }
 
         _status[i].state = pass;
-        Technique* tniq = new Technique();
-        tniq->setGLExtensionsPred(1.1, std::vector<std::string>());
+        Technique* tniq = new Technique(true);
         tniq->passes.push_back(pass);
         Effect* effect = new Effect;
         effect->techniques.push_back(tniq);
index 2efad952b68085ea46a40c2a35dc588c3fc26be4..3869c521ab2588a369ada417d8b8b4055aac6733 100644 (file)
@@ -683,7 +683,10 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool
   }
 
   if (!tileGeometryBin.vasiLights.empty()) {
-    osg::Geode* vasiGeode = new osg::Geode;
+    EffectGeode* vasiGeode = new EffectGeode;
+    Effect* vasiEffect
+        = getLightEffect(6, osg::Vec3(1, 0.0001, 0.000001), 1, 6, true);
+    vasiGeode->setEffect(vasiEffect);
     SGVec4f red(1, 0, 0, 1);
     SGMaterial* mat = 0;
     if (matlib)
@@ -696,27 +699,31 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool
       mat = matlib->find("RWY_WHITE_LIGHTS");
     if (mat)
       white = mat->get_light_color();
-
     SGDirectionalLightListBin::const_iterator i;
     for (i = tileGeometryBin.vasiLights.begin();
          i != tileGeometryBin.vasiLights.end(); ++i) {
       vasiGeode->addDrawable(SGLightFactory::getVasi(up, *i, red, white));
     }
-    vasiGeode->setCullCallback(new SGPointSpriteLightCullCallback(osg::Vec3(1, 0.0001, 0.000001), 6));
     vasiGeode->setStateSet(lightManager->getRunwayLightStateSet());
     lightGroup->addChild(vasiGeode);
   }
-
+  Effect* runwayEffect = 0;
+  if (tileGeometryBin.runwayLights.getNumLights() > 0
+      || !tileGeometryBin.rabitLights.empty()
+      || !tileGeometryBin.reilLights.empty()
+      || !tileGeometryBin.odalLights.empty()
+      || tileGeometryBin.taxiLights.getNumLights() > 0)
+      runwayEffect = getLightEffect(4, osg::Vec3(1, 0.001, 0.0002), 1, 4, true);
   if (tileGeometryBin.runwayLights.getNumLights() > 0
       || !tileGeometryBin.rabitLights.empty()
       || !tileGeometryBin.reilLights.empty()
       || !tileGeometryBin.odalLights.empty()) {
     osg::Group* rwyLights = new osg::Group;
-    rwyLights->setCullCallback(new SGPointSpriteLightCullCallback);
     rwyLights->setStateSet(lightManager->getRunwayLightStateSet());
     rwyLights->setNodeMask(RUNWAYLIGHTS_BIT);
     if (tileGeometryBin.runwayLights.getNumLights() != 0) {
-      osg::Geode* geode = new osg::Geode;
+      EffectGeode* geode = new EffectGeode;
+      geode->setEffect(runwayEffect);
       geode->addDrawable(SGLightFactory::getLights(tileGeometryBin
                                                    .runwayLights));
       rwyLights->addChild(geode);
@@ -740,10 +747,10 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool
 
   if (tileGeometryBin.taxiLights.getNumLights() > 0) {
     osg::Group* taxiLights = new osg::Group;
-    taxiLights->setCullCallback(new SGPointSpriteLightCullCallback);
     taxiLights->setStateSet(lightManager->getTaxiLightStateSet());
     taxiLights->setNodeMask(RUNWAYLIGHTS_BIT);
-    osg::Geode* geode = new osg::Geode;
+    EffectGeode* geode = new EffectGeode;
+    geode->setEffect(runwayEffect);
     geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.taxiLights));
     taxiLights->addChild(geode);
     lightGroup->addChild(taxiLights);
index 274a4e1873054e609192e9b7f8bd157e4e97be45..e15b7beaae44367220cd3a26124bb80453998ab7 100644 (file)
@@ -26,6 +26,9 @@
 
 #include "pt_lights.hxx"
 
+#include <map>
+#include <boost/tuple/tuple_comparison.hpp>
+
 #include <osg/Array>
 #include <osg/Geometry>
 #include <osg/CullFace>
 #include <simgear/debug/logstream.hxx>
 #include <simgear/scene/util/RenderConstants.hxx>
 #include <simgear/scene/util/SGEnlargeBoundingBox.hxx>
+#include <simgear/scene/util/StateAttributeFactory.hxx>
+
+#include <simgear/scene/material/Effect.hxx>
+#include <simgear/scene/material/EffectGeode.hxx>
+#include <simgear/scene/material/Technique.hxx>
+#include <simgear/scene/material/Pass.hxx>
 
 #include "SGVasiDrawable.hxx"
 
 using OpenThreads::Mutex;
 using OpenThreads::ScopedLock;
 
+using namespace osg;
 using namespace simgear;
 
 static void
@@ -132,15 +142,11 @@ static Mutex lightMutex;
 static osg::Texture2D*
 gen_standard_light_sprite(void)
 {
-  // double checked locking ...
+  // Always called from when the lightMutex is already taken
   static osg::ref_ptr<osg::Texture2D> texture;
   if (texture.valid())
     return texture.get();
   
-  ScopedLock<Mutex> lock(lightMutex);
-  if (texture.valid())
-    return texture.get();
-  
   texture = new osg::Texture2D;
   texture->setImage(getPointSpriteImage(6));
   texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);
@@ -149,80 +155,84 @@ gen_standard_light_sprite(void)
   return texture.get();
 }
 
-SGPointSpriteLightCullCallback::SGPointSpriteLightCullCallback(const osg::Vec3& da,
-                                                               float sz) :
-  _pointSpriteStateSet(new osg::StateSet),
-  _distanceAttenuationStateSet(new osg::StateSet)
+namespace
 {
-  osg::PointSprite* pointSprite = new osg::PointSprite;
-  _pointSpriteStateSet->setTextureAttributeAndModes(0, pointSprite,
-                                                    osg::StateAttribute::ON);
-  osg::Texture2D* texture = gen_standard_light_sprite();
-  _pointSpriteStateSet->setTextureAttribute(0, texture);
-  _pointSpriteStateSet->setTextureMode(0, GL_TEXTURE_2D,
-                                       osg::StateAttribute::ON);
-  osg::TexEnv* texEnv = new osg::TexEnv;
-  texEnv->setMode(osg::TexEnv::MODULATE);
-  _pointSpriteStateSet->setTextureAttribute(0, texEnv);
-  
-  osg::Point* point = new osg::Point;
-  point->setFadeThresholdSize(1);
-  point->setMinSize(1);
-  point->setMaxSize(sz);
-  point->setSize(sz);
-  point->setDistanceAttenuation(da);
-  _distanceAttenuationStateSet->setAttributeAndModes(point);
-}
+typedef boost::tuple<float, osg::Vec3, float, float, bool> PointParams;
+typedef std::map<PointParams, ref_ptr<Effect> > EffectMap;
 
-// FIXME make state sets static
-SGPointSpriteLightCullCallback::SGPointSpriteLightCullCallback(osg::Point* point) :
-  _pointSpriteStateSet(new osg::StateSet),
-  _distanceAttenuationStateSet(new osg::StateSet)
-{
-  osg::PointSprite* pointSprite = new osg::PointSprite;
-  _pointSpriteStateSet->setTextureAttributeAndModes(0, pointSprite,
-                                                    osg::StateAttribute::ON);
-  osg::Texture2D* texture = gen_standard_light_sprite();
-  _pointSpriteStateSet->setTextureAttribute(0, texture);
-  _pointSpriteStateSet->setTextureMode(0, GL_TEXTURE_2D,
-                                       osg::StateAttribute::ON);
-  osg::TexEnv* texEnv = new osg::TexEnv;
-  texEnv->setMode(osg::TexEnv::MODULATE);
-  _pointSpriteStateSet->setTextureAttribute(0, texEnv);
-  
-  _distanceAttenuationStateSet->setAttributeAndModes(point);
+EffectMap effectMap;
+
+ref_ptr<PolygonMode> polyMode = new PolygonMode(PolygonMode::FRONT,
+                                                PolygonMode::POINT);
+ref_ptr<PointSprite> pointSprite = new PointSprite;
 }
 
-void
-SGPointSpriteLightCullCallback::operator()(osg::Node* node,
-                                           osg::NodeVisitor* nv)
+Effect* getLightEffect(float size, const Vec3& attenuation,
+                       float minSize, float maxSize, bool directional)
 {
-  assert(dynamic_cast<osgUtil::CullVisitor*>(nv));
-  osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
-  
-  // Test for point sprites and point parameters availibility
-  unsigned contextId = cv->getRenderInfo().getContextID();
-  SGSceneFeatures* features = SGSceneFeatures::instance();
-  bool usePointSprite = features->getEnablePointSpriteLights(contextId);
-  bool usePointParameters = features->getEnableDistanceAttenuationLights(contextId);
-  
-  if (usePointSprite)
-    cv->pushStateSet(_pointSpriteStateSet.get());
-  
-  if (usePointParameters)
-    cv->pushStateSet(_distanceAttenuationStateSet.get());
-  
-  traverse(node, nv);
-  
-  if (usePointParameters)
-    cv->popStateSet();
-  
-  if (usePointSprite)
-    cv->popStateSet();
+    PointParams pointParams(size, attenuation, minSize, maxSize, directional);
+    ScopedLock<Mutex> lock(lightMutex);
+    EffectMap::iterator eitr = effectMap.find(pointParams);
+    if (eitr != effectMap.end())
+        return eitr->second.get();
+    // Basic stuff; no sprite or attenuation support
+    Pass *basicPass = new Pass;
+    basicPass->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
+    basicPass->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+    StateAttributeFactory *attrFact = StateAttributeFactory::instance();
+    basicPass->setAttributeAndModes(attrFact->getStandardBlendFunc());
+    basicPass->setAttributeAndModes(attrFact->getStandardAlphaFunc());
+    if (directional) {
+        basicPass->setAttributeAndModes(attrFact->getCullFaceBack());
+        basicPass->setAttribute(polyMode.get());
+    }
+    Pass *attenuationPass = clone(basicPass, CopyOp::SHALLOW_COPY);
+    osg::Point* point = new osg::Point;
+    point->setMinSize(minSize);
+    point->setMaxSize(maxSize);
+    point->setSize(size);
+    point->setDistanceAttenuation(attenuation);
+    attenuationPass->setAttributeAndModes(point);
+    Pass *spritePass = clone(basicPass, CopyOp::SHALLOW_COPY);
+    spritePass->setTextureAttributeAndModes(0, pointSprite,
+                                            osg::StateAttribute::ON);
+    Texture2D* texture = gen_standard_light_sprite();
+    spritePass->setTextureAttribute(0, texture);
+    spritePass->setTextureMode(0, GL_TEXTURE_2D,
+                               osg::StateAttribute::ON);
+    spritePass->setTextureAttribute(0, attrFact->getStandardTexEnv());
+    Pass *combinedPass = clone(spritePass, CopyOp::SHALLOW_COPY);
+    combinedPass->setAttributeAndModes(point);
+    Effect* effect = new Effect;
+    std::vector<std::string> combinedExtensions;
+    combinedExtensions.push_back("GL_ARB_point_sprite");
+    combinedExtensions.push_back("GL_ARB_point_parameters");
+    Technique* combinedTniq = new Technique;
+    combinedTniq->passes.push_back(combinedPass);
+    combinedTniq->setGLExtensionsPred(2.0, combinedExtensions);
+    effect->techniques.push_back(combinedTniq);
+    std::vector<std::string> spriteExtensions;
+    spriteExtensions.push_back(combinedExtensions.front());
+    Technique* spriteTniq = new Technique;
+    spriteTniq->passes.push_back(spritePass);
+    spriteTniq->setGLExtensionsPred(2.0, spriteExtensions);
+    effect->techniques.push_back(spriteTniq);
+    std::vector<std::string> parameterExtensions;
+    parameterExtensions.push_back(combinedExtensions.back());
+    Technique* parameterTniq = new Technique;
+    parameterTniq->passes.push_back(attenuationPass);
+    parameterTniq->setGLExtensionsPred(1.4, parameterExtensions);
+    effect->techniques.push_back(parameterTniq);
+    Technique* basicTniq = new Technique(true);
+    basicTniq->passes.push_back(basicPass);
+    effect->techniques.push_back(basicTniq);
+    effectMap.insert(std::make_pair(pointParams, effect));
+    return effect;
 }
 
-osg::Node*
-SGLightFactory::getLight(const SGLightBin::Light& light)
+
+osg::Drawable*
+SGLightFactory::getLightDrawable(const SGLightBin::Light& light)
 {
   osg::Vec3Array* vertices = new osg::Vec3Array;
   osg::Vec4Array* colors = new osg::Vec4Array;
@@ -244,28 +254,11 @@ SGLightFactory::getLight(const SGLightBin::Light& light)
   drawArrays = new osg::DrawArrays(osg::PrimitiveSet::POINTS,
                                    0, vertices->size());
   geometry->addPrimitiveSet(drawArrays);
-  
-  osg::StateSet* stateSet = geometry->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
-  stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
-  
-  osg::BlendFunc* blendFunc = new osg::BlendFunc;
-  stateSet->setAttribute(blendFunc);
-  stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
-  
-  osg::AlphaFunc* alphaFunc;
-  alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
-  stateSet->setAttribute(alphaFunc);
-  stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
-  
-  osg::Geode* geode = new osg::Geode;
-  geode->addDrawable(geometry);
-
-  return geode;
+  return geometry;
 }
 
-osg::Node*
-SGLightFactory::getLight(const SGDirectionalLightBin::Light& light)
+osg::Drawable*
+SGLightFactory::getLightDrawable(const SGDirectionalLightBin::Light& light)
 {
   osg::Vec3Array* vertices = new osg::Vec3Array;
   osg::Vec4Array* colors = new osg::Vec4Array;
@@ -297,40 +290,13 @@ SGLightFactory::getLight(const SGDirectionalLightBin::Light& light)
   drawArrays = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,
                                    0, vertices->size());
   geometry->addPrimitiveSet(drawArrays);
-  
-  osg::StateSet* stateSet = geometry->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
-
-  osg::Material* material = new osg::Material;
-  material->setColorMode(osg::Material::OFF);
-  stateSet->setAttribute(material);
-
-  osg::CullFace* cullFace = new osg::CullFace;
-  cullFace->setMode(osg::CullFace::BACK);
-  stateSet->setAttribute(cullFace, osg::StateAttribute::ON);
-  stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
-  
-  osg::PolygonMode* polygonMode = new osg::PolygonMode;
-  polygonMode->setMode(osg::PolygonMode::FRONT, osg::PolygonMode::POINT);
-  stateSet->setAttribute(polygonMode);
-
-  stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
-  
-  osg::BlendFunc* blendFunc = new osg::BlendFunc;
-  stateSet->setAttribute(blendFunc);
-  stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
-  
-  osg::AlphaFunc* alphaFunc;
-  alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
-  stateSet->setAttribute(alphaFunc);
-  stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
-  
-  osg::Geode* geode = new osg::Geode;
-  geode->addDrawable(geometry);
-
-  return geode;
+  return geometry;
 }
 
+namespace
+{
+  ref_ptr<StateSet> simpleLightSS;
+}
 osg::Drawable*
 SGLightFactory::getLights(const SGLightBin& lights, unsigned inc, float alphaOff)
 {
@@ -358,21 +324,19 @@ SGLightFactory::getLights(const SGLightBin& lights, unsigned inc, float alphaOff
   drawArrays = new osg::DrawArrays(osg::PrimitiveSet::POINTS,
                                    0, vertices->size());
   geometry->addPrimitiveSet(drawArrays);
-  
-  osg::StateSet* stateSet = geometry->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
 
-  stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
-  
-  osg::BlendFunc* blendFunc = new osg::BlendFunc;
-  stateSet->setAttribute(blendFunc);
-  stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
-  
-  osg::AlphaFunc* alphaFunc;
-  alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
-  stateSet->setAttribute(alphaFunc);
-  stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
-  
+  {
+    ScopedLock<Mutex> lock(lightMutex);
+    if (!simpleLightSS.valid()) {
+      StateAttributeFactory *attrFact = StateAttributeFactory::instance();
+      simpleLightSS = new StateSet;
+      simpleLightSS->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
+      simpleLightSS->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+      simpleLightSS->setAttributeAndModes(attrFact->getStandardBlendFunc());
+      simpleLightSS->setAttributeAndModes(attrFact->getStandardAlphaFunc());
+    }
+  }
+  geometry->setStateSet(simpleLightSS.get());
   return geometry;
 }
 
@@ -413,34 +377,6 @@ SGLightFactory::getLights(const SGDirectionalLightBin& lights)
   drawArrays = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,
                                    0, vertices->size());
   geometry->addPrimitiveSet(drawArrays);
-  
-  osg::StateSet* stateSet = geometry->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
-
-  osg::Material* material = new osg::Material;
-  material->setColorMode(osg::Material::OFF);
-  stateSet->setAttribute(material);
-
-  osg::CullFace* cullFace = new osg::CullFace;
-  cullFace->setMode(osg::CullFace::BACK);
-  stateSet->setAttribute(cullFace, osg::StateAttribute::ON);
-  stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
-  
-  osg::PolygonMode* polygonMode = new osg::PolygonMode;
-  polygonMode->setMode(osg::PolygonMode::FRONT, osg::PolygonMode::POINT);
-  stateSet->setAttribute(polygonMode);
-
-  stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
-  
-  osg::BlendFunc* blendFunc = new osg::BlendFunc;
-  stateSet->setAttribute(blendFunc);
-  stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
-  
-  osg::AlphaFunc* alphaFunc;
-  alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
-  stateSet->setAttribute(alphaFunc);
-  stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
-  
   return geometry;
 }
 
@@ -523,35 +459,19 @@ SGLightFactory::getSequenced(const SGDirectionalLightBin& lights)
   float flashTime = 2e-2 + 5e-3*sg_random();
   osg::Sequence* sequence = new osg::Sequence;
   sequence->setDefaultTime(flashTime);
-
-  for (int i = lights.getNumLights() - 1; 0 <= i; --i)
-    sequence->addChild(getLight(lights.getLight(i)), flashTime);
+  Effect* effect = getLightEffect(10.0f, osg::Vec3(1.0, 0.0001, 0.00000001),
+                                  6.0f, 10.0f, true);
+  for (int i = lights.getNumLights() - 1; 0 <= i; --i) {
+    EffectGeode* egeode = new EffectGeode;
+    egeode->setEffect(effect);
+    egeode->addDrawable(getLightDrawable(lights.getLight(i)));
+    sequence->addChild(egeode, flashTime);
+  }
   sequence->addChild(new osg::Group, 1 + 1e-1*sg_random());
   sequence->setInterval(osg::Sequence::LOOP, 0, -1);
   sequence->setDuration(1.0f, -1);
   sequence->setMode(osg::Sequence::START);
   sequence->setSync(true);
-
-  osg::StateSet* stateSet = sequence->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
-  stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
-
-  osg::BlendFunc* blendFunc = new osg::BlendFunc;
-  stateSet->setAttribute(blendFunc);
-  stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
-  
-  osg::AlphaFunc* alphaFunc;
-  alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
-  stateSet->setAttribute(alphaFunc);
-  stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
-
-  osg::Point* point = new osg::Point;
-  point->setMinSize(6);
-  point->setMaxSize(10);
-  point->setSize(10);
-  point->setDistanceAttenuation(osg::Vec3(1.0, 0.0001, 0.00000001));
-  sequence->setCullCallback(new SGPointSpriteLightCullCallback(point));
-
   return sequence;
 }
 
@@ -566,15 +486,23 @@ SGLightFactory::getOdal(const SGLightBin& lights)
   float flashTime = 2e-2 + 5e-3*sg_random();
   osg::Sequence* sequence = new osg::Sequence;
   sequence->setDefaultTime(flashTime);
-
+  Effect* effect = getLightEffect(10.0f, osg::Vec3(1.0, 0.0001, 0.00000001),
+                                  6.0, 10.0, false);
   // centerline lights
-  for (int i = lights.getNumLights() - 1; 2 <= i; --i)
-    sequence->addChild(getLight(lights.getLight(i)), flashTime);
-
+  for (int i = lights.getNumLights() - 1; 2 <= i; --i) {
+    EffectGeode* egeode = new EffectGeode;
+    egeode->setEffect(effect);
+    egeode->addDrawable(getLightDrawable(lights.getLight(i)));
+    sequence->addChild(egeode, flashTime);
+  }
   // runway end lights
   osg::Group* group = new osg::Group;
-  for (unsigned i = 0; i < 2; ++i)
-    group->addChild(getLight(lights.getLight(i)));
+  for (unsigned i = 0; i < 2; ++i) {
+    EffectGeode* egeode = new EffectGeode;
+    egeode->setEffect(effect);
+    egeode->addDrawable(getLightDrawable(lights.getLight(i)));
+    group->addChild(egeode);
+  }
   sequence->addChild(group, flashTime);
 
   // add an extra empty group for a break
@@ -584,25 +512,5 @@ SGLightFactory::getOdal(const SGLightBin& lights)
   sequence->setMode(osg::Sequence::START);
   sequence->setSync(true);
 
-  osg::StateSet* stateSet = sequence->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
-  stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
-
-  osg::BlendFunc* blendFunc = new osg::BlendFunc;
-  stateSet->setAttribute(blendFunc);
-  stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
-  
-  osg::AlphaFunc* alphaFunc;
-  alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
-  stateSet->setAttribute(alphaFunc);
-  stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
-
-  osg::Point* point = new osg::Point;
-  point->setMinSize(6);
-  point->setMaxSize(10);
-  point->setSize(10);
-  point->setDistanceAttenuation(osg::Vec3(1.0, 0.0001, 0.00000001));
-  sequence->setCullCallback(new SGPointSpriteLightCullCallback(point));
-
   return sequence;
 }
index 5f831cbf47d4248cc42c24f1b64c7c5d36f45e2a..6357c14c23c090ab907f052ff6c43ef83ca2954b 100644 (file)
 #include "SGLightBin.hxx"
 #include "SGDirectionalLightBin.hxx"
 
-using std::string;
-using std::vector;
+namespace simgear
+{
+class Effect;
+}
 
 // Specify the way we want to draw directional point lights (assuming the
 // appropriate extensions are available.)
@@ -59,28 +61,19 @@ inline void SGConfigureDirectionalLights( bool use_point_sprites,
   sceneFeatures->setEnableDistanceAttenuationLights(distance_attenuation);
 }
 
-class SGPointSpriteLightCullCallback : public osg::NodeCallback {
-public:
-  SGPointSpriteLightCullCallback(const osg::Vec3& da = osg::Vec3(1, 0.001, 0.0002),
-                                 float sz = 4);
-  SGPointSpriteLightCullCallback(osg::Point* point);
-
-  virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
-
-private:
-  osg::ref_ptr<osg::StateSet> _pointSpriteStateSet;
-  osg::ref_ptr<osg::StateSet> _distanceAttenuationStateSet;
-};
-
 class SGLightFactory {
 public:
 
-  static osg::Node*
-  getLight(const SGLightBin::Light& light);
+  static osg::Drawable*
+  getLightDrawable(const SGLightBin::Light& light);
 
-  static osg::Node*
-  getLight(const SGDirectionalLightBin::Light& light);
+  static osg::Drawable*
+  getLightDrawable(const SGDirectionalLightBin::Light& light);
 
+  /**
+   * Return a drawable for a very simple point light that isn't
+   * distance scaled.
+   */
   static osg::Drawable*
   getLights(const SGLightBin& lights, unsigned inc = 1, float alphaOff = 0);
 
@@ -98,4 +91,6 @@ public:
   getOdal(const SGLightBin& lights);
 };
 
+simgear::Effect* getLightEffect(float size, const osg::Vec3& attenuation,
+                                float minSize, float maxSize, bool directional);
 #endif // _SG_PT_LIGHTS_HXX