Material.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. #include "Material.h"
  2. #include "FileIO.h"
  3. #include "StringUtil.h"
  4. #include "edtaa3func.h"
  5. namespace gameplay
  6. {
  7. using std::string;
  8. using std::vector;
  9. using std::map;
  10. Material::Material(const std::string& id) :
  11. _parent(NULL), _id(id), _lit(false)
  12. {
  13. }
  14. Material::Material(const Material& c) :
  15. _parent(c._parent),
  16. _id(c._id), _lit(false),
  17. _vertexShader(c._vertexShader),
  18. _fragmentShader(c._fragmentShader),
  19. _defines(c._defines),
  20. _uniforms(c._uniforms),
  21. _renderStates(c._renderStates)
  22. {
  23. for (vector<Sampler*>::const_iterator it = c._samplers.begin(); it != c._samplers.end(); ++it)
  24. {
  25. _samplers.push_back(new Sampler(**it));
  26. }
  27. }
  28. Material::~Material(void)
  29. {
  30. }
  31. const string& Material::getId() const
  32. {
  33. return _id;
  34. }
  35. void Material::setId(const char* id)
  36. {
  37. if (id)
  38. _id.assign(id);
  39. }
  40. Material* Material::getParent() const
  41. {
  42. return _parent;
  43. }
  44. void Material::setParent(Material* material)
  45. {
  46. if (material)
  47. _parent = material;
  48. }
  49. void Material::addDefine(const string& name)
  50. {
  51. if (!name.empty())
  52. {
  53. _defines[name] = string();
  54. }
  55. }
  56. bool Material::isDefined(const string& name) const
  57. {
  58. if (!name.empty())
  59. {
  60. return _defines.find(name) != _defines.end();
  61. }
  62. return false;
  63. }
  64. const char* Material::getUniform(const char* name) const
  65. {
  66. map<string, string>::const_iterator it = _uniforms.find(string(name));
  67. if (it != _uniforms.end())
  68. {
  69. return it->second.c_str();
  70. }
  71. return NULL;
  72. }
  73. void Material::setUniform(const string& name, const string& value)
  74. {
  75. _uniforms[name] = value;
  76. }
  77. const char* Material::getRenderState(const char* name) const
  78. {
  79. map<string, string>::const_iterator it = _renderStates.find(string(name));
  80. if (it != _renderStates.end())
  81. {
  82. return it->second.c_str();
  83. }
  84. return NULL;
  85. }
  86. void Material::setRenderState(const string& name, const string& value)
  87. {
  88. if (!name.empty())
  89. _renderStates[name] = value;
  90. }
  91. void Material::setVertexShader(const char* path)
  92. {
  93. if (path)
  94. _vertexShader.assign(path);
  95. }
  96. void Material::setFragmentShader(const char* path)
  97. {
  98. if (path)
  99. _fragmentShader.assign(path);
  100. }
  101. Sampler* Material::createSampler(const string& id)
  102. {
  103. Sampler* sampler = new Sampler(id.c_str());
  104. sampler->set("mipmap", "true");
  105. sampler->set("wrapS", CLAMP);
  106. sampler->set("wrapT", CLAMP);
  107. sampler->set(MIN_FILTER, LINEAR_MIPMAP_LINEAR);
  108. sampler->set(MAG_FILTER, LINEAR);
  109. _samplers.push_back(sampler);
  110. return sampler;
  111. }
  112. Sampler* Material::getSampler(const string& id) const
  113. {
  114. for (vector<Sampler*>::const_iterator it = _samplers.begin(); it != _samplers.end(); ++it)
  115. {
  116. Sampler* sampler = *it;
  117. if (sampler->getId() == id)
  118. {
  119. return sampler;
  120. }
  121. }
  122. return NULL;
  123. }
  124. bool Material::isTextured() const
  125. {
  126. return !_samplers.empty();
  127. }
  128. bool Material::isBumped() const
  129. {
  130. return getSampler("u_normalmapTexture") != NULL;
  131. }
  132. bool Material::isLit() const
  133. {
  134. return _lit;
  135. }
  136. bool Material::isSpecular() const
  137. {
  138. return isDefined(SPECULAR);
  139. }
  140. bool Material::isTextureRepeat() const
  141. {
  142. return isDefined(TEXTURE_REPEAT);
  143. }
  144. bool Material::isVertexColor() const
  145. {
  146. return isDefined("VERTEX_COLOR");
  147. }
  148. bool Material::isSkinned() const
  149. {
  150. return isDefined("SKINNING");
  151. }
  152. bool Material::isModulateAlpha() const
  153. {
  154. return isDefined("MODULATE_ALPHA");
  155. }
  156. void Material::setLit(bool value)
  157. {
  158. _lit = value;
  159. }
  160. void Material::writeMaterial(FILE* file)
  161. {
  162. fprintf(file, "material");
  163. if (getId().length() > 0)
  164. {
  165. fprintf(file, " %s", getId().c_str());
  166. }
  167. if (_parent)
  168. {
  169. assert(_parent->getId().length() > 0);
  170. fprintf(file, " : %s", _parent->getId().c_str());
  171. }
  172. fprintf(file, "\n");
  173. fprintf(file, "{\n");
  174. unsigned int indent = 1;
  175. writeUniforms(file, indent);
  176. writeSamplers(file, indent);
  177. writeRenderStates(file, indent);
  178. writeTechniqueAndPass(file, indent);
  179. --indent;
  180. writeIndent(indent, file);
  181. fprintf(file, "}\n");
  182. }
  183. void Material::writeDefines(FILE* file, unsigned int& indent)
  184. {
  185. writeIndent(indent, file);
  186. fprintf(file, "defines = ");
  187. for (map<string, string>::const_iterator it = _defines.begin(); it != _defines.end(); ++it)
  188. {
  189. if (it != _defines.begin())
  190. {
  191. fprintf(file, ";");
  192. }
  193. if (it->second.empty())
  194. {
  195. fprintf(file, "%s", it->first.c_str());
  196. }
  197. else
  198. {
  199. fprintf(file, "%s %s", it->first.c_str(), it->second.c_str());
  200. }
  201. }
  202. fprintf(file, "\n");
  203. }
  204. void Material::writeUniforms(FILE* file, unsigned int& indent)
  205. {
  206. for (map<string, string>::const_iterator it = _uniforms.begin(); it != _uniforms.end(); ++it)
  207. {
  208. writeIndent(indent, file);
  209. fprintf(file, "%s = %s\n", it->first.c_str(), it->second.c_str());
  210. }
  211. if (!_uniforms.empty())
  212. {
  213. writeIndent(indent, file);
  214. fprintf(file, "\n");
  215. }
  216. }
  217. void Material::writeSamplers(FILE* file, unsigned int& indent)
  218. {
  219. for (vector<Sampler*>::iterator it = _samplers.begin(); it != _samplers.end(); ++it)
  220. {
  221. Sampler* sampler = *it;
  222. Sampler* parentSampler = NULL;
  223. if (_parent)
  224. {
  225. parentSampler = _parent->getSampler(sampler->getId().c_str());
  226. }
  227. sampler->writeMaterial(file, indent, parentSampler);
  228. fprintf(file, "\n");
  229. }
  230. }
  231. void Material::writeRenderStates(FILE* file, unsigned int& indent)
  232. {
  233. if (_renderStates.empty())
  234. return;
  235. writeIndent(indent, file);
  236. fprintf(file, "renderState\n");
  237. writeIndent(indent, file);
  238. fprintf(file, "{\n");
  239. ++indent;
  240. for (map<string, string>::const_iterator it = _renderStates.begin(); it != _renderStates.end(); ++it)
  241. {
  242. writeIndent(indent, file);
  243. fprintf(file, "%s = %s\n", it->first.c_str(), it->second.c_str());
  244. }
  245. --indent;
  246. writeIndent(indent, file);
  247. fprintf(file, "}\n");
  248. writeIndent(indent, file);
  249. fprintf(file, "\n");
  250. }
  251. void Material::writeTechniqueAndPass(FILE* file, unsigned int& indent)
  252. {
  253. if (!_vertexShader.empty() || !_fragmentShader.empty() || !_defines.empty())
  254. {
  255. bool techniqueWritten = false;
  256. if (!_vertexShader.empty() ||
  257. !_fragmentShader.empty() ||
  258. (!_defines.empty() && (!_parent || _parent->_defines != _defines)))
  259. {
  260. writeTechniqueOpening(file, indent);
  261. techniqueWritten = true;
  262. }
  263. if (!_vertexShader.empty())
  264. {
  265. writeIndent(indent, file);
  266. fprintf(file, "%s = %s\n", "vertexShader", _vertexShader.c_str());
  267. }
  268. if (!_fragmentShader.empty())
  269. {
  270. writeIndent(indent, file);
  271. fprintf(file, "%s = %s\n", "fragmentShader", _fragmentShader.c_str());
  272. }
  273. if (!_defines.empty())
  274. {
  275. if (!_parent || _parent->_defines != _defines)
  276. {
  277. writeDefines(file, indent);
  278. }
  279. }
  280. if (techniqueWritten)
  281. {
  282. --indent;
  283. writeIndent(indent, file);
  284. fprintf(file, "}\n");
  285. --indent;
  286. writeIndent(indent, file);
  287. fprintf(file, "}\n");
  288. }
  289. }
  290. }
  291. void Material::writeTechniqueOpening(FILE* file, unsigned int& indent)
  292. {
  293. // write the techniques
  294. writeIndent(indent, file);
  295. fprintf(file, "technique\n");
  296. writeIndent(indent, file);
  297. fprintf(file, "{\n");
  298. ++indent;
  299. // write the passes
  300. writeIndent(indent, file);
  301. fprintf(file, "pass \n");
  302. writeIndent(indent, file);
  303. fprintf(file, "{\n");
  304. ++indent;
  305. }
  306. }