osgEarth 2.1.1
Public Member Functions | Protected Types | Protected Member Functions | Protected Attributes

osgEarth::VirtualProgram Class Reference

List of all members.

Public Member Functions

void setFunction (const std::string &name, const std::string &source, ShaderComp::FunctionLocation loc, float priority=1.0f)
 VirtualProgram (unsigned int mask=0xFFFFFFFFUL)
 VirtualProgram (const VirtualProgram &VirtualProgram, const osg::CopyOp &copyop=osg::CopyOp::SHALLOW_COPY)
 META_StateAttribute (osgEarth, VirtualProgram, Type(PROGRAM)) virtual int compare(const StateAttribute &sa) const
virtual void apply (osg::State &state) const
osg::Shader * getShader (const std::string &shaderSemantic, osg::Shader::Type type)
osg::Shader * setShader (const std::string &shaderSemantic, osg::Shader *shader)
void removeShader (const std::string &shaderSemantic, osg::Shader::Type type)
void getFunctions (ShaderComp::FunctionLocationMap &out) const

Protected Types

typedef std::vector
< osg::ref_ptr< osg::Shader > > 
ShaderList
typedef std::pair< std::string,
osg::Shader::Type > 
ShaderSemantic
typedef std::map
< ShaderSemantic, osg::ref_ptr
< osg::Shader > > 
ShaderMap
typedef std::map< ShaderList,
osg::ref_ptr< osg::Program > > 
ProgramMap

Protected Member Functions

bool hasLocalFunctions () const
void refreshAccumulatedFunctions (const osg::State &state)

Protected Attributes

ProgramMap _programMap
ShaderMap _shaderMap
unsigned int _mask
ShaderComp::FunctionLocationMap _functions
ShaderComp::FunctionLocationMap _accumulatedFunctions
Threading::Mutex _functionsMutex

Detailed Description

VirtualProgram enables basic GLSL shader composition within osgEarth.

VirtualProgram has been adapted from the VirtualProgram shader composition work originally done by Wojciech Lewandowski and found in OSG's osgvirtualprogram example, and is used by permission.

Definition at line 105 of file ShaderComposition.


Member Typedef Documentation

typedef std::map< ShaderList, osg::ref_ptr<osg::Program> > osgEarth::VirtualProgram::ProgramMap [protected]

Definition at line 160 of file ShaderComposition.

typedef std::vector< osg::ref_ptr< osg::Shader > > osgEarth::VirtualProgram::ShaderList [protected]

Definition at line 157 of file ShaderComposition.

typedef std::map< ShaderSemantic, osg::ref_ptr<osg::Shader> > osgEarth::VirtualProgram::ShaderMap [protected]

Definition at line 159 of file ShaderComposition.

typedef std::pair< std::string, osg::Shader::Type > osgEarth::VirtualProgram::ShaderSemantic [protected]

Definition at line 158 of file ShaderComposition.


Constructor & Destructor Documentation

VirtualProgram::VirtualProgram ( unsigned int  mask = 0xFFFFFFFFUL)

Definition at line 65 of file ShaderComposition.cpp.

                                                  : 
_mask( mask ) 
{
    // because we sometimes update/change the attribute's members from within the apply() method
    this->setDataVariance( osg::Object::DYNAMIC );
}
VirtualProgram::VirtualProgram ( const VirtualProgram VirtualProgram,
const osg::CopyOp &  copyop = osg::CopyOp::SHALLOW_COPY 
)

Definition at line 72 of file ShaderComposition.cpp.

                                                                                  :
osg::Program( rhs, copyop ),
_shaderMap( rhs._shaderMap ),
_mask( rhs._mask ),
_functions( rhs._functions )
{
    //nop
}

Member Function Documentation

void VirtualProgram::apply ( osg::State &  state) const [virtual]

If enabled, activate our program in the GL pipeline, performing any rebuild operations that might be pending.

Definition at line 136 of file ShaderComposition.cpp.

