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:
timoore
2008-12-10 22:39:48 +00:00
parent 1625192c81
commit 966b9e5c2b
4 changed files with 41 additions and 45 deletions

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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());

View File

@@ -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;
}