| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- #ifndef ANKI_RESOURCE_MATERIAL_H
- #define ANKI_RESOURCE_MATERIAL_H
- #include "anki/resource/MaterialCommon.h"
- #include "anki/resource/Resource.h"
- #include "anki/util/ConstCharPtrHashMap.h"
- #include "anki/util/StringList.h"
- #include "anki/math/Math.h"
- #include "anki/util/Visitor.h"
- #include "anki/util/NonCopyable.h"
- #include "anki/gl/Ogl.h"
- #include <memory>
- namespace anki {
- // Forward
- class ShaderProgram;
- class ShaderProgramUniformVariable;
- class XmlElement;
- class MaterialShaderProgramCreator;
- class ShaderProgramUniformBlock;
- // A few consts
- const U32 MATERIAL_MAX_PASSES = 4;
- const U32 MATERIAL_MAX_LODS = 4;
- /// Material variable base. Its a visitable
- typedef Visitable<F32, Vec2, Vec3, Vec4, Mat3, Mat4, TextureResourcePointer>
- MateriaVariableVisitable;
- // Forward
- template<typename T>
- class MaterialVariableTemplate;
- /// Holds the shader variables. Its a container for shader program variables
- /// that share the same name
- class MaterialVariable: public MateriaVariableVisitable, public NonCopyable
- {
- public:
- typedef MateriaVariableVisitable Base;
- /// Given a pair of pass and level it returns a pointer to a
- /// shader program uniform variable. The pointer may be nullptr
- typedef PassLevelHashMap<const ShaderProgramUniformVariable*>
- PassLevelToShaderProgramUniformVariableHashMap;
- /// @name Constructors & destructor
- /// @{
- MaterialVariable(
- const char* shaderProgVarName,
- PassLevelToShaderProgramHashMap& progs)
- {
- init(shaderProgVarName, progs);
- }
- virtual ~MaterialVariable();
- /// @}
- /// @name Accessors
- /// @{
- template<typename T>
- const T& getValue() const
- {
- ANKI_ASSERT(Base::getVariadicTypeId<T>() == Base::getVisitableTypeId());
- return static_cast<const MaterialVariableTemplate<T>*>(this)->get();
- }
- template<typename T>
- void setValue(const T& x)
- {
- ANKI_ASSERT(Base::getVariadicTypeId<T>() == Base::getVisitableTypeId());
- static_cast<MaterialVariableTemplate<T>*>(this)->set(x);
- }
- /// Given a key return the uniform. If the uniform is not present in the
- /// LOD pass key then returns nullptr
- const ShaderProgramUniformVariable* findShaderProgramUniformVariable(
- const PassLevelKey& key) const
- {
- PassLevelToShaderProgramUniformVariableHashMap::const_iterator it =
- sProgVars.find(key);
- return (it == sProgVars.end()) ? nullptr : it->second;
- }
- /// Get the GL data type of all the shader program variables
- GLenum getGlDataType() const;
- /// Get the name of all the shader program variables
- const std::string& getName() const;
- /// If false then it should be buildin
- virtual Bool hasValue() const = 0;
- /// @}
- private:
- PassLevelToShaderProgramUniformVariableHashMap sProgVars;
- /// Keep one ShaderProgramVariable here for easy access of the common
- /// variable stuff like name or GL data type etc
- const ShaderProgramUniformVariable* oneSProgVar;
- /// Common constructor code
- void init(const char* shaderProgVarName,
- PassLevelToShaderProgramHashMap& shaderProgsArr);
- };
- /// Material variable with data. A complete type
- template<typename Data>
- class MaterialVariableTemplate: public MaterialVariable
- {
- public:
- /// @name Constructors/Destructor
- /// @{
- MaterialVariableTemplate(
- const char* shaderProgVarName,
- PassLevelToShaderProgramHashMap& progs)
- : MaterialVariable(shaderProgVarName, progs)
- {
- setupVisitable(&data);
- }
- ~MaterialVariableTemplate()
- {}
- /// @}
- /// @name Accessors
- /// @{
- const Data& get() const
- {
- ANKI_ASSERT(dataSet == true);
- return data;
- }
- void set(const Data& x)
- {
- data = x;
- dataSet = true;
- }
- /// @}
- Bool hasValue() const
- {
- return dataSet;
- }
- private:
- Data data;
- Bool dataSet = false;
- };
- /// Contains a few properties that other classes may use. For an explanation of
- /// the variables refer to Material class documentation
- class MaterialProperties
- {
- public:
- /// @name Accessors
- /// @{
- uint getRenderingStage() const
- {
- return renderingStage;
- }
- const StringList& getPasses() const
- {
- return passes;
- }
- U32 getLevelsOfDetail() const
- {
- return levelsOfDetail;
- }
- Bool getShadow() const
- {
- return shadow;
- }
- GLenum getBlendingSfactor() const
- {
- return blendingSfactor;
- }
- GLenum getBlendingDfactor() const
- {
- return blendingDfactor;
- }
- Bool getDepthTestingEnabled() const
- {
- return depthTesting;
- }
- Bool getWireframe() const
- {
- return wireframe;
- }
- /// @}
- /// Check if blending is enabled
- Bool isBlendingEnabled() const
- {
- return blendingSfactor != GL_ONE || blendingDfactor != GL_ZERO;
- }
- protected:
- U32 renderingStage = 0;
- StringList passes;
- U32 levelsOfDetail = 1;
- Bool shadow = true;
- GLenum blendingSfactor = GL_ONE; ///< Default GL_ONE
- GLenum blendingDfactor = GL_ZERO; ///< Default GL_ZERO
- Bool depthTesting = true;
- Bool wireframe = false;
- };
- /// Material resource
- ///
- /// Every material keeps info of how to render a RenedrableNode. Using a node
- /// based logic it creates a couple of shader programs dynamically. One for
- /// color passes and one for depth. It also keeps two sets of material
- /// variables. The first is the build in and the second the user defined.
- /// During the renderer's shader setup the buildins will be set automatically,
- /// for the user variables the user needs to have its value in the material
- /// file. Some material variables may be present in both shader programs and
- /// some in only one of them
- ///
- /// Material XML file format:
- /// @code
- /// <material>
- /// <renderingStage>N</renderingStage> (1)
- ///
- /// [<passes>COLOR DEPTH</passes>]
- ///
- /// [<levelsOfDetail>N</levelsOfDetail>]
- ///
- /// [<shadow>0 | 1</shadow>]
- ///
- /// [<blendFunctions>
- /// <sFactor>GL_SOMETHING</sFactor>
- /// <dFactor>GL_SOMETHING</dFactor>
- /// </blendFunctions>]
- ///
- /// [<depthTesting>0 | 1</depthTesting>]
- ///
- /// [<wireframe>0 | 1</wireframe>]
- ///
- /// <shaderProgram>
- /// <shader> (2)
- /// <type>vertex | tc | te | geometry | fragment</type>
- ///
- /// <includes>
- /// <include>path/to/file.glsl</include>
- /// <include>path/to/file2.glsl</include>
- /// </includes>
- ///
- /// [<inputs> (3)
- /// <input>
- /// <name>xx</name>
- /// <type>any glsl type</type>
- /// <value> (4)
- /// [a_series_of_numbers |
- /// path/to/image.tga]
- /// </value>
- /// [<const>0 | 1</const>] (5)
- /// </input>
- /// </inputs>]
- ///
- /// <operations>
- /// <operation>
- /// <id>x</id>
- /// <returnType>any glsl type or void</returnType>
- /// <function>functionName</function>
- /// [<arguments>
- /// <argument>xx</argument>
- /// <argument>yy</argument>
- /// </arguments>]
- /// </operation>
- /// </operations>
- /// </vertexShader>
- ///
- /// <shader>...</shader>
- /// </shaderProgram>
- /// </material>
- /// @endcode
- /// (1): For the moment 0 means MS, 1 BS, 2 IS (aka light)
- /// (2): The order of the shaders is crucial
- /// (3): AKA uniforms
- /// (4): The \<value\> can be left empty for build-in variables
- /// (5): The \<const\> will mark a variable as constant and it cannot be changed
- /// at all. Defauls is 0
- class Material: public MaterialProperties, public NonCopyable
- {
- public:
- typedef PtrVector<MaterialVariable> VarsContainer;
- /// Type for garbage collection
- typedef PtrVector<ShaderProgramResourcePointer> ShaderPrograms;
- Material();
- ~Material();
- /// @name Accessors
- /// @{
- /// Access the base class just for copying in other classes
- const MaterialProperties& getBaseClass() const
- {
- return *this;
- }
- // Variable accessors
- const VarsContainer& getVariables() const
- {
- return vars;
- }
- const ShaderProgramUniformBlock* getCommonUniformBlock() const
- {
- return commonUniformBlock;
- }
- const ShaderPrograms& getShaderPrograms() const
- {
- return progs;
- }
- /// @}
- const ShaderProgram& findShaderProgram(const PassLevelKey& key) const
- {
- return *eSProgs.at(key);
- }
- /// Get by name
- const MaterialVariable* findVariableByName(const char* name) const
- {
- NameToVariableHashMap::const_iterator it = nameToVar.find(name);
- return (it == nameToVar.end()) ? nullptr : it->second;
- }
- /// Load a material file
- void load(const char* filename);
- /// For sorting
- Bool operator<(const Material& b) const
- {
- return hash < b.hash;
- }
- private:
- typedef ConstCharPtrHashMap<MaterialVariable*>::Type
- NameToVariableHashMap;
- std::string fname; ///< filename
- /// All the material variables
- VarsContainer vars;
- NameToVariableHashMap nameToVar;
- /// The most important aspect of materials. These are all the shader
- /// programs per level and per pass. Their number are NP * NL where
- /// NP is the number of passes and NL the number of levels of detail
- ShaderPrograms progs;
- /// For searching
- PassLevelToShaderProgramHashMap eSProgs;
- /// Used for sorting
- std::size_t hash;
- /// One uniform block
- const ShaderProgramUniformBlock* commonUniformBlock;
- /// Parse what is within the @code <material></material> @endcode
- void parseMaterialTag(const XmlElement& el);
- /// Create a unique shader source in chache. If already exists do nothing
- std::string createShaderProgSourceToCache(const std::string& source);
- /// Read all shader programs and pupulate the @a vars and @a nameToVar
- /// containers
- void populateVariables(const MaterialShaderProgramCreator& mspc);
- };
- } // end namespace anki
- #endif
|