Material.cpp 7.9 KB

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