| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- #include "Material.h"
- #include "MaterialVariable.h"
- #include "Misc/PropertyTree.h"
- #include "MaterialShaderProgramCreator.h"
- #include "Core/App.h"
- #include "Core/Globals.h"
- #include "ShaderProgram.h"
- #include <boost/foreach.hpp>
- #include <boost/property_tree/ptree.hpp>
- #include <boost/property_tree/xml_parser.hpp>
- #include <boost/assign/list_of.hpp>
- #include <boost/functional/hash.hpp>
- #include <algorithm>
- //==============================================================================
- // Statics =
- //==============================================================================
- // Dont make idiotic mistakes
- #define TXT_AND_ENUM(x) \
- (#x, x)
- ConstCharPtrHashMap<GLenum>::Type Material::txtToBlengGlEnum =
- boost::assign::map_list_of
- TXT_AND_ENUM(GL_ZERO)
- TXT_AND_ENUM(GL_ONE)
- TXT_AND_ENUM(GL_DST_COLOR)
- TXT_AND_ENUM(GL_ONE_MINUS_DST_COLOR)
- TXT_AND_ENUM(GL_SRC_ALPHA)
- TXT_AND_ENUM(GL_ONE_MINUS_SRC_ALPHA)
- TXT_AND_ENUM(GL_DST_ALPHA)
- TXT_AND_ENUM(GL_ONE_MINUS_DST_ALPHA)
- TXT_AND_ENUM(GL_SRC_ALPHA_SATURATE)
- TXT_AND_ENUM(GL_SRC_COLOR)
- TXT_AND_ENUM(GL_ONE_MINUS_SRC_COLOR);
- //==============================================================================
- // Constructor =
- //==============================================================================
- Material::Material()
- {
- renderInBlendingStageFlag = false;
- blendingSfactor = GL_ONE;
- blendingDfactor = GL_ZERO;
- depthTesting = true;
- wireframe = false;
- castsShadowFlag = true;
- // Reset tha array
- std::fill(buildinsArr.begin(), buildinsArr.end(),
- static_cast<MaterialBuildinVariable*>(NULL));
- }
- //==============================================================================
- // Destructor =
- //==============================================================================
- Material::~Material()
- {}
- //==============================================================================
- // load =
- //==============================================================================
- void Material::load(const char* filename)
- {
- try
- {
- using namespace boost::property_tree;
- ptree pt;
- read_xml(filename, pt);
- parseMaterialTag(pt.get_child("material"));
- }
- catch(std::exception& e)
- {
- throw EXCEPTION("File \"" + filename + "\" failed: " + e.what());
- }
- }
- //==============================================================================
- // parseMaterialTag =
- //==============================================================================
- void Material::parseMaterialTag(const boost::property_tree::ptree& pt)
- {
- using namespace boost::property_tree;
- //
- // castsShadow
- //
- boost::optional<bool> shadow =
- PropertyTree::getBoolOptional(pt, "castsShadow");
- if(shadow)
- {
- castsShadowFlag = shadow.get();
- }
- //
- // renderInBlendingStage
- //
- boost::optional<bool> bs =
- PropertyTree::getBoolOptional(pt, "renderInBlendingStage");
- if(bs)
- {
- renderInBlendingStageFlag = bs.get();
- }
- //
- // blendFunctions
- //
- boost::optional<const ptree&> blendFuncsTree =
- pt.get_child_optional("blendFunctions");
- if(blendFuncsTree)
- {
- // sFactor
- {
- const std::string& tmp =
- blendFuncsTree.get().get<std::string>("sFactor");
- ConstCharPtrHashMap<GLenum>::Type::const_iterator it =
- txtToBlengGlEnum.find(tmp.c_str());
- if(it == txtToBlengGlEnum.end())
- {
- throw EXCEPTION("Incorrect blend enum: " + tmp);
- }
- blendingSfactor = it->second;
- }
- // dFactor
- {
- const std::string& tmp =
- blendFuncsTree.get().get<std::string>("dFactor");
- ConstCharPtrHashMap<GLenum>::Type::const_iterator it =
- txtToBlengGlEnum.find(tmp.c_str());
- if(it == txtToBlengGlEnum.end())
- {
- throw EXCEPTION("Incorrect blend enum: " + tmp);
- }
- blendingDfactor = it->second;
- }
- }
- //
- // depthTesting
- //
- boost::optional<bool> dp =
- PropertyTree::getBoolOptional(pt, "depthTesting");
- if(dp)
- {
- depthTesting = dp.get();
- }
- //
- // wireframe
- //
- boost::optional<bool> wf =
- PropertyTree::getBoolOptional(pt, "wireframe");
- if(wf)
- {
- wireframe = wf.get();
- }
- //
- // shaderProgram
- //
- MaterialShaderProgramCreator mspc(pt.get_child("shaderProgram"));
- for(uint i = 0; i < PASS_TYPES_NUM; i++)
- {
- std::string src = std::string("#define ") + passNames[i] + "\n" +
- mspc.getShaderProgramSource();
- std::string filename = createShaderProgSourceToCache(src);
- sProgs[i].loadRsrc(filename.c_str());
- }
- populateVariables(pt.get_child("shaderProgram.inputs"));
- }
- //==============================================================================
- // createShaderProgSourceToCache =
- //==============================================================================
- std::string Material::createShaderProgSourceToCache(const std::string& source)
- {
- // Create the hash
- boost::hash<std::string> stringHash;
- std::size_t h = stringHash(source);
- std::string prefix = boost::lexical_cast<std::string>(h);
- // Create path
- boost::filesystem::path newfPathName =
- AppSingleton::getInstance().getCachePath() / (prefix + ".glsl");
- // If file not exists write it
- if(!boost::filesystem::exists(newfPathName))
- {
- // If not create it
- std::ofstream f(newfPathName.string().c_str());
- if(!f.is_open())
- {
- throw EXCEPTION("Cannot open file for writing: " +
- newfPathName.string());
- }
- f.write(source.c_str(), source.length());
- f.close();
- }
- return newfPathName.string();
- }
- //==============================================================================
- // populateVariables =
- //==============================================================================
- void Material::populateVariables(const boost::property_tree::ptree& pt)
- {
- using namespace boost::property_tree;
- //
- // Get all names of all shader prog vars. Dont duplicate
- //
- std::map<std::string, GLenum> allVarNames;
- BOOST_FOREACH(const RsrcPtr<ShaderProgram>& sProg, sProgs)
- {
- BOOST_FOREACH(const ShaderProgramVariable& v, sProg->getVariables())
- {
- allVarNames[v.getName()] = v.getGlDataType();
- }
- }
- //
- // Iterate shader program variables
- //
- MaterialVariable::ShaderPrograms sProgs_;
- for(uint i = 0; i < PASS_TYPES_NUM; i++)
- {
- sProgs_[i] = sProgs[i].get();
- }
- std::map<std::string, GLenum>::const_iterator it = allVarNames.begin();
- for(; it != allVarNames.end(); it++)
- {
- const char* svName = it->first.c_str();
- GLenum dataType = it->second;
- // Buildin?
- if(MaterialBuildinVariable::isBuildin(svName))
- {
- MaterialBuildinVariable* v =
- new MaterialBuildinVariable(svName, sProgs_);
- mtlVars.push_back(v);
- buildinsArr[v->getMatchingVariable()] = v;
- }
- // User defined
- else
- {
- // Find the ptree that contains the value
- const ptree* valuePt = NULL;
- BOOST_FOREACH(const ptree::value_type& v, pt)
- {
- if(v.first != "input")
- {
- throw EXCEPTION("Expecting <input> and not: " + v.first);
- }
- if(v.second.get<std::string>("name") == svName)
- {
- valuePt = &v.second.get_child("value");
- break;
- }
- }
- if(valuePt == NULL)
- {
- throw EXCEPTION("Variable not buildin and not found: " +
- svName);
- }
- MaterialUserVariable* v = NULL;
- // Get the value
- switch(dataType)
- {
- // sampler2D
- case GL_SAMPLER_2D:
- v = new MaterialUserVariable(svName, sProgs_,
- valuePt->get<std::string>("sampler2D").c_str());
- break;
- // float
- case GL_FLOAT:
- v = new MaterialUserVariable(svName, sProgs_,
- PropertyTree::getFloat(*valuePt));
- break;
- // vec2
- case GL_FLOAT_VEC2:
- v = new MaterialUserVariable(svName, sProgs_,
- PropertyTree::getVec2(*valuePt));
- break;
- // vec3
- case GL_FLOAT_VEC3:
- v = new MaterialUserVariable(svName, sProgs_,
- PropertyTree::getVec3(*valuePt));
- break;
- // vec4
- case GL_FLOAT_VEC4:
- v = new MaterialUserVariable(svName, sProgs_,
- PropertyTree::getVec4(*valuePt));
- break;
- // default is error
- default:
- ASSERT(0);
- }
- mtlVars.push_back(v);
- userMtlVars.push_back(v);
- }
- } // end for all sprog vars
- }
|