{
    if( _shaderMap.empty() ) // Virtual Program works as normal Program
        return Program::apply( state );

    // first, find and collect all the VirtualProgram attributes:
    ShaderMap shaderMap;
    const StateHack::AttributeVec* av = StateHack::GetAttributeVec( state, this );
    if ( av )
    {
        for( StateHack::AttributeVec::const_iterator i = av->begin(); i != av->end(); ++i )
        {
            const osg::StateAttribute* sa = i->first;
            const VirtualProgram* vp = dynamic_cast< const VirtualProgram* >( sa );
            if( vp && ( vp->_mask & _mask ) )
            {
                for( ShaderMap::const_iterator i = vp->_shaderMap.begin(); i != vp->_shaderMap.end(); ++i )
                {
                    shaderMap[ i->first ] = i->second;
                }
            }
        }
    }

    // next add the local shader components to the map:
    for( ShaderMap::const_iterator i = _shaderMap.begin(); i != _shaderMap.end(); ++i )
        shaderMap[ i->first ] = i->second;

    if( shaderMap.size() )
    {
        // next, assemble a list of the shaders in the map so we can compare it:
        ShaderList sl;
        for( ShaderMap::iterator i = shaderMap.begin(); i != shaderMap.end(); ++i )
            sl.push_back( i->second );

        // see if there's already a program associated with this list:
        osg::Program* program = 0L;
        ProgramMap::iterator p = _programMap.find( sl );
        if ( p != _programMap.end() )
        {
            program = p->second.get();
        }
        else
        {
            ShaderFactory* sf = osgEarth::Registry::instance()->getShaderFactory();

            // build a new set of accumulated functions, to support the creation of main()
            const_cast<VirtualProgram*>(this)->refreshAccumulatedFunctions( state );
                
            osg::Shader* vert_main = sf->createVertexShaderMain( _accumulatedFunctions );
            const_cast<VirtualProgram*>(this)->setShader( "osgearth_vert_main", vert_main );
            shaderMap[ ShaderSemantic("osgearth_vert_main", osg::Shader::VERTEX) ] = vert_main;

            osg::Shader* frag_main = sf->createFragmentShaderMain( _accumulatedFunctions );
            const_cast<VirtualProgram*>(this)->setShader( "osgearth_frag_main", frag_main );
            shaderMap[ ShaderSemantic("osgearth_frag_main", osg::Shader::FRAGMENT) ] = frag_main;
            
            // rebuild the shader list now that we've changed the shader map.
            sl.clear();
            for( ShaderMap::iterator i = shaderMap.begin(); i != shaderMap.end(); ++i )
                sl.push_back( i->second );

            // Create a new program and add all our shaders.
            program = new osg::Program();

#if !MERGE_SHADERS
            for( ShaderList::iterator i = sl.begin(); i != sl.end(); ++i )
            {
                program->addShader( i->get() );
            }
#else
            std::string strFragment;
            std::string strVertex;
            std::string strGeometry;
            
            for( ShaderList::iterator i = sl.begin(); i != sl.end(); ++i )
            {
                if( i->get()->getType() == osg::Shader::FRAGMENT )
                    strFragment += i->get()->getShaderSource();
                else if ( i->get()->getType() == osg::Shader::VERTEX )
                    strVertex += i->get()->getShaderSource();
                else if ( i->get()->getType() == osg::Shader::GEOMETRY )
                    strGeometry += i->get()->getShaderSource();
            }

            if( strFragment.length() > 0 )
            {
                program->addShader( new osg::Shader( osg::Shader::FRAGMENT, strFragment ) );
            }

            if( strVertex.length() > 0  )
            {
                program->addShader( new osg::Shader( osg::Shader::VERTEX, strVertex ) );
            }

            if( strGeometry.length() > 0  )
            {
                program->addShader( new osg::Shader( osg::Shader::GEOMETRY, strGeometry ) );
            }
#endif
            // finally, cache the program so we only regenerate it when it changes.
            _programMap[ sl ] = program;
        }

        // finally, apply the program attribute.
        program->apply( state );
    }
    else
    {
        Program::apply( state );
    }
}

Here is the call graph for this function:

void VirtualProgram::getFunctions ( ShaderComp::FunctionLocationMap out) const

Definition at line 250 of file ShaderComposition.cpp.

{
    Threading::ScopedMutexLock lock( const_cast<VirtualProgram*>(this)->_functionsMutex );
    out = _functions;
}

Here is the caller graph for this function:

osg::Shader * VirtualProgram::getShader ( const std::string &  shaderSemantic,
osg::Shader::Type  type 
)

Definition at line 82 of file ShaderComposition.cpp.

{
    ShaderMap::key_type key( shaderSemantic, type );
    return _shaderMap[ key ].get();
}
bool osgEarth::VirtualProgram::hasLocalFunctions ( ) const [protected]
osgEarth::VirtualProgram::META_StateAttribute ( osgEarth  ,
VirtualProgram  ,
Type(PROGRAM)   
) const [inline]

return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.

