Use a singleton Fog attribute for all 3D clouds.
Don't update this Fog with any kind of update callback; instead, update from the sky repaint method.
This commit is contained in:
@@ -24,8 +24,10 @@
|
|||||||
# include <simgear_config.h>
|
# include <simgear_config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <osg/Fog>
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
#include <osg/PositionAttitudeTransform>
|
#include <osg/PositionAttitudeTransform>
|
||||||
|
#include <osg/Vec4f>
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
@@ -137,29 +139,6 @@ bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct threeDCloudsFogUpdater : public osg::NodeCallback {
|
|
||||||
threeDCloudsFogUpdater() {};
|
|
||||||
|
|
||||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
|
|
||||||
SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
|
|
||||||
//running at 5 times frame
|
|
||||||
SGCloudField::StateSetMap::iterator iter;
|
|
||||||
osg::Fog * fog;
|
|
||||||
for( iter = SGCloudField::cloudTextureMap.begin(); iter != SGCloudField::cloudTextureMap.end(); ++iter) {
|
|
||||||
fog = static_cast<osg::Fog*>(iter->second->getAttribute( osg::StateAttribute::FOG, 0 ));
|
|
||||||
fog->setMode(osg::Fog::EXP);
|
|
||||||
osg::Vec4f fogC = updateVisitor->getFogColor().osg();
|
|
||||||
fogC[3] = 0.0;
|
|
||||||
fog->setColor(fogC);
|
|
||||||
fog->setDensity(updateVisitor->getFogExpDensity());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->getNumChildrenRequiringUpdateTraversal()>0)
|
|
||||||
traverse(node,nv);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
SGCloudField::SGCloudField() :
|
SGCloudField::SGCloudField() :
|
||||||
field_root(new osg::Group),
|
field_root(new osg::Group),
|
||||||
field_transform(new osg::MatrixTransform),
|
field_transform(new osg::MatrixTransform),
|
||||||
@@ -171,11 +150,11 @@ SGCloudField::SGCloudField() :
|
|||||||
reposition_count(0)
|
reposition_count(0)
|
||||||
{
|
{
|
||||||
cld_pos = SGGeoc();
|
cld_pos = SGGeoc();
|
||||||
field_root->setUpdateCallback( new threeDCloudsFogUpdater() );
|
|
||||||
field_root->addChild(field_transform.get());
|
field_root->addChild(field_transform.get());
|
||||||
field_root->setName("3D Cloud field root");
|
field_root->setName("3D Cloud field root");
|
||||||
osg::StateSet *rootSet = field_root->getOrCreateStateSet();
|
osg::StateSet *rootSet = field_root->getOrCreateStateSet();
|
||||||
rootSet->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
|
rootSet->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
|
||||||
|
rootSet->setAttributeAndModes(getFog());
|
||||||
|
|
||||||
osg::ref_ptr<osg::Group> quad_root = new osg::Group();
|
osg::ref_ptr<osg::Group> quad_root = new osg::Group();
|
||||||
|
|
||||||
@@ -309,3 +288,17 @@ void SGCloudField::applyVisRange(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SGCloudField::CloudFog::CloudFog()
|
||||||
|
{
|
||||||
|
fog = new osg::Fog;
|
||||||
|
fog->setMode(osg::Fog::EXP2);
|
||||||
|
fog->setDataVariance(osg::Object::DYNAMIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SGCloudField::updateFog(double visibility, const osg::Vec4f& color)
|
||||||
|
{
|
||||||
|
const double sqrt_m_log01 = sqrt(-log(0.01));
|
||||||
|
osg::Fog* fog = CloudFog::instance()->fog.get();
|
||||||
|
fog->setColor(color);
|
||||||
|
fog->setDensity(sqrt_m_log01 / visibility);
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#include <plib/sg.h>
|
#include <plib/sg.h>
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <osgSim/Impostor>
|
|
||||||
#include <osgDB/ReaderWriter>
|
#include <osgDB/ReaderWriter>
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
@@ -34,9 +34,16 @@
|
|||||||
#include <osg/Geometry>
|
#include <osg/Geometry>
|
||||||
#include <osg/Group>
|
#include <osg/Group>
|
||||||
#include <osg/Switch>
|
#include <osg/Switch>
|
||||||
#include <osg/Billboard>
|
|
||||||
|
namespace osg
|
||||||
|
{
|
||||||
|
class Fog;
|
||||||
|
class StateSet;
|
||||||
|
class Vec4f;
|
||||||
|
}
|
||||||
|
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
|
#include <simgear/structure/Singleton.hxx>
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
@@ -78,6 +85,11 @@ private:
|
|||||||
float last_coverage;
|
float last_coverage;
|
||||||
SGGeoc cld_pos;
|
SGGeoc cld_pos;
|
||||||
int reposition_count;
|
int reposition_count;
|
||||||
|
struct CloudFog : public simgear::Singleton<CloudFog>
|
||||||
|
{
|
||||||
|
CloudFog();
|
||||||
|
osg::ref_ptr<osg::Fog> fog;
|
||||||
|
};
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SGCloudField();
|
SGCloudField();
|
||||||
@@ -126,6 +138,12 @@ public:
|
|||||||
|
|
||||||
typedef std::map<std::string, osg::ref_ptr<osg::StateSet> > StateSetMap;
|
typedef std::map<std::string, osg::ref_ptr<osg::StateSet> > StateSetMap;
|
||||||
static StateSetMap cloudTextureMap;
|
static StateSetMap cloudTextureMap;
|
||||||
|
|
||||||
|
static osg::Fog* getFog()
|
||||||
|
{
|
||||||
|
return CloudFog::instance()->fog.get();
|
||||||
|
}
|
||||||
|
static void updateFog(double visibility, const osg::Vec4f& color);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _CLOUDFIELD_HXX
|
#endif // _CLOUDFIELD_HXX
|
||||||
|
|||||||
@@ -129,21 +129,10 @@ static char fragmentShaderSource[] =
|
|||||||
"{\n"
|
"{\n"
|
||||||
" vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);\n"
|
" vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);\n"
|
||||||
" vec4 finalColor = base * gl_Color;\n"
|
" vec4 finalColor = base * gl_Color;\n"
|
||||||
" gl_FragColor = mix(gl_Fog.color, finalColor, fogFactor );\n"
|
" gl_FragColor.rgb = mix(gl_Fog.color.rgb, finalColor.rgb, fogFactor );\n"
|
||||||
|
" gl_FragColor.a = finalColor.a;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
class SGCloudFogUpdateCallback : public osg::StateAttribute::Callback {
|
|
||||||
public:
|
|
||||||
virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
|
|
||||||
{
|
|
||||||
SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
|
|
||||||
osg::Fog* fog = static_cast<osg::Fog*>(sa);
|
|
||||||
fog->setMode(osg::Fog::EXP);
|
|
||||||
fog->setColor(updateVisitor->getFogColor().osg());
|
|
||||||
fog->setDensity(updateVisitor->getFogExpDensity());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SGNewCloud::SGNewCloud(string type,
|
SGNewCloud::SGNewCloud(string type,
|
||||||
const SGPath &tex_path,
|
const SGPath &tex_path,
|
||||||
string tex,
|
string tex,
|
||||||
@@ -193,11 +182,6 @@ SGNewCloud::SGNewCloud(string type,
|
|||||||
stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||||
|
|
||||||
// Fog handling
|
// Fog handling
|
||||||
osg::Fog* fog = new osg::Fog;
|
|
||||||
fog->setUpdateCallback(new SGCloudFogUpdateCallback);
|
|
||||||
stateSet->setAttributeAndModes(fog);
|
|
||||||
stateSet->setDataVariance(osg::Object::DYNAMIC);
|
|
||||||
|
|
||||||
stateSet->setAttributeAndModes(attribFactory->getSmoothShadeModel());
|
stateSet->setAttributeAndModes(attribFactory->getSmoothShadeModel());
|
||||||
stateSet->setAttributeAndModes(attribFactory->getStandardBlendFunc());
|
stateSet->setAttributeAndModes(attribFactory->getStandardBlendFunc());
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,8 @@ bool SGSky::repaint( const SGSkyColor &sc )
|
|||||||
// turn off sky
|
// turn off sky
|
||||||
disable();
|
disable();
|
||||||
}
|
}
|
||||||
|
SGCloudField::updateFog((double)effective_visibility,
|
||||||
|
osg::Vec4f(sc.fog_color.osg(), 1.0f));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user