]> git.tdb.fi Git - libs/gl.git/blob - source/materials/material.h
77e7d44ec29bdedf174d393d5f505aba0cfeb18f
[libs/gl.git] / source / materials / material.h
1 #ifndef MSP_GL_MATERIAL_H_
2 #define MSP_GL_MATERIAL_H_
3
4 #include <msp/datafile/collection.h>
5 #include <msp/datafile/dynamicobjectloader.h>
6 #include <msp/datafile/objectloader.h>
7 #include "color.h"
8 #include "programdata.h"
9 #include "texture.h"
10
11 namespace Msp {
12 namespace GL {
13
14 class Sampler;
15
16 class Material
17 {
18 private:
19         class Loader: public DataFile::CollectionObjectLoader<Material>
20         {
21         protected:
22                 Loader(Material &, Collection &);
23
24                 virtual void init_actions();
25
26         private:
27                 void sampler(const std::string &);
28         };
29
30 protected:
31         template<typename T>
32         struct Property
33         {
34                 T value;
35                 const Texture *texture;
36
37                 Property(): value(T()), texture(0) { }
38         };
39
40         template<typename C>
41         class PropertyLoader: public DataFile::DerivedObjectLoader<Material, Loader>
42         {
43         protected:
44                 PropertyLoader(C &m, Collection &c): DerivedObjectLoader<Material, Loader>(m, c) { }
45
46                 void add_property(const std::string &, void (C::*)(float), void (C::*)(const Texture *));
47                 void add_property(const std::string &, void (C::*)(const Color &), void (C::*)(const Texture *), bool);
48                 void add_property(const std::string &, void (C::*)(const Texture *));
49
50                 void property_value_scalar(void (C::*)(float), float);
51                 void property_value_rgb(void (C::*)(const Color &), float, float, float);
52                 void property_value_rgba(void (C::*)(const Color &), float, float, float, float);
53                 void property_value_srgb(void (C::*)(const Color &), float, float, float);
54                 void property_value_srgb_alpha(void (C::*)(const Color &), float, float, float, float);
55                 void property_texture(void (C::*)(const Texture *), const std::string &);
56         };
57
58 public:
59         class GenericLoader: public DataFile::DynamicObjectLoader<Material>
60         {
61                 friend class Material;
62
63         public:
64                 GenericLoader(Collection &c): DynamicObjectLoader<Material>(&c) { }
65
66         protected:
67                 virtual const TypeRegistry &get_type_registry() const { return get_material_registry(); }
68         };
69
70 protected:
71         const Sampler *sampler;
72         ProgramData shdata;
73
74         Material(): sampler(0) { }
75 public:
76         virtual ~Material() { }
77
78         virtual const Program *create_compatible_shader(const std::map<std::string, int> & = std::map<std::string, int>()) const;
79 protected:
80         virtual void fill_program_info(std::string &, std::map<std::string, int> &) const = 0;
81
82 public:
83         /** Returns the uniforms for the material. */
84         const ProgramData &get_shader_data() const { return shdata; }
85
86         virtual const Tag *get_texture_tags() const = 0;
87         virtual const Texture *get_texture(Tag) const = 0;
88         virtual const Sampler *get_sampler(Tag) const { return sampler; }
89
90         void set_debug_name(const std::string &);
91
92         template<typename T>
93         static void register_type(const std::string &);
94 private:
95         static GenericLoader::TypeRegistry &get_material_registry();
96 };
97
98 template<typename T>
99 void Material::register_type(const std::string &kw)
100 {
101         get_material_registry().register_type<T>(kw);
102 }
103
104
105 template<typename C>
106 void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_value)(float), void (C::*set_texture)(const Texture *))
107 {
108         add(kw, &PropertyLoader<C>::property_value_scalar, set_value);
109         if(set_texture)
110                 add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
111 }
112
113 template<typename C>
114 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)
115 {
116         add(kw, &PropertyLoader<C>::property_value_rgb, set_value);
117         add(kw+"_srgb", &PropertyLoader<C>::property_value_srgb, set_value);
118         if(allow_alpha)
119         {
120                 add(kw, &PropertyLoader<C>::property_value_rgba, set_value);
121                 add(kw+"_srgb", &PropertyLoader<C>::property_value_srgb_alpha, set_value);
122         }
123         if(set_texture)
124                 add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
125 }
126
127 template<typename C>
128 void Material::PropertyLoader<C>::add_property(const std::string &kw, void (C::*set_texture)(const Texture *))
129 {
130         add(kw+"_map", &PropertyLoader<C>::property_texture, set_texture);
131 }
132
133 template<typename C>
134 void Material::PropertyLoader<C>::property_value_scalar(void (C::*set_value)(float), float value)
135 {
136         (static_cast<C &>(obj).*set_value)(value);
137 }
138
139 template<typename C>
140 void Material::PropertyLoader<C>::property_value_rgb(void (C::*set_value)(const Color &), float r, float g, float b)
141 {
142         (static_cast<C &>(obj).*set_value)(Color(r, g, b));
143 }
144
145 template<typename C>
146 void Material::PropertyLoader<C>::property_value_rgba(void (C::*set_value)(const Color &), float r, float g, float b, float a)
147 {
148         (static_cast<C &>(obj).*set_value)(Color(r, g, b, a));
149 }
150
151 template<typename C>
152 void Material::PropertyLoader<C>::property_value_srgb(void (C::*set_value)(const Color &), float r, float g, float b)
153 {
154         (static_cast<C &>(obj).*set_value)(Color(r, g, b).to_linear());
155 }
156
157 template<typename C>
158 void Material::PropertyLoader<C>::property_value_srgb_alpha(void (C::*set_value)(const Color &), float r, float g, float b, float a)
159 {
160         (static_cast<C &>(obj).*set_value)(Color(r, g, b, a).to_linear());
161 }
162
163 template<typename C>
164 void Material::PropertyLoader<C>::property_texture(void (C::*set_texture)(const Texture *), const std::string &name)
165 {
166         /* The static_cast around get_collection is needed because otherwise Android
167         SDK's g++ 4.9 fails to parse get<Texture> as a template function call */
168         (static_cast<C &>(obj).*set_texture)(&static_cast<Collection &>(get_collection()).get<Texture>(name));
169 }
170
171 } // namespace GL
172 } // namespace Msp
173
174 #endif