void VirtualProgram::addShadersToProgram(const ShaderVector& shaders, const AttribBindingList& attribBindings, const AttribAliasMap& attribAliases, osg::Program* program ) { #ifdef USE_ATTRIB_ALIASES // apply any vertex attribute aliases. But first, sort them from longest to shortest // so we don't get any overlap and bad replacements. AttribAliasVector sortedAliases; sortedAliases.reserve( attribAliases.size() ); sortedAliases.insert(sortedAliases.begin(), attribAliases.begin(), attribAliases.end()); std::sort( sortedAliases.begin(), sortedAliases.end(), s_attribAliasSortFunc ); for( VirtualProgram::ShaderVector::const_iterator i = shaders.begin(); i != shaders.end(); ++i ) { osg::Shader* shader = i->get(); applyAttributeAliases( shader, sortedAliases ); } #endif // merge the shaders if necessary. if ( s_mergeShaders ) { unsigned vertVersion = 0; HeaderMap vertHeaders; std::stringstream vertBody; unsigned fragVersion = 0; HeaderMap fragHeaders; std::stringstream fragBody; // parse the shaders, combining header lines and finding the highest version: for( VirtualProgram::ShaderVector::const_iterator i = shaders.begin(); i != shaders.end(); ++i ) { osg::Shader* s = i->get(); if ( s->getType() == osg::Shader::VERTEX ) { parseShaderForMerging( s->getShaderSource(), vertVersion, vertHeaders, vertBody ); } else if ( s->getType() == osg::Shader::FRAGMENT ) { parseShaderForMerging( s->getShaderSource(), fragVersion, fragHeaders, fragBody ); } } // write out the merged shader code: std::string vertBodyText; vertBodyText = vertBody.str(); std::stringstream vertShaderBuf; if ( vertVersion > 0 ) vertShaderBuf << "#version " << vertVersion << "\n"; for( HeaderMap::const_iterator h = vertHeaders.begin(); h != vertHeaders.end(); ++h ) vertShaderBuf << h->second << "\n"; vertShaderBuf << vertBodyText << "\n"; vertBodyText = vertShaderBuf.str(); std::string fragBodyText; fragBodyText = fragBody.str(); std::stringstream fragShaderBuf; if ( fragVersion > 0 ) fragShaderBuf << "#version " << fragVersion << "\n"; for( HeaderMap::const_iterator h = fragHeaders.begin(); h != fragHeaders.end(); ++h ) fragShaderBuf << h->second << "\n"; fragShaderBuf << fragBodyText << "\n"; fragBodyText = fragShaderBuf.str(); // add them to the program. program->addShader( new osg::Shader(osg::Shader::VERTEX, vertBodyText) ); program->addShader( new osg::Shader(osg::Shader::FRAGMENT, fragBodyText) ); if ( s_dumpShaders ) { OE_NOTICE << LC << "\nMERGED VERTEX SHADER: \n\n" << vertBodyText << "\n\n" << "MERGED FRAGMENT SHADER: \n\n" << fragBodyText << "\n" << std::endl; } } else { for( VirtualProgram::ShaderVector::const_iterator i = shaders.begin(); i != shaders.end(); ++i ) { program->addShader( i->get() ); if ( s_dumpShaders ) OE_NOTICE << LC << "SHADER " << i->get()->getName() << ":\n" << i->get()->getShaderSource() << "\n" << std::endl; } } // add the attribute bindings for( VirtualProgram::AttribBindingList::const_iterator abl = attribBindings.begin(); abl != attribBindings.end(); ++abl ) { program->addBindAttribLocation( abl->first, abl->second ); } }
void VirtualProgram::addShadersToProgram(const ShaderVector& shaders, const AttribBindingList& attribBindings, osg::Program* program ) { if ( s_mergeShaders ) { unsigned vertVersion = 0; HeaderMap vertHeaders; std::stringstream vertBody; unsigned fragVersion = 0; HeaderMap fragHeaders; std::stringstream fragBody; // parse the shaders, combining header lines and finding the highest version: for( VirtualProgram::ShaderVector::const_iterator i = shaders.begin(); i != shaders.end(); ++i ) { osg::Shader* s = i->get(); if ( s->getType() == osg::Shader::VERTEX ) { parseShaderForMerging( s->getShaderSource(), vertVersion, vertHeaders, vertBody ); } else if ( s->getType() == osg::Shader::FRAGMENT ) { parseShaderForMerging( s->getShaderSource(), fragVersion, fragHeaders, fragBody ); } } // write out the merged shader code: std::string vertBodyText; vertBodyText = vertBody.str(); std::stringstream vertShaderBuf; if ( vertVersion > 0 ) vertShaderBuf << "#version " << vertVersion << "\n"; for( HeaderMap::const_iterator h = vertHeaders.begin(); h != vertHeaders.end(); ++h ) vertShaderBuf << h->second << "\n"; vertShaderBuf << vertBodyText << "\n"; vertBodyText = vertShaderBuf.str(); std::string fragBodyText; fragBodyText = fragBody.str(); std::stringstream fragShaderBuf; if ( fragVersion > 0 ) fragShaderBuf << "#version " << fragVersion << "\n"; for( HeaderMap::const_iterator h = fragHeaders.begin(); h != fragHeaders.end(); ++h ) fragShaderBuf << h->second << "\n"; fragShaderBuf << fragBodyText << "\n"; fragBodyText = fragShaderBuf.str(); // add them to the program. program->addShader( new osg::Shader(osg::Shader::VERTEX, vertBodyText) ); program->addShader( new osg::Shader(osg::Shader::FRAGMENT, fragBodyText) ); if ( s_dumpShaders ) { OE_NOTICE << LC << "\nMERGED VERTEX SHADER: \n\n" << vertBodyText << "\n\n" << "MERGED FRAGMENT SHADER: \n\n" << fragBodyText << "\n" << std::endl; } } else { for( VirtualProgram::ShaderVector::const_iterator i = shaders.begin(); i != shaders.end(); ++i ) { program->addShader( i->get() ); if ( s_dumpShaders ) OE_NOTICE << LC << "SHADER " << i->get()->getName() << ":\n" << i->get()->getShaderSource() << "\n" << std::endl; } } // add the attribute bindings for( VirtualProgram::AttribBindingList::const_iterator abl = attribBindings.begin(); abl != attribBindings.end(); ++abl ) { program->addBindAttribLocation( abl->first, abl->second ); } }