1 #ifndef MSP_GL_MATERIAL_H_
2 #define MSP_GL_MATERIAL_H_
4 #include <msp/datafile/collection.h>
5 #include <msp/datafile/dynamicobjectloader.h>
6 #include <msp/datafile/objectloader.h>
8 #include "programdata.h"
17 Base class for materials. Subclasses provide different shading models.
22 class Loader: public DataFile::CollectionObjectLoader<Material>
25 Loader(Material &, Collection &);
27 virtual void init_actions();
30 void alpha_cutoff(float);
31 void sampler(const std::string &);
39 const Texture *texture;
41 Property(): value(T()), texture(0) { }
45 class PropertyLoader: public DataFile::DerivedObjectLoader<Material, Loader>
48 PropertyLoader(C &m, Collection &c): DerivedObjectLoader<Material, Loader>(m, c) { }
50 void add_property(const std::string &, void (C::*)(float), void (C::*)(const Texture *));
51 void add_property(const std::string &, void (C::*)(const Color &), void (C::*)(const Texture *), bool);
52 void add_property(const std::string &, void (C::*)(const Texture *));
54 void property_value_scalar(void (C::*)(float), float);
55 void property_value_rgb(void (C::*)(const Color &), float, float, float);
56 void property_value_rgba(void (C::*)(const Color &), float, float, float, float);
57 void property_value_srgb(void (C::*)(const Color &), float, float, float);
58 void property_value_srgb_alpha(void (C::*)(const Color &), float, float, float, float);
59 void property_texture(void (C::*)(const Texture *), const std::string &);
63 class GenericLoader: public DataFile::DynamicObjectLoader<Material>
65 friend class Material;
68 GenericLoader(Collection &c): DynamicObjectLoader<Material>(&c) { }
71 virtual const TypeRegistry &get_type_registry() const { return get_material_registry(); }
75 const Sampler *sampler = 0;
76 float alpha_cutoff = 0.0f;
81 virtual ~Material() = default;
83 /** Returns a shader appropriate for this material. The same shader is
84 returned for materials with the same set of features. Additional
85 specialization values can be passed in to customize the shader. */
86 virtual const Program *create_compatible_shader(const std::map<std::string, int> & = std::map<std::string, int>()) const;
88 virtual void fill_program_info(std::string &, std::map<std::string, int> &) const = 0;
91 /** Returns the uniform values for the material. */
92 const ProgramData &get_shader_data() const { return shdata; }
94 /** Returns texture tags used by the material. The returned array is
95 terminated by an empty tag. */
96 virtual const Tag *get_texture_tags() const = 0;
98 virtual const Texture *get_texture(Tag) const = 0;
99 virtual const Sampler *get_sampler(Tag) const { return sampler; }
101 void set_alpha_cutoff(float a);
102 float get_alpha_cutoff() const { return alpha_cutoff; }
104 void set_debug_name(const std::string &);
107 static void register_type(const std::string &);
109 static GenericLoader::TypeRegistry &get_material_registry();
113 void Material::register_type(const std::string &kw)
115 get_material_registry().register_type<T>(kw);
120 void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_value)(float), void (C::*set_texture)(const Texture *))
122 add(kw, &PropertyLoader<C>::property_value_scalar, set_value);
124 add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
128 void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_value)(const Color &), void (C::*set_texture)(const Texture *), bool allow_alpha)
130 add(kw, &PropertyLoader<C>::property_value_rgb, set_value);
131 add(kw+"_srgb", &PropertyLoader<C>::property_value_srgb, set_value);
134 add(kw, &PropertyLoader<C>::property_value_rgba, set_value);
135 add(kw+"_srgb", &PropertyLoader<C>::property_value_srgb_alpha, set_value);
138 add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
142 void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_texture)(const Texture *))
144 add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
148 void Material::PropertyLoader<C>::property_value_scalar(void (C::*set_value)(float), float value)
150 (static_cast<C &>(obj).*set_value)(value);
154 void Material::PropertyLoader<C>::property_value_rgb(void (C::*set_value)(const Color &), float r, float g, float b)
156 (static_cast<C &>(obj).*set_value)(Color(r, g, b));
160 void Material::PropertyLoader<C>::property_value_rgba(void (C::*set_value)(const Color &), float r, float g, float b, float a)
162 (static_cast<C &>(obj).*set_value)(Color(r, g, b, a));
166 void Material::PropertyLoader<C>::property_value_srgb(void (C::*set_value)(const Color &), float r, float g, float b)
168 (static_cast<C &>(obj).*set_value)(Color(r, g, b).to_linear());
172 void Material::PropertyLoader<C>::property_value_srgb_alpha(void (C::*set_value)(const Color &), float r, float g, float b, float a)
174 (static_cast<C &>(obj).*set_value)(Color(r, g, b, a).to_linear());
178 void Material::PropertyLoader<C>::property_texture(void (C::*set_texture)(const Texture *), const std::string &name)
180 /* The static_cast around get_collection is needed because otherwise Android
181 SDK's g++ 4.9 fails to parse get<Texture> as a template function call */
182 (static_cast<C &>(obj).*set_texture)(&static_cast<Collection &>(get_collection()).get<Texture>(name));