osgEarth 2.1.1
|
Public Member Functions | |
OceanSurfaceNode () | |
void | setOceanMaskImageLayer (const ImageLayer *layer) |
const ImageLayer * | getOceanMaskImageLayer () const |
float | getWaveHeight () const |
void | setWaveHeight (float waveHeight) |
float | getMaxRange () const |
void | setMaxRange (float maxRange) |
float | getPeriod () const |
void | setPeriod (float period) |
bool | getEnabled () const |
void | setEnabled (bool enabled) |
bool | getInvertMask () const |
void | setInvertMask (bool invertMask) |
void | setModulationColor (const osg::Vec4f &color) |
osg::Vec4f | getModulationColor () const |
float | getOceanAnimationPeriod () const |
void | setOceanAnimationPeriod (float oceanAnimationPeriod) |
osg::Image * | getOceanSurfaceImage () const |
void | setOceanSurfaceImage (osg::Image *image) |
float | getOceanSurfaceImageSizeRadians () const |
void | setOceanSurfaceImageSizeRadians (float size) |
void | setAdjustToMSL (bool adjustToMSL) |
bool | getAdjustToMSL () const |
virtual void | traverse (osg::NodeVisitor &nv) |
Private Member Functions | |
void | rebuildShaders () |
void | shadersDirty (bool value) |
Private Attributes | |
bool | _shadersDirty |
float | _maxRange |
UID | _oceanMaskLayerUID |
int | _oceanSurfaceTextureUnit |
bool | _oceanSurfaceTextureApplied |
float | _waveHeight |
float | _period |
bool | _enabled |
bool | _invertMask |
bool | _adjustToMSL |
osg::observer_ptr < osg::CoordinateSystemNode > | _csn |
optional< osg::Vec4f > | _oceanColor |
float | _oceanAnimationPeriod |
float | _oceanSurfaceImageSizeRadians |
osg::ref_ptr< osg::Image > | _oceanSurfaceImage |
osg::ref_ptr< osg::Texture3D > | _oceanSurfaceTexture |
osg::observer_ptr< const ImageLayer > | _maskLayer |
OceanSurfaceNode is a decorator node that animates the surface of the globe to simulate simple waves. Note: This only works with multitextured maps, not multipass.
Definition at line 38 of file OceanSurfaceNode.
OceanSurfaceNode::OceanSurfaceNode | ( | ) |
Creates a new OceanSurfaceNode
Definition at line 43 of file OceanSurfaceNode.cpp.
: _shadersDirty(false), _maxRange(800000), _oceanMaskLayerUID(-1), _oceanSurfaceTextureUnit(-1), _oceanSurfaceTextureApplied(false), _waveHeight(100), _period(1024), _enabled(true), _invertMask(false), _adjustToMSL(true), _oceanColor(osg::Vec4f(0,0,1,0)), _oceanAnimationPeriod(6.0), _oceanSurfaceImageSizeRadians(osg::PI/500.0) { rebuildShaders(); getOrCreateStateSet()->getOrCreateUniform("osgearth_OceanPeriod", osg::Uniform::FLOAT)->set(_period); getOrCreateStateSet()->getOrCreateUniform("osgearth_OceanAnimationPeriod", osg::Uniform::FLOAT)->set(_oceanAnimationPeriod); osg::Uniform* oceanHeightUniform = getOrCreateStateSet()->getOrCreateUniform("osgearth_OceanHeight", osg::Uniform::FLOAT); oceanHeightUniform->set( _waveHeight); oceanHeightUniform->setDataVariance( osg::Object::DYNAMIC); //Initialize the ocean surface texture _oceanSurfaceTexture = new osg::Texture3D(); _oceanSurfaceTexture->setWrap(osg::Texture::WRAP_S,osg::Texture::REPEAT); _oceanSurfaceTexture->setWrap(osg::Texture::WRAP_T,osg::Texture::REPEAT); _oceanSurfaceTexture->setWrap(osg::Texture::WRAP_R,osg::Texture::REPEAT); _oceanSurfaceTexture->setFilter(osg::Texture3D::MIN_FILTER,osg::Texture3D::LINEAR); _oceanSurfaceTexture->setFilter(osg::Texture3D::MAG_FILTER,osg::Texture3D::LINEAR); }
bool OceanSurfaceNode::getAdjustToMSL | ( | ) | const |
Gets whether or not to adjust the height of the ocean to always be at MSL 0 and ignore the current vert height
Definition at line 97 of file OceanSurfaceNode.cpp.
{ return _adjustToMSL; }
bool OceanSurfaceNode::getEnabled | ( | ) | const |
Gets whether the ocean effect is enabled
Definition at line 181 of file OceanSurfaceNode.cpp.
{ return _enabled; }
bool OceanSurfaceNode::getInvertMask | ( | ) | const |
Gets whether to invert the mask ocean mask.
Definition at line 197 of file OceanSurfaceNode.cpp.
{ return _invertMask; }
float OceanSurfaceNode::getMaxRange | ( | ) | const |
Gets the range at which the effect starts to show.
Definition at line 148 of file OceanSurfaceNode.cpp.
{ return _maxRange; }
osg::Vec4f OceanSurfaceNode::getModulationColor | ( | ) | const |
Definition at line 223 of file OceanSurfaceNode.cpp.
{ return _oceanColor.value(); }
float OceanSurfaceNode::getOceanAnimationPeriod | ( | ) | const |
Gets the period of the ocean animation effect in seconds
Definition at line 229 of file OceanSurfaceNode.cpp.
{ return _oceanAnimationPeriod; }
const ImageLayer* osgEarth::Util::OceanSurfaceNode::getOceanMaskImageLayer | ( | ) | const [inline] |
Gets the image layer being used as an ocean mask.
Definition at line 54 of file OceanSurfaceNode.
{ return _maskLayer.get(); }
osg::Image * OceanSurfaceNode::getOceanSurfaceImage | ( | ) | const |
Gets the ocean surface image to the given 3D image.
Definition at line 113 of file OceanSurfaceNode.cpp.
{ return _oceanSurfaceImage.get(); }
float OceanSurfaceNode::getOceanSurfaceImageSizeRadians | ( | ) | const |
Gets the size of the ocean surface image in radians
Definition at line 246 of file OceanSurfaceNode.cpp.
{ return _oceanSurfaceImageSizeRadians; }
float OceanSurfaceNode::getPeriod | ( | ) | const |
Gets the period of the wave
Definition at line 164 of file OceanSurfaceNode.cpp.
{ return _period; }
float OceanSurfaceNode::getWaveHeight | ( | ) | const |
void OceanSurfaceNode::rebuildShaders | ( | ) | [private] |
Definition at line 276 of file OceanSurfaceNode.cpp.
{ // need the terrain engine so we can get at the compositor. TerrainEngineNode* engine = osgEarth::findTopMostNodeOfType<TerrainEngineNode>( this ); if ( !engine ) { OE_DEBUG << LC << "No terrain engine found in the map node; abort" << std::endl; return; } // access the compositor because we are going to be sampling map layers. TextureCompositor* comp = engine->getTextureCompositor(); if ( !comp ) { OE_INFO << LC << "No texture compositor found in the terrain engine; abort" << std::endl; return; } // reserve a texture unit for the surface texture (if we haven't already) if ( !_oceanSurfaceTextureApplied && _oceanSurfaceTextureUnit < 0 && _oceanSurfaceTexture.valid() ) { if ( comp->reserveTextureImageUnit( _oceanSurfaceTextureUnit ) ) { getOrCreateStateSet()->setTextureAttributeAndModes( _oceanSurfaceTextureUnit, _oceanSurfaceTexture.get(), osg::StateAttribute::ON); _oceanSurfaceTextureApplied = true; } else { OE_WARN << LC << "Sorry, failed to allocate a texture image unit for the surface texture." << std::endl; } } // create a VP to store our custom shader components. osgEarth::VirtualProgram* vp = new osgEarth::VirtualProgram(); getOrCreateStateSet()->setAttributeAndModes( vp, osg::StateAttribute::ON ); // if the ocean is disabled, just return without injecting any shaders. if ( !_enabled ) return; // build the sampler function if necessary osg::ref_ptr<const ImageLayer> safeMaskLayer = _maskLayer.get(); osg::Shader* maskSampler = 0L; if ( safeMaskLayer.valid() ) { maskSampler = comp->createSamplerFunction( safeMaskLayer->getUID(), MASK_SAMPLER_FUNC, osg::Shader::VERTEX ); if ( maskSampler ) vp->setShader( MASK_SAMPLER_FUNC, maskSampler ); } // make the helper functions. { std::stringstream buf; buf << "vec3 xyz_to_lat_lon_height(in vec3 xyz) \n" << "{ \n" << " float X = xyz.x;\n" << " float Y = xyz.y;\n" << " float Z = xyz.z;\n" << " float _radiusEquator = 6378137.0;\n" << " float _radiusPolar = 6356752.3142;\n" << " float flattening = (_radiusEquator-_radiusPolar)/_radiusEquator;\n" << " float _eccentricitySquared = 2.0*flattening - flattening*flattening;\n" << " float p = sqrt(X*X + Y*Y);\n" << " float theta = atan(Z*_radiusEquator , (p*_radiusPolar));\n" << " float eDashSquared = (_radiusEquator*_radiusEquator - _radiusPolar*_radiusPolar)/(_radiusPolar*_radiusPolar);\n" << " float sin_theta = sin(theta);\n" << " float cos_theta = cos(theta);\n" << " float latitude = atan( (Z + eDashSquared*_radiusPolar*sin_theta*sin_theta*sin_theta), (p - _eccentricitySquared*_radiusEquator*cos_theta*cos_theta*cos_theta) );\n" << " float longitude = atan(Y,X);\n" << " float sin_latitude = sin(latitude);\n" << " float N = _radiusEquator / sqrt( 1.0 - _eccentricitySquared*sin_latitude*sin_latitude);\n" << " float height = p/cos(latitude) - N;\n" << " return vec3(longitude, latitude, height);\n" << "} \n" << "\n"; std::string str = buf.str(); vp->setShader( "xyz_to_lat_lon_height", new osg::Shader(osg::Shader::VERTEX, str) ); } // next make the vertex shader function that will morph the ocean verts and prepare // the texture coordinates for the surface effects. { std::stringstream buf; buf << std::fixed; buf << "uniform float osg_SimulationTime; \n" << "uniform mat4 osg_ViewMatrixInverse;\n" << "uniform mat4 osg_ViewMatrix;\n" << "uniform float osgearth_OceanHeight;\n" << "uniform float osgearth_OceanPeriod;\n" << "uniform float osgearth_OceanAnimationPeriod;\n" << "varying float osgearth_OceanAlpha;\n" << "varying float osgearth_CameraRange; \n" << "vec3 xyz_to_lat_lon_height(in vec3 xyz); \n"; if ( _oceanSurfaceTextureApplied ) { buf << "varying vec3 osgearth_oceanSurfaceTexCoord; \n"; } if ( maskSampler ) { buf << "vec4 " << MASK_SAMPLER_FUNC << "(); \n"; } buf << "void osgearth_ocean_morphSurface() \n" << "{ \n" << " mat4 modelMatrix = osg_ViewMatrixInverse * gl_ModelViewMatrix; \n" << " vec4 vert = modelMatrix * gl_Vertex; \n" << " vec3 vert3 = vec3(vert.x, vert.y, vert.z); \n" << " vec3 latlon = xyz_to_lat_lon_height(vert3); \n" << " osgearth_OceanAlpha = 1.0; \n"; if ( maskSampler ) { buf << " osgearth_OceanAlpha = 1.0 - (" << MASK_SAMPLER_FUNC << "()).a; \n"; } if ( _invertMask ) buf << " osgearth_OceanAlpha = 1.0 - osgearth_OceanAlpha; \n"; buf << " if ( osgearth_CameraRange <= " << _maxRange << " ) \n" << " { \n" << " float s = mix(1.0, 0.0, osgearth_CameraRange / " << _maxRange << "); \n" //Invert so it's between 0 and 1 << " osgearth_OceanAlpha *= s; \n" << " } \n" << " else \n" << " { \n" << " osgearth_OceanAlpha = 0.0; \n" << " } \n" << " if (osgearth_OceanAlpha > 0.0) \n" << " { \n" << " float PI_2 = 3.14158 * 2.0; \n" << " float period = PI_2/osgearth_OceanPeriod; \n" << " float half_period = period / 2.0; \n" << " vec3 n = normalize(vert3);\n" << " float theta = (mod(latlon.x, period) / period) * PI_2; \n" << " float phi = (mod(latlon.y, half_period) / half_period) * PI_2; \n" << " float phase1 = osg_SimulationTime * 2.0; \n" << " float phase2 = osg_SimulationTime * 4.0; \n" << " float waveHeight = (osgearth_OceanAlpha) * osgearth_OceanHeight; \n" << " float scale1 = sin(theta + phase1) * waveHeight; \n" << " float scale2 = cos(phi + phase2) * waveHeight; \n" << " float scale3 = sin(theta + phase2) * cos(phi + phase1) * waveHeight * 1.6; \n" << " float scale = (scale1 + scale2 + scale3)/3.0; \n"; // flatten verts to MSL: if ( _adjustToMSL ) { buf << " vec3 offset = n * -latlon.z; \n" << " vert += vec4( offset.xyz, 0 ); \n"; } // apply the save scale: buf << " n = n * scale; \n" << " vert += vec4(n.x, n.y,n.z,0); \n" << " vert = osg_ViewMatrix * vert; \n" << " gl_Position = gl_ProjectionMatrix * vert; \n" << " }\n"; // set up the coords for the surface texture: if ( _oceanSurfaceTextureApplied ) { buf << " osgearth_oceanSurfaceTexCoord.x = latlon.x / " << _oceanSurfaceImageSizeRadians << "; \n" << " osgearth_oceanSurfaceTexCoord.y = latlon.y / " << _oceanSurfaceImageSizeRadians << "; \n" << " osgearth_oceanSurfaceTexCoord.z = fract(osg_SimulationTime/osgearth_OceanAnimationPeriod); \n"; } buf << "}\n"; // add as a custom user function in the shader composition: std::string vertSource = buf.str(); vp->setFunction( "osgearth_ocean_morphSurface", vertSource, osgEarth::ShaderComp::LOCATION_VERTEX_PRE_TEXTURING ); } // now we need a fragment function that will apply the ocean surface texture. if ( _oceanSurfaceTextureApplied ) { getOrCreateStateSet()->getOrCreateUniform( "osgearth_oceanSurfaceTex", osg::Uniform::SAMPLER_3D )->set( _oceanSurfaceTextureUnit ); std::stringstream buf; buf << "uniform sampler3D osgearth_oceanSurfaceTex; \n" << "varying vec3 osgearth_oceanSurfaceTexCoord; \n" << "varying float osgearth_OceanAlpha; \n" << "void osgearth_ocean_applySurfaceTex( inout vec4 color ) \n" << "{ \n" << " vec4 texel = texture3D(osgearth_oceanSurfaceTex, osgearth_oceanSurfaceTexCoord); \n" << " color = vec4( mix( color.rgb, texel.rgb, texel.a * osgearth_OceanAlpha ), color.a); \n" << "} \n"; std::string str = buf.str(); vp->setFunction( "osgearth_ocean_applySurfaceTex", str, osgEarth::ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING ); } }
void OceanSurfaceNode::setAdjustToMSL | ( | bool | adjustToMSL | ) |
Sets whether or not to adjust the height of the ocean to always be at MSL 0 and ignore the current vert height
Definition at line 103 of file OceanSurfaceNode.cpp.
{ if (_adjustToMSL != adjustToMSL) { _adjustToMSL = adjustToMSL; shadersDirty( true ); } }
void OceanSurfaceNode::setEnabled | ( | bool | enabled | ) |
Sets whether the ocean effect is enabled
Definition at line 187 of file OceanSurfaceNode.cpp.
{ if (_enabled != enabled) { _enabled = enabled; shadersDirty(true); } }
void OceanSurfaceNode::setInvertMask | ( | bool | invertMask | ) |
Sets whether to invert the mask ocean mask. Normally, transparant areas are considered ocean. When inverted, transparent areas are considered land.
Definition at line 203 of file OceanSurfaceNode.cpp.
{ if (_invertMask != invertMask) { _invertMask = invertMask; shadersDirty( true ); } }
void OceanSurfaceNode::setMaxRange | ( | float | maxRange | ) |
Sets the max range at which the effect starts to show
Definition at line 154 of file OceanSurfaceNode.cpp.
{ if (_maxRange != maxRange) { _maxRange = maxRange; shadersDirty(true); } }
void OceanSurfaceNode::setModulationColor | ( | const osg::Vec4f & | color | ) |
Sets an optional ocean color. The ocean will take on this color based on the alpha values in the masking texture.
Definition at line 213 of file OceanSurfaceNode.cpp.
{ if ( !_oceanColor.isSetTo( color ) ) { _oceanColor = color; shadersDirty( true ); } }
void OceanSurfaceNode::setOceanAnimationPeriod | ( | float | oceanAnimationPeriod | ) |
Sets the period of the ocean animation effect in seconds
Definition at line 235 of file OceanSurfaceNode.cpp.
{ if (_oceanAnimationPeriod != oceanAnimationPeriod) { _oceanAnimationPeriod = oceanAnimationPeriod; getOrCreateStateSet()->getOrCreateUniform("osgearth_OceanAnimationPeriod", osg::Uniform::FLOAT)->set(oceanAnimationPeriod); //TODO: consider rebuildShaders() instead.. } }
void OceanSurfaceNode::setOceanMaskImageLayer | ( | const ImageLayer * | layer | ) |
Sets the image layer to use as an ocean mask.
Definition at line 87 of file OceanSurfaceNode.cpp.
{ if ( _maskLayer.get() != layer ) { _maskLayer = layer; shadersDirty(true); } }
void OceanSurfaceNode::setOceanSurfaceImage | ( | osg::Image * | image | ) |
Sets the ocean surface image to the given 3D image.
Definition at line 119 of file OceanSurfaceNode.cpp.
{ if (_oceanSurfaceImage.get() != image) { _oceanSurfaceImage = image; _oceanSurfaceTexture->setImage( _oceanSurfaceImage.get() ); shadersDirty( true ); } }
void OceanSurfaceNode::setOceanSurfaceImageSizeRadians | ( | float | size | ) |
Sets the size of the ocean surface image in radians
Definition at line 252 of file OceanSurfaceNode.cpp.
{ if (_oceanSurfaceImageSizeRadians != size) { _oceanSurfaceImageSizeRadians = size; shadersDirty( true ); } }
void OceanSurfaceNode::setPeriod | ( | float | period | ) |
Sets the period of the wave
Definition at line 170 of file OceanSurfaceNode.cpp.
void OceanSurfaceNode::setWaveHeight | ( | float | waveHeight | ) |
Sets the wave height
Definition at line 137 of file OceanSurfaceNode.cpp.
{ if (_waveHeight != waveHeight) { _waveHeight = waveHeight; getOrCreateStateSet()->getOrCreateUniform("osgearth_OceanHeight", osg::Uniform::FLOAT)->set(_waveHeight); //TODO: consider rebuildShaders() instead.. } }
void OceanSurfaceNode::shadersDirty | ( | bool | value | ) | [private] |
Definition at line 77 of file OceanSurfaceNode.cpp.
{ if ( _shadersDirty != value ) { _shadersDirty = value; ADJUST_UPDATE_TRAV_COUNT( this, _shadersDirty ? 1 : -1 ); } }
void OceanSurfaceNode::traverse | ( | osg::NodeVisitor & | nv | ) | [virtual] |
Definition at line 262 of file OceanSurfaceNode.cpp.
{ if ( _shadersDirty && nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR ) { rebuildShaders(); shadersDirty( false ); } osg::Group::traverse( nv ); }
bool osgEarth::Util::OceanSurfaceNode::_adjustToMSL [private] |
Definition at line 172 of file OceanSurfaceNode.
osg::observer_ptr<osg::CoordinateSystemNode> osgEarth::Util::OceanSurfaceNode::_csn [private] |
Definition at line 173 of file OceanSurfaceNode.
bool osgEarth::Util::OceanSurfaceNode::_enabled [private] |
Definition at line 170 of file OceanSurfaceNode.
bool osgEarth::Util::OceanSurfaceNode::_invertMask [private] |
Definition at line 171 of file OceanSurfaceNode.
osg::observer_ptr< const ImageLayer > osgEarth::Util::OceanSurfaceNode::_maskLayer [private] |
Definition at line 179 of file OceanSurfaceNode.
float osgEarth::Util::OceanSurfaceNode::_maxRange [private] |
Definition at line 164 of file OceanSurfaceNode.
float osgEarth::Util::OceanSurfaceNode::_oceanAnimationPeriod [private] |
Definition at line 175 of file OceanSurfaceNode.
optional<osg::Vec4f> osgEarth::Util::OceanSurfaceNode::_oceanColor [private] |
Definition at line 174 of file OceanSurfaceNode.
Definition at line 165 of file OceanSurfaceNode.
osg::ref_ptr< osg::Image > osgEarth::Util::OceanSurfaceNode::_oceanSurfaceImage [private] |
Definition at line 177 of file OceanSurfaceNode.
float osgEarth::Util::OceanSurfaceNode::_oceanSurfaceImageSizeRadians [private] |
Definition at line 176 of file OceanSurfaceNode.
osg::ref_ptr< osg::Texture3D > osgEarth::Util::OceanSurfaceNode::_oceanSurfaceTexture [private] |
Definition at line 178 of file OceanSurfaceNode.
Definition at line 167 of file OceanSurfaceNode.
Definition at line 166 of file OceanSurfaceNode.
float osgEarth::Util::OceanSurfaceNode::_period [private] |
Definition at line 169 of file OceanSurfaceNode.
bool osgEarth::Util::OceanSurfaceNode::_shadersDirty [private] |
Definition at line 162 of file OceanSurfaceNode.
float osgEarth::Util::OceanSurfaceNode::_waveHeight [private] |
Definition at line 168 of file OceanSurfaceNode.