|
看看他的源代码。它仅仅创建了一个大气层球体,并将模拟大气散射的shader应用于该球体,并没有将shader应用于地球,所以就造成了:
“有大气散射效果,但是没有影响地球本身”
如果不理解的话,看看googleearth的大气散射效果对比下就知道了。
这项技术是成熟的,shader大家用的也都一样。
void
SkyNode::makeAtmosphere( const osg::EllipsoidModel* em )
{
// create some skeleton geometry to shade:
osg::Geometry* drawable = s_makeEllipsoidGeometry( em, _outerRadius );
osg::Geode* geode = new osg::Geode();
geode->addDrawable( drawable );
osg::StateSet* set = geode->getOrCreateStateSet();
// configure the state set:
set->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
set->setMode( GL_CULL_FACE, osg::StateAttribute::ON );
set->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
//set->setBinNumber( 65 ); // todo, what?
set->setBinNumber( BIN_ATMOSPHERE );
set->setAttributeAndModes( new osg:epth( osg::Depth:ESS, 0, 1, false ) ); // no depth write
set->setAttributeAndModes( new osg::BlendFunc( GL_ONE, GL_ONE ), osg::StateAttribute::ON );
set->setAttributeAndModes( new osg::FrontFace( osg::FrontFace::CLOCKWISE ), osg::StateAttribute::ON );
// next, create and add the shaders:
osg:rogram* program = new osg::Program();
osg::Shader* vs = new osg::Shader( osg::Shader::VERTEX, s_atmosphereVertexSource );
program->addShader( vs );
osg::Shader* fs = new osg::Shader( osg::Shader::FRAGMENT, s_atmosphereFragmentSource );
program->addShader( fs );
set->setAttributeAndModes( program, osg::StateAttribute::ON );
// apply the uniforms:
float r_wl = ::powf( .65f, 4.0f );
float g_wl = ::powf( .57f, 4.0f );
float b_wl = ::powf( .475f, 4.0f );
osg::Vec3 RGB_wl( 1.0f/r_wl, 1.0f/g_wl, 1.0f/b_wl );
float Kr = 0.0025f;
float Kr4PI = Kr * 4.0f * osg::PI;
float Km = 0.0015f;
float Km4PI = Km * 4.0f * osg::PI;
float ESun = 15.0f;
float MPhase = -.095f;
float RayleighScaleDepth = 0.25f;
int Samples = 2;
float Weather = 1.0f;
float Scale = 1.0f / (_outerRadius - _innerRadius);
_defaultPerViewData._lightPosUniform = set->getOrCreateUniform( "atmos_v3LightPos", osg::Uniform::FLOAT_VEC3 );
_defaultPerViewData._lightPosUniform->set( _defaultPerViewData._lightPos / _defaultPerViewData._lightPos.length() );
set->getOrCreateUniform( "atmos_v3InvWavelength", osg::Uniform::FLOAT_VEC3 )->set( RGB_wl );
set->getOrCreateUniform( "atmos_fInnerRadius", osg::Uniform::FLOAT )->set( _innerRadius );
set->getOrCreateUniform( "atmos_fInnerRadius2", osg::Uniform::FLOAT )->set( _innerRadius * _innerRadius );
set->getOrCreateUniform( "atmos_fOuterRadius", osg::Uniform::FLOAT )->set( _outerRadius );
set->getOrCreateUniform( "atmos_fOuterRadius2", osg::Uniform::FLOAT )->set( _outerRadius * _outerRadius );
set->getOrCreateUniform( "atmos_fKrESun", osg::Uniform::FLOAT )->set( Kr * ESun );
set->getOrCreateUniform( "atmos_fKmESun", osg::Uniform::FLOAT )->set( Km * ESun );
set->getOrCreateUniform( "atmos_fKr4PI", osg::Uniform::FLOAT )->set( Kr4PI );
set->getOrCreateUniform( "atmos_fKm4PI", osg::Uniform::FLOAT )->set( Km4PI );
set->getOrCreateUniform( "atmos_fScale", osg::Uniform::FLOAT )->set( Scale );
set->getOrCreateUniform( "atmos_fScaleDepth", osg::Uniform::FLOAT )->set( RayleighScaleDepth );
set->getOrCreateUniform( "atmos_fScaleOverScaleDepth", osg::Uniform::FLOAT )->set( Scale / RayleighScaleDepth );
set->getOrCreateUniform( "atmos_g", osg::Uniform::FLOAT )->set( MPhase );
set->getOrCreateUniform( "atmos_g2", osg::Uniform::FLOAT )->set( MPhase * MPhase );
set->getOrCreateUniform( "atmos_nSamples", osg::Uniform::INT )->set( Samples );
set->getOrCreateUniform( "atmos_fSamples", osg::Uniform::FLOAT )->set( (float)Samples );
set->getOrCreateUniform( "atmos_fWeather", osg::Uniform::FLOAT )->set( Weather );
//geode->setCullCallback( new DoNotIncludeInNearFarComputationCallback() );
AddCallbackToDrawablesVisitor visitor( _innerRadius );
geode->accept( visitor );
_atmosphere = geode;
} |
|