PageRenderTime 61ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/Code/Libs/Amaterasu3D/System/Loaders/ShadersLoader.cpp

https://github.com/beltegeuse/Amaterasu3D
C++ | 523 lines | 448 code | 23 blank | 52 comment | 113 complexity | 8efac9d016d64ee035d29f2dc8cddd47 MD5 | raw file
  1. //==========================================================
  2. // Amaterasu3D - perceptual 3D engine
  3. //
  4. // Copyright (C) 2010-2011 Adrien Gruson
  5. //
  6. // This program is free software; you can redistribute it and/or
  7. // modify it under the terms of the GNU General Public License
  8. // as published by the Free Software Foundation; either version 2
  9. // of the License, or (at your option) any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program; if not, write to the Free Software
  18. // Foundation, Inc.,
  19. // 59 Temple Place - Suite 330,
  20. // Boston, MA 02111-1307, USA.
  21. //
  22. // E-mail : adrien.gruson@gmail.com
  23. //==========================================================
  24. #include "ShadersLoader.h"
  25. #include <tinyxml.h>
  26. #include <Logger/Logger.h>
  27. #include <System/MediaManager.h>
  28. #include <TinyXMLHelper.h>
  29. #include <System/SettingsManager.h>
  30. namespace ama3D
  31. {
  32. ShadersLoader::ShadersLoader()
  33. {
  34. }
  35. ShadersLoader::~ShadersLoader()
  36. {
  37. }
  38. void ShadersLoader::LoadMaterials(Shader* shader, TiXmlElement *root)
  39. {
  40. TiXmlElement *rootMaterial = root->FirstChildElement("Materials");
  41. if (!rootMaterial)
  42. {
  43. Logger::Log() << "[INFO] No Materials is available ... \n";
  44. return;
  45. }
  46. TiXmlElement *materialNode = rootMaterial->FirstChildElement("Material");
  47. while (materialNode)
  48. {
  49. std::string name;
  50. std::string type;
  51. TinyXMLGetAttributeValue<std::string>(materialNode, "name", &name);
  52. TinyXMLGetAttributeValue<std::string>(materialNode, "type", &type);
  53. if (type == "Diffuse")
  54. {
  55. shader->AddMaterialBinding(DIFFUSE_MATERIAL, name);
  56. }
  57. else if (type == "Specular")
  58. {
  59. shader->AddMaterialBinding(SPECULAR_MATERIAL, name);
  60. }
  61. else if (type == "Ambiant")
  62. {
  63. shader->AddMaterialBinding(AMBIANT_MATERIAL, name);
  64. }
  65. else if (type == "Emissive")
  66. {
  67. shader->AddMaterialBinding(EMISSION_MATERIAL, name);
  68. }
  69. else
  70. {
  71. throw CException("invalid material type");
  72. }
  73. materialNode = materialNode->NextSiblingElement();
  74. }
  75. }
  76. void ShadersLoader::LoadShaderFBO(Shader* shader, TiXmlElement *root)
  77. {
  78. TiXmlElement *rootFBO = root->FirstChildElement("OutputFrame");
  79. if (!rootFBO)
  80. {
  81. Logger::Log() << "[INFO] No FBO is available ... \n";
  82. return;
  83. }
  84. // Get the depth buffer type
  85. std::string typeDepthString;
  86. TinyXMLGetAttributeValue<std::string>(rootFBO, "depthType",
  87. &typeDepthString);
  88. Logger::Log() << " * Depth buffer type " << typeDepthString << "\n";
  89. FBODepthType typeDepth;
  90. if (typeDepthString == "None")
  91. {
  92. typeDepth = FBODEPTH_NONE;
  93. }
  94. else if (typeDepthString == "RenderTarget")
  95. {
  96. typeDepth = FBODEPTH_RENDERTARGET;
  97. }
  98. else if (typeDepthString == "Texture")
  99. {
  100. typeDepth = FBODEPTH_TEXTURE;
  101. }
  102. else
  103. throw CException("invalid buffer type");
  104. // Get the size of buffer
  105. std::string typeSize;
  106. int X = 0;
  107. int Y = 0;
  108. TinyXMLGetAttributeValue<std::string>(rootFBO, "size", &typeSize);
  109. if (typeSize == "Screen")
  110. {
  111. Math::TVector2I sizeScreen =
  112. CSettingsManager::Instance().GetSizeRenderingWindow();
  113. X = sizeScreen.x;
  114. Y = sizeScreen.y;
  115. }
  116. else if (typeSize == "HalfScreen")
  117. {
  118. Math::TVector2I sizeScreen =
  119. CSettingsManager::Instance().GetSizeRenderingWindow();
  120. X = sizeScreen.x / 2;
  121. Y = sizeScreen.y / 2;
  122. }
  123. else if (typeSize == "Custom")
  124. {
  125. TinyXMLGetAttributeValue<int>(rootFBO, "width", &X);
  126. TinyXMLGetAttributeValue<int>(rootFBO, "height", &Y);
  127. }
  128. else
  129. {
  130. throw CException("unknow type of size");
  131. }
  132. // Get all buffers
  133. std::map<std::string, FBOTextureBufferParam> buffers;
  134. Logger::Log() << " * Chargement des differents buffers .... \n";
  135. TiXmlElement *frameNode = rootFBO->FirstChildElement("Frame");
  136. shader->Begin();
  137. while (frameNode)
  138. {
  139. std::string name;
  140. std::string typeString;
  141. TinyXMLGetAttributeValue<std::string>(frameNode, "name", &name);
  142. TinyXMLGetAttributeValue<std::string>(frameNode, "type", &typeString);
  143. Logger::Log() << " * Create buffer : " << name << " ( "
  144. << typeString << " ) \n";
  145. FBOTextureBufferParam param;
  146. // Mipmapping parsing
  147. bool mipmapping = false;
  148. frameNode->Attribute("mipmapping", &mipmapping);
  149. if (mipmapping)
  150. {
  151. Logger::Log() << " * Mipmapping enable \n";
  152. param.GenerateMipMapping = true;
  153. param.MinFiltering = GL_LINEAR_MIPMAP_NEAREST;
  154. param.MaxFiltering = GL_LINEAR;
  155. }
  156. bool bilinear = false;
  157. frameNode->Attribute("bilinear", &bilinear);
  158. if(bilinear)
  159. {
  160. Logger::Log() << " * Bilinear enable \n";
  161. param.MinFiltering = GL_LINEAR;
  162. param.MaxFiltering = GL_LINEAR;
  163. }
  164. if(bilinear && mipmapping)
  165. throw CException("Impossible to activate Bilinear & mipmapping on the same texture");
  166. // Parse the Image format
  167. if (typeString == "RGBA")
  168. {
  169. // Nothing to do
  170. }
  171. else if (typeString == "RGB16")
  172. {
  173. param.InternalFormat = GL_RGB16F;
  174. param.ExternalFormat = GL_RGB;
  175. }
  176. else if (typeString == "RGB32")
  177. {
  178. param.InternalFormat = GL_RGB32F;
  179. param.ExternalFormat = GL_RGB;
  180. }
  181. else if (typeString == "RGBA16")
  182. {
  183. param.InternalFormat = GL_RGBA16F;
  184. param.ExternalFormat = GL_RGBA;
  185. }
  186. else if (typeString == "RGBA32")
  187. {
  188. param.InternalFormat = GL_RGBA32F;
  189. param.ExternalFormat = GL_RGBA;
  190. }
  191. else if (typeString == "L")
  192. {
  193. param.InternalFormat = GL_LUMINANCE32F_ARB;
  194. param.ExternalFormat = GL_LUMINANCE;
  195. }
  196. else
  197. throw CException("unknow buffer type");
  198. param.Attachment = glGetFragDataLocation(shader->GetProgramObject(),
  199. name.c_str());
  200. Logger::Log() << " * Attachment : " << param.Attachment
  201. << "\n";
  202. buffers[name] = param;
  203. frameNode = frameNode->NextSiblingElement("Frame");
  204. }
  205. shader->End();
  206. FBODepthBufferParam bufferDepth;
  207. FBO* fbo = new FBO(Math::TVector2I(X, Y), buffers, typeDepth, bufferDepth); // FIXME: Inversion des tailles ???
  208. shader->SetFBO(fbo);
  209. }
  210. void ShadersLoader::LoadShaderMatrix(Shader* shader, TiXmlElement *root)
  211. {
  212. TiXmlElement *rootMatrix = root->FirstChildElement("MatrixInput");
  213. if (!rootMatrix)
  214. {
  215. Logger::Log() << "[INFO] No Matrix is available ... \n";
  216. return;
  217. }
  218. TiXmlElement *matrixNode = rootMatrix->FirstChildElement("Matrix");
  219. Logger::Log() << "[INFO] Matrix : \n";
  220. while (matrixNode)
  221. {
  222. std::string nameMatrix;
  223. std::string typeMatrix;
  224. TinyXMLGetAttributeValue<std::string>(matrixNode, "name", &nameMatrix);
  225. TinyXMLGetAttributeValue<std::string>(matrixNode, "type", &typeMatrix);
  226. MatrixType type;
  227. //TODO: Faire une factory ???
  228. if (typeMatrix == "Model")
  229. {
  230. Logger::Log() << " * Matrix : " << nameMatrix << " (Model) \n";
  231. type = MODEL_MATRIX;
  232. }
  233. else if (typeMatrix == "Projection")
  234. {
  235. Logger::Log() << " * Matrix : " << nameMatrix
  236. << " (Projection) \n";
  237. type = PROJECTION_MATRIX;
  238. }
  239. else if (typeMatrix == "Normal")
  240. {
  241. Logger::Log() << " * Matrix : " << nameMatrix << " (Normal) \n";
  242. type = NORMAL_MATRIX;
  243. }
  244. else if (typeMatrix == "View")
  245. {
  246. Logger::Log() << " * Matrix : " << nameMatrix << " (View) \n";
  247. type = VIEW_MATRIX;
  248. }
  249. else
  250. {
  251. throw CException("Unknow Matrix : " + typeMatrix);
  252. }
  253. shader->AddMatrixBinding(type, nameMatrix);
  254. matrixNode = matrixNode->NextSiblingElement("Matrix");
  255. }
  256. }
  257. void ShadersLoader::LoadShaderAttributs(Shader* shader, TiXmlElement *root)
  258. {
  259. TiXmlElement *rootAttributs = root->FirstChildElement("Attributs");
  260. if (!rootAttributs)
  261. {
  262. Logger::Log() << "[INFO] No Attribut is available ... \n";
  263. return;
  264. }
  265. TiXmlElement *attributNode = rootAttributs->FirstChildElement("Attribut");
  266. Logger::Log() << "[INFO] Attribut : \n";
  267. while (attributNode)
  268. {
  269. std::string nameAttrib;
  270. std::string typeAttrib;
  271. TinyXMLGetAttributeValue<std::string>(attributNode, "name",
  272. &nameAttrib);
  273. TinyXMLGetAttributeValue<std::string>(attributNode, "type",
  274. &typeAttrib);
  275. int typeID;
  276. //TODO: Faire une factory ???
  277. if (typeAttrib == "Vertex")
  278. {
  279. Logger::Log() << " * Attribut : " << nameAttrib << " (Vertex) \n";
  280. typeID = VERTEX_ATTRIBUT;
  281. }
  282. else if (typeAttrib == "Color")
  283. {
  284. Logger::Log() << " * Attribut : " << nameAttrib << " (Color) \n";
  285. typeID = COLOR_ATTRIBUT;
  286. }
  287. else if (typeAttrib == "TexCoord")
  288. {
  289. Logger::Log() << " * Attribut : " << nameAttrib
  290. << " (TexCoord) \n";
  291. typeID = TEXCOORD_ATTRIBUT;
  292. }
  293. else if (typeAttrib == "Tangent")
  294. {
  295. Logger::Log() << " * Attribut : " << nameAttrib
  296. << " (Tangent) \n";
  297. typeID = TANGENT_ATTRIBUT;
  298. }
  299. else if (typeAttrib == "BiTangent")
  300. {
  301. Logger::Log() << " * Attribut : " << nameAttrib
  302. << " (BiTangent) \n";
  303. typeID = BITANGENT_ATTRIBUT;
  304. }
  305. else if (typeAttrib == "Normal")
  306. {
  307. Logger::Log() << " * Attribut : " << nameAttrib << " (Normal) \n";
  308. typeID = NORMAL_ATTRIBUT;
  309. }
  310. else if(typeAttrib == "Custom")
  311. {
  312. // TODO: Add Limit number & do verifications
  313. int idNum;
  314. TinyXMLGetAttributeValue<int>(attributNode, "id",&idNum);
  315. Logger::Log() << " * Attribut : " << nameAttrib << " (Custom " << idNum << ") \n";
  316. typeID = CUSTOM_ATTRIBUT + idNum;
  317. }
  318. else
  319. {
  320. throw CException("Unknow attribut : " + typeAttrib);
  321. }
  322. shader->AddAttributBinding(typeID, nameAttrib);
  323. attributNode = attributNode->NextSiblingElement("Attribut");
  324. }
  325. }
  326. void ShadersLoader::LoadShaderTextures(Shader* shader, TiXmlElement *root)
  327. {
  328. TiXmlElement *rootTextures = root->FirstChildElement("Textures");
  329. if (!rootTextures)
  330. {
  331. Logger::Log() << "[INFO] No Textures is available ... \n";
  332. return;
  333. }
  334. TiXmlElement *textureNode = rootTextures->FirstChildElement("Texture");
  335. Logger::Log() << "[INFO] Textures : \n";
  336. while (textureNode)
  337. {
  338. std::string nameAttrib;
  339. std::string typeAttrib;
  340. TinyXMLGetAttributeValue<std::string>(textureNode, "name", &nameAttrib);
  341. TinyXMLGetAttributeValue<std::string>(textureNode, "type", &typeAttrib);
  342. int typeID;
  343. int id;
  344. //TODO: Faire une factory ???
  345. if (typeAttrib == "Diffuse")
  346. {
  347. Logger::Log() << " * Texture : " << nameAttrib << " (Diffuse) \n";
  348. typeID = DIFFUSE_TEXTURE;
  349. }
  350. else if (typeAttrib == "Normal")
  351. {
  352. Logger::Log() << " * Texture : " << nameAttrib << " (Normal) \n";
  353. typeID = NORMAL_TEXTURE;
  354. }
  355. else if (typeAttrib == "Specular")
  356. {
  357. Logger::Log() << " * Texture : " << nameAttrib
  358. << " (Specular) \n";
  359. typeID = SPECULAR_TEXTURE;
  360. }
  361. else if (typeAttrib == "Custom")
  362. {
  363. textureNode->Attribute("id", &id);
  364. Logger::Log() << " * Texture : " << nameAttrib << " (Custom) ["
  365. << id << "]\n";
  366. typeID = CUSTOM_TEXTURE + id;
  367. }
  368. else
  369. {
  370. throw CException("Unknow attribut : " + typeAttrib);
  371. }
  372. shader->AddTextureUnit(typeID, nameAttrib);
  373. textureNode = textureNode->NextSiblingElement("Texture");
  374. }
  375. }
  376. ShaderCompilerConfig ShadersLoader::LoadShaderCompilerConfig(TiXmlElement* root)
  377. {
  378. ShaderCompilerConfig config;
  379. // Define extraction
  380. TiXmlElement *definesNode = root->FirstChildElement("Defines");
  381. if (definesNode)
  382. {
  383. TiXmlElement *defineNode = definesNode->FirstChildElement("Define");
  384. while (defineNode)
  385. {
  386. std::string nameAttrib;
  387. std::string type;
  388. std::string defaultValueAttrib;
  389. TinyXMLGetAttributeValue<std::string>(defineNode, "name", &nameAttrib);
  390. TinyXMLGetAttributeValue<std::string>(defineNode, "type", &type);
  391. TinyXMLGetAttributeValue<std::string>(defineNode, "defaultValue", &defaultValueAttrib);
  392. ShaderCompilerConfig::DefineEntry entry = ShaderCompilerConfig::GetDefineEntry(type, defaultValueAttrib);
  393. config.AddDefine(nameAttrib, entry);
  394. defineNode = defineNode->NextSiblingElement();
  395. }
  396. }
  397. return config;
  398. }
  399. Shader* ShadersLoader::LoadFromFile(const std::string& Filename)
  400. {
  401. TiXmlDocument doc(Filename.c_str());
  402. if (!doc.LoadFile())
  403. {
  404. Logger::Log() << "[ERROR] TinyXML error : " << doc.ErrorDesc() << "\n";
  405. throw CLoadingFailed(Filename, "unable to load xml with TinyXML");
  406. }
  407. // Get the root
  408. TiXmlHandle hdl(&doc);
  409. TiXmlElement *root = hdl.FirstChild("Shader").Element();
  410. // Problem to find the root
  411. if (!root)
  412. {
  413. throw CLoadingFailed(Filename, "unable to find root (Shader)");
  414. }
  415. // Get the shader name and display it
  416. std::string name;
  417. std::string shaderTypeName;
  418. TinyXMLGetAttributeValue<std::string>(root, "name", &name);
  419. TinyXMLGetAttributeValue<std::string>(root, "type", &shaderTypeName);
  420. Logger::Log() << "[INFO] Load shader : " << name << " ( " << shaderTypeName
  421. << " ) ... \n";
  422. ShaderType shaderType;
  423. if (shaderTypeName == "Basic")
  424. shaderType = BASIC_SHADER;
  425. else if (shaderTypeName == "GBuffer")
  426. shaderType = GBUFFER_SHADER;
  427. else
  428. throw CException("unknow shader type");
  429. // Load the shader compiler config
  430. ShaderCompilerConfig config = LoadShaderCompilerConfig(root);
  431. // Get the 2 files name
  432. // * Vertex shader
  433. TiXmlElement *shadername = root->FirstChildElement("VertexShader");
  434. if (!shadername)
  435. {
  436. throw CLoadingFailed(Filename, "unable to find VertexShader (Shader)");
  437. }
  438. std::string vertexShadername = std::string(
  439. shadername->Attribute("filename"));
  440. Logger::Log() << " * Vertex shader : " << vertexShadername << "\n";
  441. // * Fragment shader
  442. shadername = root->FirstChildElement("FragmentShader");
  443. if (!shadername)
  444. {
  445. throw CLoadingFailed(Filename, "unable to find VertexShader (Shader)");
  446. }
  447. std::string fragmentShadername = std::string(
  448. shadername->Attribute("filename"));
  449. Logger::Log() << " * Fragment shader : " << fragmentShadername << "\n";
  450. /*
  451. * Find full path
  452. */
  453. vertexShadername =
  454. CMediaManager::Instance().FindMedia(vertexShadername).Fullname();
  455. fragmentShadername =
  456. CMediaManager::Instance().FindMedia(fragmentShadername).Fullname();
  457. Shader* shader = 0;
  458. shadername = root->FirstChildElement("GeometryShader");
  459. if (shadername != 0)
  460. {
  461. std::string geometryShadername = std::string(
  462. shadername->Attribute("filename"));
  463. Logger::Log() << " * Geometry shader : " << geometryShadername
  464. << "\n";
  465. geometryShadername = CMediaManager::Instance().FindMedia(
  466. geometryShadername).Fullname();
  467. std::string in, out;
  468. TinyXMLGetAttributeValue(shadername, "in", &in);
  469. TinyXMLGetAttributeValue(shadername, "out", &out);
  470. shader = CShaderManager::Instance().loadfromFile(
  471. vertexShadername.c_str(), fragmentShadername.c_str(),
  472. geometryShadername.c_str(), shaderType, config);
  473. shader->SetGeometryShaderParameters(OpenGLEnumFromString(in),
  474. OpenGLEnumFromString(out));
  475. }
  476. else
  477. {
  478. Logger::Log() << " * No Geometry shader\n";
  479. // Shader creation ....
  480. shader = CShaderManager::Instance().loadfromFile(
  481. vertexShadername.c_str(), fragmentShadername.c_str(),
  482. shaderType, config);
  483. }
  484. shader->Link();
  485. // Attrib blinding ...
  486. LoadShaderAttributs(shader, root);
  487. // Textures uniform
  488. LoadShaderTextures(shader, root);
  489. // Matrix uniform
  490. LoadShaderMatrix(shader, root);
  491. // FBO
  492. LoadShaderFBO(shader, root);
  493. // Materials
  494. LoadMaterials(shader, root);
  495. // Update all bindings
  496. // * Warning : Need to relink after
  497. shader->UpdateAll();
  498. return shader;
  499. }
  500. }