Definition at line 130 of file ShaderComposition.

        {
           // check the types are equal and then create the rhs variable
           // used by the COMPARE_StateAttribute_Parameter macros below.
           COMPARE_StateAttribute_Types(VirtualProgram,sa)

           // compare each parameter in turn against the rhs.
           COMPARE_StateAttribute_Parameter(_mask)
           COMPARE_StateAttribute_Parameter(_shaderMap)
           return 0; // passed all the above comparison macros, must be equal.
        }
void VirtualProgram::refreshAccumulatedFunctions ( const osg::State &  state) [protected]

Definition at line 257 of file ShaderComposition.cpp.

{
    // This method searches the state's attribute stack and accumulates all 
    // the user functions (including those in this program).

    Threading::ScopedMutexLock lock( _functionsMutex );

    _accumulatedFunctions.clear();

    const StateHack::AttributeVec* av = StateHack::GetAttributeVec( state, this );
    for( StateHack::AttributeVec::const_iterator i = av->begin(); i != av->end(); ++i )
    {
        const osg::StateAttribute* sa = i->first;
        const VirtualProgram* vp = dynamic_cast< const VirtualProgram* >( sa );
        if( vp && vp != this && ( vp->_mask & _mask ) )
        {
            FunctionLocationMap rhs;
            vp->getFunctions( rhs );

            for( FunctionLocationMap::const_iterator j = rhs.begin(); j != rhs.end(); ++j )
            {
                const OrderedFunctionMap& ofm = j->second;
                for( OrderedFunctionMap::const_iterator k = ofm.begin(); k != ofm.end(); ++k )
                {
                    _accumulatedFunctions[j->first].insert( *k );
                }
            }
        }
    }

    // add the local ones too:
    for( FunctionLocationMap::const_iterator j = _functions.begin(); j != _functions.end(); ++j )
    {
        const OrderedFunctionMap& ofm = j->second;
        for( OrderedFunctionMap::const_iterator k = ofm.begin(); k != ofm.end(); ++k )
        {
            _accumulatedFunctions[j->first].insert( *k );
        }
    } 
}

Here is the call graph for this function:

Here is the caller graph for this function:

void VirtualProgram::removeShader ( const std::string &  shaderSemantic,
osg::Shader::Type  type 
)

Definition at line 127 of file ShaderComposition.cpp.

{
    _shaderMap.erase( ShaderMap::key_type( shaderSemantic, type ) );
}

Here is the caller graph for this function:

void VirtualProgram::setFunction ( const std::string &  name,
const std::string &  source,
ShaderComp::FunctionLocation  loc,
float  priority = 1.0f 
)

Adds a shader function to the program. Call this method (rather than setShader directly) to inject "user" functions into the shader program.

name: name of the function. This should be the actual function name in the shader source. source: the shader source code. location: Function location relative to the built-ins. priority: Lets you control the order of functions that you inject at the same location.

Definition at line 112 of file ShaderComposition.cpp.

{
    Threading::ScopedMutexLock lock( _functionsMutex );

    OrderedFunctionMap& ofm = _functions[location];
    ofm.insert( std::pair<float,std::string>( priority, functionName ) );
    osg::Shader::Type type = (int)location <= (int)LOCATION_VERTEX_POST_LIGHTING ?
        osg::Shader::VERTEX : osg::Shader::FRAGMENT;
    setShader( functionName, new osg::Shader( type, shaderSource ) );
}

Here is the call graph for this function:

Here is the caller graph for this function:

osg::Shader * VirtualProgram::setShader ( const std::string &  shaderSemantic,
osg::Shader *  shader 
)

Definition at line 89 of file ShaderComposition.cpp.

{
    if( shader->getType() == osg::Shader::UNDEFINED ) 
        return NULL;

    ShaderMap::key_type key( shaderSemantic, shader->getType() );

    osg::ref_ptr< osg::Shader >  shaderNew     = shader;
    osg::ref_ptr< osg::Shader >& shaderCurrent = _shaderMap[ key ];

    shaderNew->setName( shaderSemantic );

    if( shaderCurrent != shaderNew )
    {
       shaderCurrent = shaderNew;
    }

    //OE_NOTICE << shader->getShaderSource() << std::endl;

    return shaderCurrent.get();
}

Here is the caller graph for this function:


Member Data Documentation

Definition at line 167 of file ShaderComposition.

Definition at line 166 of file ShaderComposition.

Definition at line 169 of file ShaderComposition.

unsigned int osgEarth::VirtualProgram::_mask [protected]

Definition at line 164 of file ShaderComposition.

Definition at line 162 of file ShaderComposition.

Definition at line 163 of file ShaderComposition.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines