void VirtualProgram::apply( osg::State & state ) const { if( _shaderMap.empty() ) // Virtual Program works as normal Program return Program::apply( state ); State::AttributeVec *av = &state.getAttributeVec(this); #if NOTIFICATION_MESSAGES std::ostream &os = osg::notify( osg::NOTICE ); os << "VirtualProgram cumulate Begin" << std::endl; #endif ShaderMap shaderMap; for( State::AttributeVec::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 ) ) { #if NOTIFICATION_MESSAGES if( vp->getName().empty() ) os << "VirtualProgram cumulate [ Unnamed VP ] apply" << std::endl; else os << "VirtualProgram cumulate ["<< vp->getName() << "] apply" << std::endl; #endif for( ShaderMap::const_iterator i = vp->_shaderMap.begin(); i != vp->_shaderMap.end(); ++i ) { shaderMap[ i->first ] = i->second; } } else { #if NOTIFICATION_MESSAGES os << "VirtualProgram cumulate ( not VP or mask not match ) ignored" << std::endl; #endif continue; // ignore osg::Programs } } for( ShaderMap::const_iterator i = this->_shaderMap.begin(); i != this->_shaderMap.end(); ++i ) shaderMap[ i->first ] = i->second; #if NOTIFICATION_MESSAGES os << "VirtualProgram cumulate End" << std::endl; #endif if( shaderMap.size() ) { ShaderList sl; for( ShaderMap::iterator i = shaderMap.begin(); i != shaderMap.end(); ++i ) sl.push_back( i->second ); osg::ref_ptr< osg::Program > & program = _programMap[ sl ]; if( !program.valid() ) { 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 NOTIFICATION_MESSAGES os << "====VirtualProgram merged Fragment Shader:" << std::endl << strFragment << "====" << std::endl; #endif } if( strVertex.length() > 0 ) { program->addShader( new osg::Shader( osg::Shader::VERTEX, strVertex ) ); #if NOTIFICATION_MESSAGES os << "VirtualProgram merged Vertex Shader:" << std::endl << strVertex << "====" << std::endl; #endif } if( strGeometry.length() > 0 ) { program->addShader( new osg::Shader( osg::Shader::GEOMETRY, strGeometry ) ); #if NOTIFICATION_MESSAGES os << "VirtualProgram merged Geometry Shader:" << std::endl << strGeometry << "====" << std::endl; #endif } #endif } state.applyAttribute( program.get() ); } else { Program::apply( state ); } #if NOTIFICATION_MESSAGES os << "VirtualProgram Apply" << std::endl; #endif }