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)); } }
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 ); } }
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 }
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])); }