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>
|
||||
#endif
|
||||
|
||||
#include <osg/Fog>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <osg/Vec4f>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
@@ -137,29 +139,6 @@ bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
|
||||
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() :
|
||||
field_root(new osg::Group),
|
||||
field_transform(new osg::MatrixTransform),
|
||||
@@ -171,11 +150,11 @@ SGCloudField::SGCloudField() :
|
||||
reposition_count(0)
|
||||
{
|
||||
cld_pos = SGGeoc();
|
||||
field_root->setUpdateCallback( new threeDCloudsFogUpdater() );
|
||||
field_root->addChild(field_transform.get());
|
||||
field_root->setName("3D Cloud field root");
|
||||
osg::StateSet *rootSet = field_root->getOrCreateStateSet();
|
||||
rootSet->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
|
||||
rootSet->setAttributeAndModes(getFog());
|
||||
|
||||
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 <simgear/compiler.h>
|
||||
#include <vector>
|
||||
#include <osgSim/Impostor>
|
||||
|
||||
#include <osgDB/ReaderWriter>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
@@ -34,9 +34,16 @@
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Group>
|
||||
#include <osg/Switch>
|
||||
#include <osg/Billboard>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Fog;
|
||||
class StateSet;
|
||||
class Vec4f;
|
||||
}
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/structure/Singleton.hxx>
|
||||
|
||||
using std::vector;
|
||||
|
||||
@@ -78,6 +85,11 @@ private:
|
||||
float last_coverage;
|
||||
SGGeoc cld_pos;
|
||||
int reposition_count;
|
||||
struct CloudFog : public simgear::Singleton<CloudFog>
|
||||
{
|
||||
CloudFog();
|
||||
osg::ref_ptr<osg::Fog> fog;
|
||||
};
|
||||
public:
|
||||
|
||||
SGCloudField();
|
||||
@@ -126,6 +138,12 @@ public:
|
||||
|
||||
typedef std::map<std::string, osg::ref_ptr<osg::StateSet> > StateSetMap;
|
||||
static StateSetMap cloudTextureMap;
|
||||
|
||||
static osg::Fog* getFog()
|
||||
{
|
||||
return CloudFog::instance()->fog.get();
|
||||
}
|
||||
static void updateFog(double visibility, const osg::Vec4f& color);
|
||||
};
|
||||
|
||||
#endif // _CLOUDFIELD_HXX
|
||||
|
||||
@@ -129,21 +129,10 @@ static char fragmentShaderSource[] =
|
||||
"{\n"
|
||||
" vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);\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";
|
||||
|
||||
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,
|
||||
const SGPath &tex_path,
|
||||
string tex,
|
||||
@@ -193,11 +182,6 @@ SGNewCloud::SGNewCloud(string type,
|
||||
stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||
|
||||
// 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->getStandardBlendFunc());
|
||||
|
||||
|
||||
@@ -128,7 +128,8 @@ bool SGSky::repaint( const SGSkyColor &sc )
|
||||
// turn off sky
|
||||
disable();
|
||||
}
|
||||
|
||||
SGCloudField::updateFog((double)effective_visibility,
|
||||
osg::Vec4f(sc.fog_color.osg(), 1.0f));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user