Exemplo n.º 1
0
void CDebugShadersDlg::OnListRefresh()
{
    const auto& s = AfxGetAppSettings();
    CString path;
    int oldSel = m_Shaders.GetCurSel();
    if (oldSel != CB_ERR) {
        m_Shaders.GetLBText(oldSel, path);
        ASSERT(!path.IsEmpty());
    }
    ShaderList list = ShaderList::GetDefaultShaders();
    list.insert(list.cend(), s.m_ShadersExtraList.cbegin(), s.m_ShadersExtraList.cend());
    m_Shaders.ResetContent();
    for (const auto& shader : list) {
        ASSERT(!shader.filePath.IsEmpty());
        int idx = m_Shaders.InsertString(-1, shader.filePath);
        if (idx >= 0) {
            if (shader.filePath == path) {
                VERIFY(m_Shaders.SetCurSel(idx) != CB_ERR);
            }
        } else {
            ASSERT(FALSE);
        }
    }
    if (m_Shaders.GetCurSel() == CB_ERR) {
        if (m_Shaders.GetCount() > 0) {
            VERIFY(m_Shaders.SetCurSel(0) != CB_ERR);
        }
        UpdateNotifierState();
        VERIFY(PostMessage(WM_APP_RECOMPILE_SHADER));
    }
}
Exemplo n.º 2
0
void
VirtualProgram::apply( osg::State & state ) const
{
    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 );
    }
}
Exemplo n.º 3
0
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

}
Exemplo n.º 4
0
void Manager::_parseMaterial(Material* material, io::IReader* stream)
{
    static std::map<std::string, bool RenderState::*>   stateCommands;
    static std::map<std::string, DepthFn>               depthFnLiterals;
    static std::map<std::string, BlendFn::Factor>       blendFnLiterals;

    if (stateCommands.empty())
    {
        stateCommands["depthtest"]     = &RenderState::depthTest;
        stateCommands["depthwrite"]    = &RenderState::depthWrite;
        stateCommands["alphatest"]     = &RenderState::alphaTest;
        stateCommands["blend"]         = &RenderState::blend;
        stateCommands["cullface"]      = &RenderState::cullFace;
        stateCommands["polygonoffset"] = &RenderState::polygonOffset;
    }

    if (depthFnLiterals.empty())
    {
        depthFnLiterals["never"]    = DepthFn::Never;
        depthFnLiterals["less"]     = DepthFn::Less;
        depthFnLiterals["equal"]    = DepthFn::Equal;
        depthFnLiterals["lequal"]   = DepthFn::LEqual;
        depthFnLiterals["greater"]  = DepthFn::Greater;
        depthFnLiterals["notequal"] = DepthFn::NotEqual;
        depthFnLiterals["gequal"]   = DepthFn::GEqual;
        depthFnLiterals["always"]   = DepthFn::Always;
    }

    if (blendFnLiterals.empty())
    {
        blendFnLiterals["one"]               = BlendFn::One;
        blendFnLiterals["zero"]              = BlendFn::Zero;
        blendFnLiterals["srccolor"]          = BlendFn::SrcColor;
        blendFnLiterals["oneminussrccolor"]  = BlendFn::OneMinusSrcColor;
        blendFnLiterals["srcalpha"]          = BlendFn::SrcAlpha;
        blendFnLiterals["oneminussrcalpha"]  = BlendFn::OneMinusSrcAlpha;
        blendFnLiterals["dstalpha"]          = BlendFn::DstAlpha;
        blendFnLiterals["oneminusdstalpha"]  = BlendFn::OneMinusDstAlpha;
        blendFnLiterals["dstcolor"]          = BlendFn::DstColor;
        blendFnLiterals["oneminusdstcolor"]  = BlendFn::OneMinusDstColor;
        blendFnLiterals["srcalphasaturate"]  = BlendFn::SrcAlphaSaturate;
    }

    enum {States, Textures, Shaders} mode = States;

    RenderState renderState;
    ShaderList shaders;
    std::vector<std::string> textures;

    char key[64] = {}, value[256] = {};
    int tokens = 0;

    for (io::LineParser parser(stream); parser.readLine();)
    {
        if (!parser.indent())
            mode = States;

        switch (mode)
        {
        case States:
            tokens = std::sscanf(parser.line().c_str(), "%63[^:] : %255s", key, value);
            if (tokens == 2)
            {
                for (auto str = key; *str; ++str)
                    *str = ::tolower(*str);

                for (auto str = value; *str; ++str)
                    *str = ::tolower(*str);

                auto stateCmdIt = stateCommands.find(key);
                if (stateCmdIt != stateCommands.end())
                    renderState.*stateCmdIt->second = strcmp(value, "true") == 0;

                else if (strcmp(key, "depthfunc") == 0)
                {
                    auto depthFnIt = depthFnLiterals.find(value);
                    if (depthFnIt != depthFnLiterals.end())
                        renderState.depthFunc = depthFnIt->second;
                }
                else if (strcmp(key, "blendfunc") == 0)
                {
                    char srcFactor[32], dstFactor[32];
                    if (std::sscanf("[ %31[^ 0xa0\t,] , %31[^ 0xa0\t\\] ]", srcFactor, dstFactor) == 2)
                    {
                        auto blendFnIt = blendFnLiterals.find(srcFactor);
                        if (blendFnIt != blendFnLiterals.end())
                            renderState.blendFunc.srcFactor = blendFnIt->second;

                        blendFnIt = blendFnLiterals.find(dstFactor);
                        if (blendFnIt != blendFnLiterals.end())
                            renderState.blendFunc.dstFactor = blendFnIt->second;
                    }
                }
                else if (strcmp(key, "passhint") == 0)
                    material->setPassHint(atoi(value));
            }
            else if (tokens == 1)
            {
                for (auto str = key; *str; ++str)
                    *str = ::tolower(*str);

                if (strcmp(key, "shaders") == 0)
                    mode = Shaders;

                else if (strcmp(key, "textures") == 0)
                    mode = Textures;
            }
            break;

        case Shaders:
            if (std::sscanf(parser.line().c_str(), " - %255s", value) == 1)
                shaders.add(getShader(value));
            break;

        case Textures:
            if (std::sscanf(parser.line().c_str(), " - %255s", value) == 1)
                textures.push_back(value);
            break;
        }
    }

    material->setRenderState(renderState);
    material->setShaders(shaders);

    auto maxTextures = std::min<std::size_t>(material->numTextures(), textures.size());

    for (std::size_t i = 0; i < maxTextures; ++i)
        material->setTexture(i, getTexture(textures[i]));
}