Exemplo n.º 1
0
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 );
    }
}
Exemplo n.º 2
0
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 );
    }
}