查看: 7565|回复: 6

OSGEarth SkyNode大气效果效果不佳的原因找到了。

[复制链接]

该用户从未签到

发表于 2011-8-30 21:38:48 | 显示全部楼层 |阅读模式
看看他的源代码。它仅仅创建了一个大气层球体,并将模拟大气散射的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;
}

该用户从未签到

发表于 2011-8-31 08:40:24 | 显示全部楼层
GPU Gems的大气散射效果基本上很多人都用过,Flysky他们给中央台作的OSG地球也用了这个效果。至于效果和通用性之间如何取舍,这就是见仁见智的问题了

该用户从未签到

 楼主| 发表于 2011-8-31 13:56:00 | 显示全部楼层
这里不存在通用性的问题,SkyNode也用的是gpu gems的shader,这里存在性能的差异。
如果考虑地球本身的话会损失一些性能。

该用户从未签到

发表于 2011-9-15 17:01:57 | 显示全部楼层
用这个shader为地球加入散射之后,往上添加的物体都不见了。

该用户从未签到

发表于 2012-4-20 19:10:45 | 显示全部楼层
sky11811 发表于 2011-8-31 13:56
这里不存在通用性的问题,SkyNode也用的是gpu gems的shader,这里存在性能的差异。
如果考虑地球本身的话会 ...

我也是用这个shader为地球加入散射之后,就一片漆黑了。之前因为看到其他人没用SkyNode实现的大气层非常柔和,应该就是shader也应用到了地球的原因,所以请问楼主我该怎么修改SkyNode,才能让shader也应用到地球?

该用户从未签到

发表于 2012-11-19 20:40:04 | 显示全部楼层
现在有解决方法了吗?

该用户从未签到

发表于 2012-11-19 20:42:40 | 显示全部楼层
GPU Gems确实漂亮一点
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表