2
0

Material.h 9.5 KB

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