X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Ftgdb%2Fpt_lights.cxx;h=bfe3c5ae963544aaab92c694afc79d79cdce94e3;hb=9cbbe5559844317f44744788ddb308101a1e75e9;hp=e5c9a19cd6504daa2d404c6f4b983efa9728efa0;hpb=4324ffccf4bdcf34f8f8bd2f03d408fb6c958ed0;p=simgear.git diff --git a/simgear/scene/tgdb/pt_lights.cxx b/simgear/scene/tgdb/pt_lights.cxx index e5c9a19c..bfe3c5ae 100644 --- a/simgear/scene/tgdb/pt_lights.cxx +++ b/simgear/scene/tgdb/pt_lights.cxx @@ -26,6 +26,9 @@ #include "pt_lights.hxx" +#include +#include + #include #include #include @@ -50,15 +53,26 @@ #include +#include +#include + #include #include -#include -#include #include #include +#include + +#include +#include +#include +#include #include "SGVasiDrawable.hxx" +using OpenThreads::Mutex; +using OpenThreads::ScopedLock; + +using namespace osg; using namespace simgear; static void @@ -123,19 +137,16 @@ getPointSpriteImage(int logResolution) return image; } +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 texture; if (texture.valid()) return texture.get(); - static SGMutex mutex; - SGGuard guard(mutex); - if (texture.valid()) - return texture.get(); - texture = new osg::Texture2D; texture->setImage(getPointSpriteImage(6)); texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP); @@ -144,86 +155,90 @@ 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 PointParams; +typedef std::map > 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 polyMode = new PolygonMode(PolygonMode::FRONT, + PolygonMode::POINT); +ref_ptr 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(nv)); - osgUtil::CullVisitor* cv = static_cast(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 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 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 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 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; - vertices->push_back(light.position.osg()); - colors->push_back(light.color.osg()); + vertices->push_back(toOsg(light.position)); + colors->push_back(toOsg(light.color)); osg::Geometry* geometry = new osg::Geometry; geometry->setVertexArray(vertices); @@ -239,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; @@ -272,12 +270,12 @@ SGLightFactory::getLight(const SGDirectionalLightBin::Light& light) SGVec3f perp1 = perpendicular(normal); SGVec3f perp2 = cross(normal, perp1); SGVec3f position = light.position; - vertices->push_back(position.osg()); - vertices->push_back((position + perp1).osg()); - vertices->push_back((position + perp2).osg()); - colors->push_back(visibleColor.osg()); - colors->push_back(invisibleColor.osg()); - colors->push_back(invisibleColor.osg()); + vertices->push_back(toOsg(position)); + vertices->push_back(toOsg(position + perp1)); + vertices->push_back(toOsg(position + perp2)); + colors->push_back(toOsg(visibleColor)); + colors->push_back(toOsg(invisibleColor)); + colors->push_back(toOsg(invisibleColor)); osg::Geometry* geometry = new osg::Geometry; geometry->setVertexArray(vertices); @@ -292,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 simpleLightSS; +} osg::Drawable* SGLightFactory::getLights(const SGLightBin& lights, unsigned inc, float alphaOff) { @@ -336,10 +307,10 @@ SGLightFactory::getLights(const SGLightBin& lights, unsigned inc, float alphaOff osg::Vec4Array* colors = new osg::Vec4Array; for (unsigned i = 0; i < lights.getNumLights(); i += inc) { - vertices->push_back(lights.getLight(i).position.osg()); + vertices->push_back(toOsg(lights.getLight(i).position)); SGVec4f color = lights.getLight(i).color; color[3] = SGMiscf::max(0, SGMiscf::min(1, color[3] + alphaOff)); - colors->push_back(color.osg()); + colors->push_back(toOsg(color)); } osg::Geometry* geometry = new osg::Geometry; @@ -353,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 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; } @@ -389,12 +358,12 @@ SGLightFactory::getLights(const SGDirectionalLightBin& lights) SGVec3f perp1 = perpendicular(normal); SGVec3f perp2 = cross(normal, perp1); SGVec3f position = lights.getLight(i).position; - vertices->push_back(position.osg()); - vertices->push_back((position + perp1).osg()); - vertices->push_back((position + perp2).osg()); - colors->push_back(visibleColor.osg()); - colors->push_back(invisibleColor.osg()); - colors->push_back(invisibleColor.osg()); + vertices->push_back(toOsg(position)); + vertices->push_back(toOsg(position + perp1)); + vertices->push_back(toOsg(position + perp2)); + colors->push_back(toOsg(visibleColor)); + colors->push_back(toOsg(invisibleColor)); + colors->push_back(toOsg(invisibleColor)); } osg::Geometry* geometry = new osg::Geometry; @@ -408,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; } @@ -518,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; } @@ -561,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 @@ -579,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; }