Material.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. #ifndef ANKI_RESOURCE_MATERIAL_H
  2. #define ANKI_RESOURCE_MATERIAL_H
  3. #include "anki/resource/MaterialCommon.h"
  4. #include "anki/resource/Resource.h"
  5. #include "anki/util/ConstCharPtrHashMap.h"
  6. #include "anki/util/StringList.h"
  7. #include "anki/math/Math.h"
  8. #include "anki/util/Visitor.h"
  9. #include "anki/util/NonCopyable.h"
  10. #include "anki/gl/Ogl.h"
  11. #include <memory>
  12. namespace anki {
  13. // Forward
  14. class ShaderProgram;
  15. class ShaderProgramUniformVariable;
  16. class XmlElement;
  17. class MaterialShaderProgramCreator;
  18. class ShaderProgramUniformBlock;
  19. // A few consts
  20. const U32 MATERIAL_MAX_PASSES = 4;
  21. const U32 MATERIAL_MAX_LODS = 4;
  22. /// Material variable base. Its a visitable
  23. typedef Visitable<F32, Vec2, Vec3, Vec4, Mat3, Mat4, TextureResourcePointer>
  24. MateriaVariableVisitable;
  25. // Forward
  26. template<typename T>
  27. class MaterialVariableTemplate;
  28. /// Holds the shader variables. Its a container for shader program variables
  29. /// that share the same name
  30. class MaterialVariable: public MateriaVariableVisitable, public NonCopyable
  31. {
  32. public:
  33. typedef MateriaVariableVisitable Base;
  34. /// Given a pair of pass and level it returns a pointer to a
  35. /// shader program uniform variable. The pointer may be nullptr
  36. typedef PassLevelHashMap<const ShaderProgramUniformVariable*>
  37. PassLevelToShaderProgramUniformVariableHashMap;
  38. /// @name Constructors & destructor
  39. /// @{
  40. MaterialVariable(
  41. const char* shaderProgVarName,
  42. PassLevelToShaderProgramHashMap& progs)
  43. {
  44. init(shaderProgVarName, progs);
  45. }
  46. virtual ~MaterialVariable();
  47. /// @}
  48. /// @name Accessors
  49. /// @{
  50. template<typename T>
  51. const T& getValue() const
  52. {
  53. ANKI_ASSERT(Base::getVariadicTypeId<T>() == Base::getVisitableTypeId());
  54. return static_cast<const MaterialVariableTemplate<T>*>(this)->get();
  55. }
  56. template<typename T>
  57. void setValue(const T& x)
  58. {
  59. ANKI_ASSERT(Base::getVariadicTypeId<T>() == Base::getVisitableTypeId());
  60. static_cast<MaterialVariableTemplate<T>*>(this)->set(x);
  61. }
  62. /// Given a key return the uniform. If the uniform is not present in the
  63. /// LOD pass key then returns nullptr
  64. const ShaderProgramUniformVariable* findShaderProgramUniformVariable(
  65. const PassLevelKey& key) const
  66. {
  67. PassLevelToShaderProgramUniformVariableHashMap::const_iterator it =
  68. sProgVars.find(key);
  69. return (it == sProgVars.end()) ? nullptr : it->second;
  70. }
  71. /// Get the GL data type of all the shader program variables
  72. GLenum getGlDataType() const;
  73. /// Get the name of all the shader program variables
  74. const std::string& getName() const;
  75. /// If false then it should be buildin
  76. virtual Bool hasValue() const = 0;
  77. /// @}
  78. private:
  79. PassLevelToShaderProgramUniformVariableHashMap sProgVars;
  80. /// Keep one ShaderProgramVariable here for easy access of the common
  81. /// variable stuff like name or GL data type etc
  82. const ShaderProgramUniformVariable* oneSProgVar;
  83. /// Common constructor code
  84. void init(const char* shaderProgVarName,
  85. PassLevelToShaderProgramHashMap& shaderProgsArr);
  86. };
  87. /// Material variable with data. A complete type
  88. template<typename Data>
  89. class MaterialVariableTemplate: public MaterialVariable
  90. {
  91. public:
  92. /// @name Constructors/Destructor
  93. /// @{
  94. MaterialVariableTemplate(
  95. const char* shaderProgVarName,
  96. PassLevelToShaderProgramHashMap& progs)
  97. : MaterialVariable(shaderProgVarName, progs)
  98. {
  99. setupVisitable(&data);
  100. }
  101. ~MaterialVariableTemplate()
  102. {}
  103. /// @}
  104. /// @name Accessors
  105. /// @{
  106. const Data& get() const
  107. {
  108. ANKI_ASSERT(dataSet == true);
  109. return data;
  110. }
  111. void set(const Data& x)
  112. {
  113. data = x;
  114. dataSet = true;
  115. }
  116. /// @}
  117. Bool hasValue() const
  118. {
  119. return dataSet;
  120. }
  121. private:
  122. Data data;
  123. Bool dataSet = false;
  124. };
  125. /// Contains a few properties that other classes may use. For an explanation of
  126. /// the variables refer to Material class documentation
  127. class MaterialProperties
  128. {
  129. public:
  130. /// @name Accessors
  131. /// @{
  132. uint getRenderingStage() const
  133. {
  134. return renderingStage;
  135. }
  136. const StringList& getPasses() const
  137. {
  138. return passes;
  139. }
  140. U32 getLevelsOfDetail() const
  141. {
  142. return levelsOfDetail;
  143. }
  144. Bool getShadow() const
  145. {
  146. return shadow;
  147. }
  148. GLenum getBlendingSfactor() const
  149. {
  150. return blendingSfactor;
  151. }
  152. GLenum getBlendingDfactor() const
  153. {
  154. return blendingDfactor;
  155. }
  156. Bool getDepthTestingEnabled() const
  157. {
  158. return depthTesting;
  159. }
  160. Bool getWireframe() const
  161. {
  162. return wireframe;
  163. }
  164. /// @}
  165. /// Check if blending is enabled
  166. Bool isBlendingEnabled() const
  167. {
  168. return blendingSfactor != GL_ONE || blendingDfactor != GL_ZERO;
  169. }
  170. protected:
  171. U32 renderingStage = 0;
  172. StringList passes;
  173. U32 levelsOfDetail = 1;
  174. Bool shadow = true;
  175. GLenum blendingSfactor = GL_ONE; ///< Default GL_ONE
  176. GLenum blendingDfactor = GL_ZERO; ///< Default GL_ZERO
  177. Bool depthTesting = true;
  178. Bool wireframe = false;
  179. };
  180. /// Material resource
  181. ///
  182. /// Every material keeps info of how to render a RenedrableNode. Using a node
  183. /// based logic it creates a couple of shader programs dynamically. One for
  184. /// color passes and one for depth. It also keeps two sets of material
  185. /// variables. The first is the build in and the second the user defined.
  186. /// During the renderer's shader setup the buildins will be set automatically,
  187. /// for the user variables the user needs to have its value in the material
  188. /// file. Some material variables may be present in both shader programs and
  189. /// some in only one of them
  190. ///
  191. /// Material XML file format:
  192. /// @code
  193. /// <material>
  194. /// <renderingStage>N</renderingStage> (1)
  195. ///
  196. /// [<passes>COLOR DEPTH</passes>]
  197. ///
  198. /// [<levelsOfDetail>N</levelsOfDetail>]
  199. ///
  200. /// [<shadow>0 | 1</shadow>]
  201. ///
  202. /// [<blendFunctions>
  203. /// <sFactor>GL_SOMETHING</sFactor>
  204. /// <dFactor>GL_SOMETHING</dFactor>
  205. /// </blendFunctions>]
  206. ///
  207. /// [<depthTesting>0 | 1</depthTesting>]
  208. ///
  209. /// [<wireframe>0 | 1</wireframe>]
  210. ///
  211. /// <shaderProgram>
  212. /// <shader> (2)
  213. /// <type>vertex | tc | te | geometry | fragment</type>
  214. ///
  215. /// <includes>
  216. /// <include>path/to/file.glsl</include>
  217. /// <include>path/to/file2.glsl</include>
  218. /// </includes>
  219. ///
  220. /// [<inputs> (3)
  221. /// <input>
  222. /// <name>xx</name>
  223. /// <type>any glsl type</type>
  224. /// <value> (4)
  225. /// [a_series_of_numbers |
  226. /// path/to/image.tga]
  227. /// </value>
  228. /// [<const>0 | 1</const>] (5)
  229. /// </input>
  230. /// </inputs>]
  231. ///
  232. /// <operations>
  233. /// <operation>
  234. /// <id>x</id>
  235. /// <returnType>any glsl type or void</returnType>
  236. /// <function>functionName</function>
  237. /// [<arguments>
  238. /// <argument>xx</argument>
  239. /// <argument>yy</argument>
  240. /// </arguments>]
  241. /// </operation>
  242. /// </operations>
  243. /// </vertexShader>
  244. ///
  245. /// <shader>...</shader>
  246. /// </shaderProgram>
  247. /// </material>
  248. /// @endcode
  249. /// (1): For the moment 0 means MS, 1 BS, 2 IS (aka light)
  250. /// (2): The order of the shaders is crucial
  251. /// (3): AKA uniforms
  252. /// (4): The \<value\> can be left empty for build-in variables
  253. /// (5): The \<const\> will mark a variable as constant and it cannot be changed
  254. /// at all. Defauls is 0
  255. class Material: public MaterialProperties, public NonCopyable
  256. {
  257. public:
  258. typedef PtrVector<MaterialVariable> VarsContainer;
  259. /// Type for garbage collection
  260. typedef PtrVector<ShaderProgramResourcePointer> ShaderPrograms;
  261. Material();
  262. ~Material();
  263. /// @name Accessors
  264. /// @{
  265. /// Access the base class just for copying in other classes
  266. const MaterialProperties& getBaseClass() const
  267. {
  268. return *this;
  269. }
  270. // Variable accessors
  271. const VarsContainer& getVariables() const
  272. {
  273. return vars;
  274. }
  275. const ShaderProgramUniformBlock* getCommonUniformBlock() const
  276. {
  277. return commonUniformBlock;
  278. }
  279. const ShaderPrograms& getShaderPrograms() const
  280. {
  281. return progs;
  282. }
  283. /// @}
  284. const ShaderProgram& findShaderProgram(const PassLevelKey& key) const
  285. {
  286. return *eSProgs.at(key);
  287. }
  288. /// Get by name
  289. const MaterialVariable* findVariableByName(const char* name) const
  290. {
  291. NameToVariableHashMap::const_iterator it = nameToVar.find(name);
  292. return (it == nameToVar.end()) ? nullptr : it->second;
  293. }
  294. /// Load a material file
  295. void load(const char* filename);
  296. /// For sorting
  297. Bool operator<(const Material& b) const
  298. {
  299. return hash < b.hash;
  300. }
  301. private:
  302. typedef ConstCharPtrHashMap<MaterialVariable*>::Type
  303. NameToVariableHashMap;
  304. std::string fname; ///< filename
  305. /// All the material variables
  306. VarsContainer vars;
  307. NameToVariableHashMap nameToVar;
  308. /// The most important aspect of materials. These are all the shader
  309. /// programs per level and per pass. Their number are NP * NL where
  310. /// NP is the number of passes and NL the number of levels of detail
  311. ShaderPrograms progs;
  312. /// For searching
  313. PassLevelToShaderProgramHashMap eSProgs;
  314. /// Used for sorting
  315. std::size_t hash;
  316. /// One uniform block
  317. const ShaderProgramUniformBlock* commonUniformBlock;
  318. /// Parse what is within the @code <material></material> @endcode
  319. void parseMaterialTag(const XmlElement& el);
  320. /// Create a unique shader source in chache. If already exists do nothing
  321. std::string createShaderProgSourceToCache(const std::string& source);
  322. /// Read all shader programs and pupulate the @a vars and @a nameToVar
  323. /// containers
  324. void populateVariables(const MaterialShaderProgramCreator& mspc);
  325. };
  326. } // end namespace anki
  327. #endif